Metriques d'utilisation des outils

Les metriques montrent a quelle frequence les agents appellent des tools.
Sur cette page
  1. Idee en 30 secondes
  2. Probleme principal
  3. Comment ca fonctionne
  4. Metriques production typiques sur les tools
  5. Comment lire la couche outils
  6. Quand l'utiliser
  7. Exemple d'implementation
  8. Investigation
  9. Erreurs typiques
  10. Il y a un volume global d'appels, mais pas de detail par tool
  11. Les appels repetes ne sont pas suivis
  12. Pas de p95 latency par outil
  13. Labels a forte cardinalite
  14. Pas d'alertes sur la couche outils
  15. Auto-verification
  16. FAQ
  17. Pages liees

Idee en 30 secondes

Les tool usage metrics montrent non seulement si l'agent fonctionne, mais aussi comment il utilise les outils et ou la couche outils casse.

Elles aident a voir quels outils sont les plus appeles, ou la latency augmente, et ou commencent les appels repetes ou en erreur.

Sans ces metriques, il est difficile de detecter a temps la surcharge de la couche outils et la hausse des couts.

Probleme principal

Les metriques globales de run ne montrent pas ce qui se passe exactement au niveau des outils.

Deux runs peuvent avoir une latency globale similaire, mais dans un cas le probleme vient d'un search lent, dans l'autre d'appels fetch repetes. Sans metriques outils, c'est difficile a voir avant un incident.

Ensuite, on voit comment lire ces signaux et trouver les problemes.

En production, cela ressemble souvent a :

  • un outil devient discretement un hot spot ;
  • les retries augmentent, mais la cause reste floue ;
  • une partie des runs depense trop d'etapes sur les outils ;
  • l'equipe voit le probleme seulement quand error rate ou budget monte.

C'est pourquoi la couche outils doit etre surveillee a part, et pas seulement via les metriques globales de run.

Comment ca fonctionne

Les tool usage metrics sont construites autour des evenements tool_call et tool_result.

Les tool metrics se divisent en :

  • infra metrics (tool_latency_p95, tool_error_rate) ;
  • behavior metrics (repeated_tool_calls, tool_calls_per_run, unique_tools_per_run).

Ces metriques repondent a "comment la couche outils se comporte dans le temps". Les logs et le tracing restent necessaires pour expliquer un run probleme precis.

Les retries se produisent generalement au niveau runtime, pas au niveau du code : l'agent recoit une erreur d'outil comme observation et essaye a nouveau. Les retries ne sont pas juste des appels repetes, mais un signal que l'agent tente de s'adapter aux erreurs d'outils.

Metriques production typiques sur les tools

MetriqueCe qu'elle montrePourquoi elle est utile
tool_calls_totalnombre total d'appels toolscontrole de charge de la couche outils
tool_calls_per_runnombre de tool calls par rundetection des appels excessifs ou cycliques
unique_tools_per_runnombre d'outils differents utilises par runevaluation de la complexite du workflow
tool_error_ratepart des tool calls en erreurdetection precoce des outils instables
tool_latency_p50 / p95latency typique et latency de queue des toolslocalisation des dependances lentes
repeated_tool_callsappels repetant le meme tool avec les memes argsdetection du spam d'outils
tool_cost_per_runcout estime des tools dans un runcontrole budget et detection d'outils couteux

Pour que les metriques soient vraiment utiles, elles sont generalement segmentees par tool, release et, si besoin, model.

Important : ne pas ajouter de champs a forte cardinalite (run_id, request_id, args_hash) dans les labels, sinon le stockage metriques se surcharge vite.

Comment lire la couche outils

Ce qui est appele -> comment l'agent se comporte -> ce qui evolue dans le temps. Ce sont trois niveaux a regarder ensemble.

Il faut lire les tendances dans le temps et les differences entre releases, pas des valeurs isolees.

Voici les combinaisons de signaux a surveiller :

  • tool_error_rate ↑ + repeated_tool_calls ↑ -> tool instable, l'agent retry
  • tool_latency_p95 ↑ + tool_cost_per_run ↑ -> degradation d'un outil couteux
  • tool_calls_per_run ↑ + unique_tools_per_run ↑ -> complexite excessive du workflow

Quand l'utiliser

Un ensemble complet de tool-metrics n'est pas toujours necessaire.

Pour un agent simple avec 1-2 outils, tool_calls_total et tool_error_rate peuvent parfois suffire.

Mais des tool usage metrics detaillees deviennent critiques quand :

  • l'agent utilise activement des API externes ou une BD ;
  • des retries arrivent frequemment ;
  • il faut controler les couts lies aux outils ;
  • il faut detecter le tool spam avant impact utilisateur.

Exemple d'implementation

Ci-dessous un exemple simplifie d'instrumentation des tool usage metrics en style Prometheus. L'exemple montre le controle de base : volume d'appels, latency, classes d'erreurs, repetitions et charge outils par run.

PYTHON
import hashlib
import json
import time
from prometheus_client import Counter, Histogram

TOOL_CALL_TOTAL = Counter(
    "agent_tool_call_total",
    "Total tool calls",
    ["tool", "status", "release"],
)

TOOL_ERROR_TOTAL = Counter(
    "agent_tool_error_total",
    "Total tool errors by class",
    ["tool", "error_class", "release"],
)

TOOL_LATENCY_MS = Histogram(
    "agent_tool_latency_ms",
    "Tool latency in milliseconds",
    ["tool", "release"],
    buckets=(20, 50, 100, 250, 500, 1000, 2000, 5000),
)

TOOL_CALLS_PER_RUN = Histogram(
    "agent_tool_calls_per_run",
    "Number of tool calls per run",
    ["release"],
    buckets=(0, 1, 2, 4, 8, 12, 16, 24, 32),
)

UNIQUE_TOOLS_PER_RUN = Histogram(
    "agent_unique_tools_per_run",
    "Number of unique tools used in run",
    ["release"],
    buckets=(0, 1, 2, 3, 4, 6, 8, 12),
)

REPEATED_TOOL_CALL_TOTAL = Counter(
    "agent_repeated_tool_call_total",
    "Repeated tool calls with same tool+args signature",
    ["tool", "release"],
)

TOOL_COST_USD_TOTAL = Counter(
    "agent_tool_cost_usd_total",
    "Estimated total tool cost in USD",
    ["tool", "release"],
)

STEP_ERROR_TOTAL = Counter(
    "agent_step_error_total",
    "Total non-tool step errors by type and class",
    ["step_type", "error_class", "release"],
)


def stable_hash(value):
    # default=str donne une compatibilite de base ;
    # dans les systemes critiques, une serialisation explicite est preferable (ex. ISO 8601)
    payload = json.dumps(value, sort_keys=True, ensure_ascii=False, default=str).encode("utf-8")
    return hashlib.sha256(payload).hexdigest()


def run_agent(agent, task, release="2026-03-21"):
    tool_calls = 0
    unique_tools = set()
    seen_signatures = set()

    try:
        for step in agent.iter(task):
            step_type = step.type
            result = None

            if step_type != "tool_call":
                try:
                    result = step.execute()
                except Exception as error:
                    STEP_ERROR_TOTAL.labels(
                        step_type=step_type,
                        error_class=type(error).__name__,
                        release=release,
                    ).inc()
                    raise

                if result and result.is_final:
                    break
                continue

            tool_name = getattr(step, "tool_name", "unknown")
            args = getattr(step, "args", {})

            tool_calls += 1
            unique_tools.add(tool_name)

            signature = (tool_name, stable_hash(args))
            if signature in seen_signatures:
                REPEATED_TOOL_CALL_TOTAL.labels(tool=tool_name, release=release).inc()
            else:
                seen_signatures.add(signature)

            started_at = time.time()
            try:
                result = step.execute()
                TOOL_CALL_TOTAL.labels(tool=tool_name, status="ok", release=release).inc()
                cost_usd = getattr(result, "cost_usd", None)
                if cost_usd:
                    TOOL_COST_USD_TOTAL.labels(tool=tool_name, release=release).inc(cost_usd)
            except Exception as error:
                TOOL_CALL_TOTAL.labels(tool=tool_name, status="error", release=release).inc()
                TOOL_ERROR_TOTAL.labels(
                    tool=tool_name,
                    error_class=type(error).__name__,
                    release=release,
                ).inc()
                # Cet exemple fait raise.
                # Dans les agents reels, l'erreur est souvent passee au LLM comme observation pour retry.
                raise
            finally:
                TOOL_LATENCY_MS.labels(tool=tool_name, release=release).observe(
                    (time.time() - started_at) * 1000
                )

            if result and result.is_final:
                break
    finally:
        TOOL_CALLS_PER_RUN.labels(release=release).observe(tool_calls)
        UNIQUE_TOOLS_PER_RUN.labels(release=release).observe(len(unique_tools))

# tool_cost_per_run est generalement calcule au niveau dashboard :
# sum(agent_tool_cost_usd_total) / run_count

Voici a quoi ces metriques peuvent ressembler ensemble dans un dashboard reel :

Toolcalls/minerror_ratep95 latencyStatut
search_docs3206.8%1.9scritical: alert
fetch_url1801.4%680mswarning: p95 en hausse
db_lookup950.3%120msok

Pour error_class, il vaut mieux utiliser un dictionnaire de valeurs normalisees pour eviter une cardinalite inutile.

Investigation

Quand une alerte se declenche :

  1. trouver l'outil anormal via les metriques ;
  2. regarder les runs concrets dans le tracing ;
  3. verifier arguments et reponses dans les logs ;
  4. identifier la root cause (tool, logique agent, ou API externe).

Erreurs typiques

Meme si les tool metrics sont deja en place, elles ne fonctionnent souvent pas comme attendu a cause des erreurs ci-dessous.

Il y a un volume global d'appels, mais pas de detail par tool

tool_calls_total sans detail par outil aide tres peu en incident. Dans ce cas, il est difficile de trouver vite la source d'un echec d'outil.

Les appels repetes ne sont pas suivis

Sans repeated_tool_calls, il est difficile de voir que l'agent appelle le meme tool avec les memes args. Cela masque souvent la phase precoce de spam d'outils.

Pas de p95 latency par outil

Le systeme peut sembler stable alors qu'une partie des utilisateurs attend deja 5+ secondes. Pour la couche outils, le minimum est p50 et p95.

Labels a forte cardinalite

Ajouter run_id, request_id ou args_hash dans les labels surcharge vite le backend metriques. Mieux vaut garder ces donnees dans les logs, pas dans les labels.

Pas d'alertes sur la couche outils

Sans alertes, les metriques restent une telemetrie passive. On peut alors rater les premiers signaux d'explosion budgetaire due a des appels excessifs d'API externes.

Auto-verification

Ci-dessous une checklist courte des tool usage metrics de base avant release.

Progression: 0/9

⚠ L'observability de base manque

Le système sera difficile à déboguer en production. Commencez par run_id, structured logs et tracing des tool calls.

FAQ

Q : En quoi les tool usage metrics different des metriques globales d'agent ?
R : Les metriques globales montrent l'etat du systeme dans son ensemble. Les tool usage metrics montrent ce qui se passe precisement au niveau outils.

Q : Quel minimum de tool-metrics faut-il au demarrage ?
R : Commence par tool_calls_total, tool_error_rate, tool_latency_p95 et tool_calls_per_run.

Q : Faut-il ajouter args_hash dans les labels ?
R : Non. Cela cree presque toujours une forte cardinalite. Pour ces donnees, mieux vaut des logs structures.

Q : Comment separer un echec ponctuel d'un probleme systemique de couche outils ?
R : Verifie si le probleme se repete pour un outil donne sur plusieurs runs et releases. Si les memes signaux (error_class, latency, repeated_tool_calls) reviennent, c'est systemique.

Pages liees

Suite du sujet :

⏱️ 8 min de lectureMis à jour 22 mars 2026Difficulté: ★★★
Intégré : contrôle en productionOnceOnly
Ajoutez des garde-fous aux agents tool-calling
Livrez ce pattern avec de la gouvernance :
  • Budgets (steps / plafonds de coût)
  • Permissions outils (allowlist / blocklist)
  • Kill switch & arrêt incident
  • Idempotence & déduplication
  • Audit logs & traçabilité
Mention intégrée : OnceOnly est une couche de contrôle pour des systèmes d’agents en prod.

Auteur

Nick — ingénieur qui construit une infrastructure pour des agents IA en production.

Focus : patterns d’agents, modes de défaillance, contrôle du runtime et fiabilité des systèmes.

🔗 GitHub: https://github.com/mykolademyanov


Note éditoriale

Cette documentation est assistée par l’IA, avec une responsabilité éditoriale humaine pour l’exactitude, la clarté et la pertinence en production.

Le contenu s’appuie sur des défaillances réelles, des post-mortems et des incidents opérationnels dans des systèmes d’agents IA déployés.