Idee en 30 secondes
Le latency monitoring pour les agents IA montre ou le systeme ralentit : dans les etapes LLM, les tools, les files d'attente ou les iterations repetees.
Sans cela, il est difficile de comprendre pourquoi les utilisateurs attendent plus longtemps, meme quand un run se termine formellement avec succes.
Probleme principal
Un run peut se terminer correctement, mais rester trop lent pour la production.
Deux requetes avec la meme reponse peuvent avoir une latency differente : a cause d'une chaine de reasoning plus longue, d'un tool lent ou de retries. Sans latency monitoring, cela se voit souvent seulement apres les plaintes utilisateurs.
Voyons ensuite comment lire ces signaux et trouver ce qui ralentit exactement un run.
En production, cela ressemble souvent a :
- la latency moyenne semble normale, mais p95 monte deja ;
- un tool devient discretement un bottleneck ;
- les retries ajoutent des secondes sans hausse visible du trafic ;
- l'equipe voit le probleme seulement apres panne partielle.
C'est pourquoi la latency-layer doit etre surveillee separement, et pas seulement via des metriques globales de run.
Comment ca fonctionne
Le monitoring de latency repose sur deux types de signaux :
- runtime signals (
queue_time,step_latency,tool_latency,ttft) ; - service signals (
run_latency_p50/p95/p99,timeout_rate,retry_overhead_ms).
Ces metriques repondent a la question "ou et pourquoi le systeme ralentit dans le temps". Logs et tracing sont necessaires pour expliquer un run lent concret.
Latency != user experience. Les utilisateurs ne ressentent pas la moyenne - ils ressentent p95/p99. Ce sont les requetes lentes qui definissent la perception. Latency est souvent liee directement au cost. Des runs plus longs impliquent plus de tokens, plus d'appels tools et plus de retries, ce qui augmente directement le cost.
Metriques de latency production typiques
| Metrique | Ce qu'elle montre | Pourquoi elle est utile |
|---|---|---|
| run_latency_p50 | temps d'execution typique d'un run | controle de base de la vitesse |
| run_latency_p95 / p99 | longue queue et runs les plus lents | detection precoce de degradation |
| step_latency_p95 | quelles etapes agent ralentissent | localisation de l'etape problematique |
| tool_latency_p95 | latency de tools specifiques | recherche de bottlenecks externes |
| ttft_p95 | time-to-first-token pour LLM | controle de vitesse de premiere reponse |
| queue_time_p95 | combien de temps un run attend avant de demarrer | controle de charge et capacity |
| timeout_rate | part des etapes finissant en timeout | signal precoce d'instabilite |
| retry_overhead_ms | temps ajoute par les retries | impact de la recuperation sur latency |
run_latency_p95 et run_latency_p99 sont generalement calcules au niveau dashboard/requetes, pas comme compteur separe dans le code.
Pour garder des metriques pratiques, on segmente souvent par release, model, tool et type de workflow.
Important : ne pas ajouter de champs a forte cardinalite (run_id, request_id, user_id) dans les labels, sinon le stockage metriques se surcharge vite.
Comment lire la latency-layer
Ou apparait le delai -> comment l'agent se comporte -> ce qui ralentit exactement le run. Ces trois niveaux doivent etre lus ensemble.
Il faut regarder les tendances dans le temps et les differences entre releases, pas des valeurs isolees.
Ensuite, lire les combinaisons de signaux :
run_latency_p95up +tool_latency_p95up -> bottleneck dans les tools externes ;run_latency_p95up +step_countup -> l'agent fait des iterations inutiles ;ttft_p95up +tool_latency_p95~= stable -> probleme dans la couche LLM, pas tools ;timeout_rateup +retry_overhead_msup -> retries masquent l'instabilite et ajoutent de la latency ;queue_time_p95up +run_countup -> manque de capacity dans le systeme.
Quand l'utiliser
Un latency monitoring complet n'est pas toujours necessaire.
Pour un prototype simple, un temps de reponse de base peut suffire.
Mais le monitoring detaille des latences devient critique quand :
- le systeme est deja en production avec SLO/SLA de vitesse ;
- l'agent utilise plusieurs tools externes et dependances ;
- les releases sont frequentes et les regressions de latency doivent etre visibles ;
- le workflow contient des files, retries ou boucles de reasoning multi-etapes.
Exemple d'implementation
Ci-dessous un exemple simplifie d'instrumentation Prometheus des metriques de latency. Il montre le controle de base : run latency, etapes, tools, timeouts et retry overhead.
import time
from prometheus_client import Counter, Histogram
# perf_counter() est utilise au lieu de time.time()
# pour obtenir des mesures de latency monotones et precises
RUN_TOTAL = Counter(
"agent_run_total",
"Total number of agent runs",
["status", "stop_reason", "release"],
)
RUN_LATENCY_MS = Histogram(
"agent_run_latency_ms",
"Run latency in milliseconds",
["release"],
buckets=(100, 250, 500, 1000, 2000, 5000, 10000, 20000),
)
STEP_LATENCY_MS = Histogram(
"agent_step_latency_ms",
"Latency by step type in milliseconds",
["step_type", "release"],
buckets=(20, 50, 100, 250, 500, 1000, 2000, 5000),
)
TOOL_LATENCY_MS = Histogram(
"agent_tool_latency_ms",
"Tool latency in milliseconds",
["tool", "release"],
buckets=(20, 50, 100, 250, 500, 1000, 2000, 5000),
)
QUEUE_TIME_MS = Histogram(
"agent_queue_time_ms",
"Queue wait time before run start",
["release"],
buckets=(0, 20, 50, 100, 250, 500, 1000, 2000),
)
TTFT_MS = Histogram(
"agent_ttft_ms",
"Time to first token in milliseconds",
["model", "release"],
buckets=(50, 100, 200, 400, 800, 1500, 3000),
)
TIMEOUT_TOTAL = Counter(
"agent_timeout_total",
"Total timeout errors by layer",
["layer", "release"],
)
RETRY_OVERHEAD_MS = Histogram(
"agent_retry_overhead_ms",
"Added latency from retries",
["release"],
buckets=(0, 50, 100, 250, 500, 1000, 2000, 5000),
)
def run_agent(agent, task, queue_time_ms=0, release="2026-03-22"):
run_status = "ok"
stop_reason = "max_steps"
started_at = time.perf_counter()
if queue_time_ms > 0:
QUEUE_TIME_MS.labels(release=release).observe(queue_time_ms)
try:
for step in agent.iter(task):
step_type = step.type
step_started_at = time.perf_counter()
try:
result = step.execute()
except TimeoutError:
run_status = "error"
if step_type == "tool_call":
stop_reason = "tool_timeout"
elif step_type == "llm_generate":
stop_reason = "llm_timeout"
else:
stop_reason = "step_timeout"
layer = (
"tool"
if step_type == "tool_call"
else "llm"
if step_type == "llm_generate"
else "runtime"
)
TIMEOUT_TOTAL.labels(layer=layer, release=release).inc()
raise
except Exception:
run_status = "error"
if step_type == "tool_call":
stop_reason = "tool_error"
elif step_type == "llm_generate":
stop_reason = "llm_error"
else:
stop_reason = "step_error"
raise
finally:
step_latency_ms = (time.perf_counter() - step_started_at) * 1000
STEP_LATENCY_MS.labels(step_type=step_type, release=release).observe(step_latency_ms)
if step_type == "tool_call":
TOOL_LATENCY_MS.labels(
tool=getattr(step, "tool_name", "unknown"),
release=release,
).observe(step_latency_ms)
# retry overhead peut exister meme si l'etape echoue
retry_overhead_ms = float(getattr(step, "retry_overhead_ms", 0) or 0)
if retry_overhead_ms > 0:
RETRY_OVERHEAD_MS.labels(release=release).observe(retry_overhead_ms)
if step_type == "llm_generate":
model = getattr(step, "model", "unknown")
ttft_ms = float(getattr(result, "ttft_ms", 0) or 0)
if ttft_ms > 0:
TTFT_MS.labels(model=model, release=release).observe(ttft_ms)
if result and result.is_final:
stop_reason = "completed"
break
finally:
run_latency_ms = (time.perf_counter() - started_at) * 1000
RUN_LATENCY_MS.labels(release=release).observe(run_latency_ms)
RUN_TOTAL.labels(status=run_status, stop_reason=stop_reason, release=release).inc()
# run_latency_p95 et run_latency_p99 sont generalement calcules au niveau dashboard :
# histogram_quantile(...) sur les bucket-metrics agent_run_latency_ms.
Voici a quoi ces metriques peuvent ressembler ensemble sur un dashboard reel :
| Segment | p50 latency | p95 latency | timeout_rate | Statut |
|---|---|---|---|---|
| gpt-4.1 + tools | 1.1s | 4.8s | 2.9% | critical: SLO risk |
| mini-model + cache | 420ms | 1.2s | 0.4% | ok |
| research workflow | 1.7s | 6.1s | 1.8% | warning: p95 augmente |
Investigation
Quand une alerte de latency se declenche :
- trouver le segment anormal (
release,tool,model) ; - regarder les runs lents dans le tracing ;
- verifier retries, timeout et stop_reason dans les logs ;
- trouver la root cause (tool, LLM, queue, logique agent, service externe).
Erreurs typiques
Meme si les metriques de latency existent, elles apportent souvent peu de valeur a cause des erreurs ci-dessous.
On regarde seulement la latency moyenne
La moyenne cache souvent la degradation.
Pour la production, le minimum est p50 et p95, et pour les cas critiques aussi p99.
Pas de decoupage de latency par tools et step type
Sans cela, il est difficile de savoir ce qui est lent : LLM, tool ou boucle agent elle-meme. Dans ce cas, localiser vite un echec d'outil devient difficile.
Queue time est ignoree
Un run peut etre lent avant meme de commencer l'execution.
Sans queue_time_p95, on rate facilement les problemes de capacity.
Pas de metriques timeout-rate et retry-overhead
Les retries peuvent masquer l'instabilite et gonfler artificiellement la latency. Cela arrive souvent avec spam d'outils.
Pas d'alertes sur p95/p99 et timeout spikes
Sans alertes, l'equipe apprend les problemes trop tard, quand le SLO est deja viole.
Auto-verification
Ci-dessous une checklist courte du latency monitoring 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 latency monitoring differe du monitoring classique de vitesse API ?
R : Pour les agents, il faut monitorer non seulement le temps de reponse global, mais aussi les etapes internes : reasoning, tools, retries, queue time.
Q : Quel minimum de metriques de latency faut-il au demarrage ?
R : Commencer avec run_latency_p50/p95, tool_latency_p95, timeout_rate et queue_time_p95.
Q : Pourquoi p95 est plus important que la latency moyenne ?
R : Parce que p95 montre ce qui se passe pour les requetes lentes, celles que les utilisateurs remarquent le plus.
Q : Comment separer un probleme de latency tools d'un probleme de latency LLM ?
R : Comparer tool_latency_p95 et ttft_p95 : si seule la tool-latency monte, le bottleneck est dans les tools ; si ttft monte, le probleme est dans la couche LLM.
Pages liees
Suite du sujet :
- Metriques d'agents — modele global des metriques pour systemes agents.
- Tool usage metrics — comment isoler la latency au niveau tools.
- Cost monitoring pour agents — comment latency est liee au cost.
- Tracing d'agent — comment trouver l'etape lente dans un run concret.
- Alerting dans les agents IA — comment construire des alertes precoces.