Agent-Logging

Logs erfassen Aktionen, Prompts und Tool-Aufrufe des Agenten.
Auf dieser Seite
  1. Idee in 30 Sekunden
  2. Hauptproblem
  3. Wie es funktioniert
  4. Welche Events zuerst geloggt werden sollten
  5. Wann einsetzen
  6. Implementierungsbeispiel
  7. Typische Fehler
  8. Es wird nur die finale Antwort geloggt
  9. Keine stabilen IDs (run_id, trace_id)
  10. Raw prompts oder raw args werden ohne Redaction geloggt
  11. tool_result und stop_reason fehlen
  12. Selbstcheck
  13. FAQ
  14. Verwandte Seiten

Idee in 30 Sekunden

Agent-Logging beantwortet eine einfache Frage: Was genau ist wÀhrend eines Runs passiert.

DafĂŒr braucht man strukturierte Events mit Korrelation ĂŒber run_id und trace_id.

Ohne das sieht man in Incidents meist nur die finale Antwort, aber nicht den Weg dorthin.

Hauptproblem

Im klassischen Backend reichen oft ein paar Logs pro Request.

In Agentensystemen kann eine Anfrage Reasoning, Tool-Aufrufe, Retries und mehrere Modellschritte enthalten. Wenn nur das Finale geloggt wird, ist schwer zu erkennen, wo das System gebrochen ist.

In Production sieht das oft so aus:

  • ein Nutzer meldet eine falsche Antwort;
  • Kosten oder Latenz steigen in Wellen;
  • im Log steht ein einzelner Fehler ohne Run-Kontext.

Deshalb brauchen Agenten keine zufĂ€lligen Logs, sondern strukturiertes Event-Logging ĂŒber den gesamten Run-Lifecycle.

Wie es funktioniert

Die Basisidee ist einfach: Jeder wichtige Schritt wird als eigenes strukturiertes Event gespeichert.

Minimum pro Event:

  • run_id und trace_id zur Korrelation;
  • event (was passiert ist);
  • timestamp;
  • status (ok / error) wo relevant;
  • zentrale Schrittfelder (tool, latency, stop_reason usw.).

Welche Events zuerst geloggt werden sollten

EventWas festgehalten werden sollte
run_startedrun_id, trace_id, request_id, user_id
agent_stepstep_type, step_index, tool
tool_calltool_name, args_hash
tool_resulttool_name, latency_ms, status, error_class
llm_resultmodel, token usage, latency_ms, status
run_finishedstop_reason, total_steps, total_latency_ms

In Production werden raw prompts und raw tool args meist nicht ohne Redaction geloggt. Oft wird stattdessen ein Hash oder eine anonymisierte Form gespeichert.

Wann einsetzen

Tiefes Logging ist nicht immer nötig.

FĂŒr einfache Single-Shot-Szenarien reichen manchmal minimale request -> response Logs.

Sobald aber Tools, Retries, mehrere Schritte oder höhere Kosten auftreten, wird es ohne strukturiertes Logging schwierig:

  • Incidents zu debuggen;
  • Kosten zu erklĂ€ren;
  • Alerts stabil zu konfigurieren.

Implementierungsbeispiel

Unten ein vereinfachtes Beispiel fĂŒr Structured Logging in Runtime und Tool-Gateway. Im Beispiel werden raw args nicht geloggt: Es wird args_hash gespeichert. agent_step protokolliert den Schritt selbst, wĂ€hrend tool_call und tool_result Start und Ergebnis des Tool-Aufrufs getrennt erfassen.

PYTHON
import hashlib
import json
import logging
import time
import uuid

logger = logging.getLogger("agent")


def stable_hash(value):
    payload = json.dumps(
        value,
        sort_keys=True,
        ensure_ascii=False,
        default=str,  # fuer datetime und komplexe Typen; in kritischen Systemen besser stabiles Format nutzen (z. B. ISO 8601)
    ).encode("utf-8")
    return hashlib.sha256(payload).hexdigest()


def log_event(event, **fields):
    logger.info(event, extra={"event": event, **fields})


def run_agent(agent, task, user_id=None, request_id=None):
    run_id = str(uuid.uuid4())
    trace_id = str(uuid.uuid4())
    started_at = time.time()
    steps = 0
    stop_reason = "max_steps"
    run_status = "ok"

    log_event(
        "run_started",
        run_id=run_id,
        trace_id=trace_id,
        user_id=user_id,
        request_id=request_id,
        task_hash=stable_hash(task),
    )

    try:
        for step in agent.iter(task):  # step: reasoning oder tool execution
            steps += 1
            step_started_at = time.time()
            step_type = step.type
            tool_name = getattr(step, "tool_name", None)

            log_event(
                "agent_step",
                run_id=run_id,
                trace_id=trace_id,
                step_index=steps,
                step_type=step_type,
                tool=tool_name,
            )

            if step_type == "tool_call":
                args = getattr(step, "args", {})
                log_event(
                    "tool_call",
                    run_id=run_id,
                    trace_id=trace_id,
                    tool=tool_name,
                    args_hash=stable_hash(args),
                )

            try:
                result = step.execute()
                latency_ms = int((time.time() - step_started_at) * 1000)

                if step_type == "tool_call":
                    log_event(
                        "tool_result",
                        run_id=run_id,
                        trace_id=trace_id,
                        tool=tool_name,
                        latency_ms=latency_ms,
                        status="ok",
                    )
                else:
                    token_usage = getattr(result, "token_usage", None)
                    log_event(
                        "llm_result",
                        run_id=run_id,
                        trace_id=trace_id,
                        step_type=step_type,
                        model=getattr(step, "model", None),
                        token_usage=token_usage,
                        latency_ms=latency_ms,
                        status="ok",
                    )
            except Exception as error:
                latency_ms = int((time.time() - step_started_at) * 1000)
                result_event = "tool_result" if step_type == "tool_call" else "llm_result"
                log_event(
                    result_event,
                    run_id=run_id,
                    trace_id=trace_id,
                    step_type=step_type,
                    tool=tool_name,
                    model=getattr(step, "model", None),
                    latency_ms=latency_ms,
                    status="error",
                    error_class=type(error).__name__,
                    error_message=str(error),
                )
                run_status = "error"
                stop_reason = "tool_error" if step_type == "tool_call" else "step_error"
                raise

            if result.is_final:
                stop_reason = "completed"
                break
    finally:
        log_event(
            "run_finished",
            run_id=run_id,
            trace_id=trace_id,
            status=run_status,
            stop_reason=stop_reason,
            total_steps=steps,
            total_latency_ms=int((time.time() - started_at) * 1000),
        )

In Production gehen solche Events meist in ein zentrales Logging-System (z. B. ELK, Datadog oder ClickHouse) und werden fuer Dashboards und Alerts genutzt.

Dieses Beispiel reicht, um:

  • problematische Tool-Calls zu finden;
  • Latenz pro Schritt zu berechnen;
  • zu verstehen, warum ein Run gestoppt hat.

Ein einzelner JSON-Logeintrag kann so aussehen:

JSON
{
  "timestamp": "2026-03-21T15:17:00Z",
  "event": "tool_result",
  "run_id": "run_9fd2",
  "trace_id": "tr_9fd2",
  "tool": "search_docs",
  "latency_ms": 410,
  "status": "ok"
}

Typische Fehler

Auch wenn Logging vorhanden ist, bleiben Incidents oft schwer auswertbar wegen der typischen Fehler unten.

Es wird nur die finale Antwort geloggt

Ohne Zwischen-Events ist nicht sichtbar, wie der Agent zum Ergebnis kam. Damit dauert selbst ein einfacher Incident zu lange.

Keine stabilen IDs (run_id, trace_id)

Wenn Events nicht korrelieren, kann kein vollstĂ€ndiges Run-Bild rekonstruiert werden. In Production wird Debugging dann oft zur manuellen Suche ĂŒber mehrere Services.

Raw prompts oder raw args werden ohne Redaction geloggt

Das ist ein direkter Leak-Risiko fĂŒr personenbezogene oder sensitive Daten. Sicherer sind Hashes, redigierte Felder oder anonymisierte Versionen.

tool_result und stop_reason fehlen

Wenn tool_result und stop_reason fehlen, ist schwer zu erkennen, was genau gebrochen ist. Diese Luecken maskieren oft Tool-Ausfall oder eine fruehe Phase von Tool-Spam.

Selbstcheck

Unten ist eine kurze Checkliste fuer Basis-Agent-Logging 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 unterscheidet sich Logging von Tracing?
A: Logging beantwortet „was ist passiert“ und protokolliert Events. Tracing zeigt „wie genau ist es passiert“ ueber Schrittfolge und Verknuepfungen.

Q: Was sollte zuerst geloggt werden, wenn kaum Logging existiert?
A: Starte mit Basis: run_id, trace_id, run_started, tool_call, tool_result, run_finished, stop_reason. Das reicht bereits fuer Basis-Debugging.

Q: Kann man Prompts vollstaendig loggen?
A: Standardmaessig besser nicht. In Production enthalten Prompts oft sensitive Daten. Sicherer sind Hash oder redigierte Versionen.

Q: Woran erkenne ich, dass Logging ausreicht?
A: Wenn du innerhalb von 5-10 Minuten die Ereignisfolge eines problematischen Runs rekonstruieren und den Fehlerpunkt finden kannst, funktioniert dein Basis-Logging.

Verwandte Seiten

Weiter zum Thema:

⏱ 6 Min. Lesezeit ‱ Aktualisiert 9. April 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.