Agent-Metriken

Metriken zeigen Erfolg, Tool-Aufrufe und Ausfuehrungsschritte des Agenten.
Auf dieser Seite
  1. Idee in 30 Sekunden
  2. Hauptproblem
  3. Wie es funktioniert
  4. Typische Production-Metriken fuer Agenten
  5. Wann einsetzen
  6. Implementierungsbeispiel
  7. Typische Fehler
  8. Nur Durchschnittswerte, ohne p95/p99
  9. Hoch-kardinale Labels
  10. Keine stop_reason-Metriken
  11. Keine Alerts auf zentrale Anomalien
  12. Selbstcheck
  13. FAQ
  14. Verwandte Seiten

Idee in 30 Sekunden

Agent-Metriken zeigen den Zustand des Systems ueber viele Runs hinweg, nicht nur in einem Einzelfall.

Sie beantworten: ist das System stabil, steigen die Kosten, und wo beginnt die Degradation.

Ohne Metriken werden Probleme meist zu spaet sichtbar: nach Nutzerbeschwerden oder Budget-Ueberschreitung.

Hauptproblem

Logs und Tracing erklaeren einen konkreten Incident gut.

In Production braucht man aber Trends: was mit latency, token usage, error rate und tool calls zwischen Releases passiert. Ohne Metriken kann das System schrittweise degradieren und lange unbemerkt bleiben.

In Production sieht das meist so aus:

  • die durchschnittliche Antwortzeit wirkt normal, aber p95 steigt bereits;
  • Token-Kosten springen nach einem Release in Wellen;
  • die Zahl der tool calls pro Run waechst;
  • das Team merkt das Problem erst nach einem Incident.

Genau deshalb sind Metriken ein eigenes Observability-Signal: sie helfen, Anomalien frueh zu erkennen und vor groesseren Ausfaellen zu reagieren.

Wie es funktioniert

Metriken sind aggregierte numerische Signale, die das Systemverhalten ueber die Zeit zeigen.

Ueblich sind drei Metrik-Ebenen:

  • Run-Ebene (run_count, success_rate, stop_reason);
  • Schritte und Tools (tool_calls_per_run, tool_error_rate, step_count);
  • Kosten und Geschwindigkeit (token_usage, cost_per_run (wird aus token_usage im Dashboard oder per Metrik-Query berechnet), latency_p50/p95).

Metriken geben ein Fruehsignal, wenn das System zu degradieren beginnt. Logs beantworten "was ist passiert", und Tracing beantwortet "wie genau ist es in einem konkreten Run passiert".

Typische Production-Metriken fuer Agenten

MetrikWas sie zeigtWozu sie dient
run_countAnzahl der Runs pro ZeitraumKontrolle von Last und Traffic-Volumen
success_rateAnteil erfolgreicher Runsschnelle Stabilitaetspruefung
latency_p50 / latency_p95typische und langsame Schwanz-LatenzErkennung von Performance-Degradation
token_usage_per_runwie viele Tokens ein Run verbrauchtKontrolle der LLM-Kosten
cost_per_rungeschaetzte Kosten eines RunsBudgetkontrolle und Kostenprognose
tool_calls_per_runwie oft ein Run Tools aufruftErkennung ueberfluessiger oder zyklischer Aufrufe
tool_error_rateHaeufigkeit von Tool-Fehlernfruehe Erkennung instabiler Abhaengigkeiten
stop_reason_distributionVerteilung der Run-AbbruchgruendeKontrolle von Limits und typischen Fehlern

Damit Metriken nuetzlich sind, werden sie meist nach release, model oder tool segmentiert.

Wichtig: keine hoch-kardinalen Felder (run_id, request_id, user_id) als Labels verwenden, sonst wird das Metrik-Storage schnell ueberlastet.

Wann einsetzen

Ein breites Metrik-Set ist nicht immer noetig.

Fuer fruehe Prototypen reichen manchmal einfache Zaehler fuer Runs und Fehler.

Kritisch werden Metriken, wenn:

  • das Agentensystem bereits in Production ist;
  • SLOs fuer latency oder Qualitaet gelten;
  • Token- und Tool-Kosten kontrolliert werden muessen;
  • Releases haeufig sind und Regressionen vor Incidents sichtbar sein sollen.

Implementierungsbeispiel

Unten ist ein vereinfachtes Beispiel fuer Runtime-Instrumentierung im Prometheus-Stil. In realen Systemen gelten dieselben Prinzipien fuer Datadog, Grafana Cloud, CloudWatch und andere Plattformen.

PYTHON
import time
from prometheus_client import Counter, Histogram

RUN_TOTAL = Counter(
    "agent_run_total",
    "Total number of agent runs",
    ["status", "stop_reason", "release"],
)
# success_rate = RUN_TOTAL{status="ok"} / RUN_TOTAL

RUN_LATENCY_MS = Histogram(
    "agent_run_latency_ms",
    "Run latency in milliseconds",
    ["release"],
    buckets=(100, 250, 500, 1000, 2000, 5000, 10000),
)

STEP_COUNT = Histogram(
    "agent_steps_per_run",
    "Number of steps per run",
    ["release"],
    buckets=(1, 2, 4, 8, 12, 16, 24, 32),
)

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"],
)

LLM_ERROR_TOTAL = Counter(
    "agent_llm_error_total",
    "Total LLM step errors by model and class",
    ["model", "error_class", "release"],
)

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

TOKEN_USAGE_TOTAL = Counter(
    "agent_token_usage_total",
    "Total LLM tokens",
    ["model", "token_type", "release"],
)


def observe_llm_usage(model, token_usage, release):
    # die meisten LLM-Provider liefern token usage in der Antwort
    if not token_usage:
        return
    TOKEN_USAGE_TOTAL.labels(model=model, token_type="prompt", release=release).inc(
        token_usage.get("prompt_tokens", 0)
    )
    TOKEN_USAGE_TOTAL.labels(model=model, token_type="completion", release=release).inc(
        token_usage.get("completion_tokens", 0)
    )


def run_agent(agent, task, release="2026-03-21"):
    started_at = time.time()
    steps = 0
    stop_reason = "max_steps"
    run_status = "ok"

    try:
        for step in agent.iter(task):
            steps += 1
            step_type = step.type
            result = None  # kann bei unbekannten Schritt-Typen None bleiben (durch den Check unten abgesichert)

            if step_type == "tool_call":
                tool_name = getattr(step, "tool_name", "unknown")
                tool_started_at = time.time()
                try:
                    result = step.execute()
                    TOOL_CALL_TOTAL.labels(tool=tool_name, status="ok", release=release).inc()
                    TOOL_LATENCY_MS.labels(tool=tool_name, release=release).observe(
                        (time.time() - tool_started_at) * 1000
                    )
                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()
                    TOOL_LATENCY_MS.labels(tool=tool_name, release=release).observe(
                        (time.time() - tool_started_at) * 1000
                    )
                    run_status = "error"
                    stop_reason = "tool_error"
                    raise
            else:
                try:
                    result = step.execute()
                    observe_llm_usage(
                        model=getattr(step, "model", "unknown"),
                        token_usage=getattr(result, "token_usage", None),
                        release=release,
                    )
                except Exception as error:
                    LLM_ERROR_TOTAL.labels(
                        model=getattr(step, "model", "unknown"),
                        error_class=type(error).__name__,
                        release=release,
                    ).inc()
                    run_status = "error"
                    stop_reason = "step_error"
                    raise

            if result and result.is_final:
                stop_reason = "completed"
                break

    finally:
        RUN_TOTAL.labels(status=run_status, stop_reason=stop_reason, release=release).inc()
        RUN_LATENCY_MS.labels(release=release).observe((time.time() - started_at) * 1000)
        STEP_COUNT.labels(release=release).observe(steps)

In Production fliessen diese Metriken in Dashboards und Alerts.

So koennen diese Metriken zusammen in einem realen Dashboard aussehen:

MetrikAktueller WertTrendStatus
latency_p952.4s+38% in 30 Minwarning: ueber SLO
tool_error_rate7.2%+4.1pp in 15 Mincritical: alert
token_usage_per_run8.9k+22% nach Releasewarning: Anomalie
success_rate91.4%-5.3pp in 1 Stundewarning: Rueckgang

Fuer error_class ist ein normalisiertes Wertewoerterbuch besser, um unnoetige Kardinalitaet zu vermeiden.

Zum Beispiel kann eine Metrikzeile so aussehen:

TEXT
agent_tool_call_total{tool="search_docs",status="error",release="2026-03-21"} 47

Typische Fehler

Selbst wenn Metriken vorhanden sind, bringen sie oft wenig wegen typischer Fehler unten.

Nur Durchschnittswerte, ohne p95/p99

Der Durchschnitt versteckt den langen Schwanz langsamer Runs. Fuer Production ist das Minimum p50 und p95.

Hoch-kardinale Labels

Labels wie run_id oder user_id erhoehen die Last auf dem Metrik-Backend stark. Besser segmentieren nach release, model, tool.

Keine stop_reason-Metriken

Ohne stop_reason-Verteilung ist schwer zu verstehen, warum Runs mit max_steps oder tool_error enden. Das maskiert oft Tool-Ausfall und fruehe Signale einer Budget-Explosion.

Keine Alerts auf zentrale Anomalien

Metriken ohne Alerts werden zu passiven Charts. Ohne Alerts uebersieht man leicht Tool-Spam oder einen starken Einbruch der Erfolgsrate nach einem Release.

Selbstcheck

Unten ist eine kurze Checkliste fuer Basis-Metriken von Agenten vor Release.

Fortschritt: 0/9

⚠ Grundlegende Observability fehlt

Das System wird in production schwer zu debuggen sein. Starten Sie mit run_id, structured logs und tracing von tool calls.

FAQ

Q: Worin unterscheiden sich Metriken von Logs und Tracing?
A: Metriken zeigen Trends und Systemzustand ueber die Zeit. Logs erklaeren Ereignisse, und Tracing zeigt den Pfad eines konkreten Runs.

Q: Welches Minimum an Metriken braucht man fuer den ersten Production-Release?
A: Starte mit run_count, success_rate, latency_p95, tool_error_rate, token_usage_per_run und stop_reason_distribution.

Q: Warum reicht nur durchschnittliche latency nicht aus?
A: Der Durchschnitt versteckt lange langsame Runs. p95 zeigt reale Nutzer-Degradation deutlich frueher.

Q: Welche Labels brechen Metrik-Storage am haeufigsten?
A: Alles mit hoher Kardinalitaet: run_id, request_id, user_id, komplette Prompts oder raw args.

Verwandte Seiten

Weiter zum Thema:

⏱ 7 Min. Lesezeit ‱ Aktualisiert 21. MĂ€rz 2026Schwierigkeit: ★★★
Integriert: Production ControlOnceOnly
Guardrails fĂŒr Tool-Calling-Agents
Shippe dieses Pattern mit Governance:
  • Budgets (Steps / Spend Caps)
  • Tool-Permissions (Allowlist / Blocklist)
  • Kill switch & Incident Stop
  • Idempotenz & Dedupe
  • Audit logs & Nachvollziehbarkeit
Integrierter Hinweis: OnceOnly ist eine Control-Layer fĂŒr Production-Agent-Systeme.

Autor

Nick — Engineer, der Infrastruktur fĂŒr KI-Agenten in Produktion aufbaut.

Fokus: Agent-Patterns, Failure-Modes, Runtime-Steuerung und SystemzuverlÀssigkeit.

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


Redaktioneller Hinweis

Diese Dokumentation ist KI-gestĂŒtzt, mit menschlicher redaktioneller Verantwortung fĂŒr Genauigkeit, Klarheit und Produktionsrelevanz.

Der Inhalt basiert auf realen AusfÀllen, Post-Mortems und operativen VorfÀllen in produktiv eingesetzten KI-Agenten-Systemen.