Tool-Response-Korruption (Schema-Drift + Truncation) + Code

  • Erkenne den Fehler früh, bevor die Rechnung steigt.
  • Verstehe, was in Prod bricht – und warum.
  • Guardrails kopieren: Budgets, Stop-Reasons, Validation.
  • Wissen, wann das nicht die Root Cause ist.
Erkennungs-Signale
  • Tool-Calls pro Run steigen (oder wiederholen sich mit args-hash).
  • Kosten/Tokens pro Request steigen ohne bessere Ergebnisse.
  • Retries kippen von selten zu konstant (429/5xx).
Corrupted oder driftende Tool Outputs führen zu falschen Actions. Output Validation, Size Limits und fail-closed verhindern, dass der Agent auf Garbage handelt.
Auf dieser Seite
  1. Problem (aus der Praxis)
  2. Warum das in Production bricht
  3. 1) Output wird als trusted angenommen
  4. 2) Partial Responses passieren
  5. 3) Schema Drift ist konstant
  6. 4) Das Modell “smooth’t” Corruption
  7. Implementierungsbeispiel (echter Code)
  8. Echter Incident (mit Zahlen)
  9. Abwägungen
  10. Wann du es NICHT nutzen solltest
  11. Checkliste (Copy/Paste)
  12. Sicheres Default-Config-Snippet (JSON/YAML)
  13. FAQ (3–5)
  14. Verwandte Seiten (3–6 Links)
Interaktiver Ablauf
Szenario:
Schritt 1/2: Execution

Normal path: execute → tool → observe.

Problem (aus der Praxis)

Dein Tool liefert JSON.

Bis es das nicht tut.

Proxy injectet HTML. Response ist truncat’t. Tool Version renamed Felder.

Das Modell sieht “irgendwas” und macht weiter. So bekommst du:

  • falsche Decisions
  • falsche Writes
  • und den schlimmsten Bug: “es ist nicht gecrasht, es war nur falsch”

Tool Output ist die Realität des Agents. Wenn die Realität korrupt ist, sind Decisions korrupt.

Warum das in Production bricht

1) Output wird als trusted angenommen

Viele Teams validieren Inputs und ignorieren Outputs. Bei Agents ist das falsch:

  • Output steuert Entscheidungen
  • Output ist die Hauptquelle für silent corruption

2) Partial Responses passieren

Timeouts failen nicht immer clean. Du bekommst:

  • halbes JSON
  • 200 mit Error Payload
  • leeren Body mit Success Status

3) Schema Drift ist konstant

Internal APIs ändern sich. Vendors ändern sich. Deine Tools ändern sich. Ohne Output Validation merkst du’s erst über User-Failures.

4) Das Modell “smooth’t” Corruption

Menschen stoppen bei invalid JSON. Modelle füllen Lücken. Für Text: Feature. Für Tool Actions: Bug.

Implementierungsbeispiel (echter Code)

Safe Pattern:

  1. size limits
  2. content-type
  3. schema + invariants
  4. fail closed/degrade
PYTHON
import json
from typing import Any


class ToolOutputInvalid(RuntimeError):
  pass


def parse_json_strict(raw: str, *, max_chars: int = 200_000) -> Any:
  if len(raw) > max_chars:
      raise ToolOutputInvalid("tool output too large")
  try:
      return json.loads(raw)
  except Exception as e:
      raise ToolOutputInvalid(f"invalid JSON: {type(e).__name__}")


def validate_user_profile(obj: Any) -> dict[str, Any]:
  if not isinstance(obj, dict):
      raise ToolOutputInvalid("expected object")
  if "user_id" not in obj or not isinstance(obj["user_id"], str):
      raise ToolOutputInvalid("missing user_id")
  if "plan" in obj and obj["plan"] not in {"free", "pro", "enterprise"}:
      raise ToolOutputInvalid("invalid plan enum")
  return obj


def get_user_profile(user_id: str) -> dict[str, Any]:
  raw = http_get(f"https://api.internal/users/{user_id}")  # (pseudo)
  obj = parse_json_strict(raw)
  return validate_user_profile(obj)
JAVASCRIPT
export class ToolOutputInvalid extends Error {}

export function parseJsonStrict(raw, { maxChars = 200_000 } = {}) {
if (raw.length > maxChars) throw new ToolOutputInvalid("tool output too large");
try {
  return JSON.parse(raw);
} catch (e) {
  throw new ToolOutputInvalid("invalid JSON: " + (e && e.name ? e.name : "Error"));
}
}

export function validateUserProfile(obj) {
if (!obj || typeof obj !== "object") throw new ToolOutputInvalid("expected object");
if (typeof obj.user_id !== "string") throw new ToolOutputInvalid("missing user_id");
if ("plan" in obj && !["free", "pro", "enterprise"].includes(obj.plan)) {
  throw new ToolOutputInvalid("invalid plan enum");
}
return obj;
}

Absichtlich strikt. Wenn Output kaputt ist, ist die richtige Reaktion oft:

  • stoppen
  • partial returnen
  • Failure class loggen

Nicht: “raten”.

Echter Incident (mit Zahlen)

Agent updatete CRM Notes basierend auf user profile.

user.profile lieferte manchmal HTML Error Pages mit 200 (Proxy misconfig). Das Modell extrahierte “plan=enterprise” aus irgendeinem Banner.

Impact:

  • 23 CRM Records falsch getaggt
  • Sales verbrannte ~3 Stunden
  • Cleanup Job + Restore aus Logs (unvollständig)

Fix:

  1. content-type checks + strict JSON parse
  2. schema validation + enums
  3. fail closed + safe-mode (skip writes)
  4. metrics: tool_output_invalid rate

Tools lügen auf langweilige Weise. Dein Agent muss widersprechen.

Abwägungen

  • Strikte Validation erhöht hard failures bei Drift (gut: du siehst es).
  • fail closed senkt success rate, verhindert silent corruption.
  • Schema Maintenance ist Arbeit. Silent data corruption ist schlimmere Arbeit.

Wann du es NICHT nutzen solltest

  • Wenn das Tool strong typed end-to-end ist und du es voll kontrollierst: weniger Validation (size limits trotzdem).
  • Wenn Tool free-form Text liefert: wrap mit extractor → structured output.
  • Wenn du nicht stoppen darfst: du brauchst fallback tools, nicht looser validation.

Checkliste (Copy/Paste)

  • [ ] Max response size
  • [ ] content-type check
  • [ ] strict parse
  • [ ] schema + enums
  • [ ] invariants (ids, ranges)
  • [ ] fail closed/degrade (keine writes auf invalid output)
  • [ ] metrics/alerts auf invalid output rate
  • [ ] log args hash + tool version + error class

Sicheres Default-Config-Snippet (JSON/YAML)

YAML
validation:
  tool_output:
    fail_closed: true
    max_chars: 200000
    require_content_type: "application/json"
    enforce_enums: true
safe_mode:
  on_invalid_output: "skip_writes"
metrics:
  track: ["tool_output_invalid_rate"]

FAQ (3–5)

Ist Output Validation bei internen Tools nicht redundant?
Nein. Interne Tools driften auch. ‘Intern’ heißt nur: der Bug gehört dir.
Was ist der Worst Case ohne Validation?
Silent corruption: falsche Writes, die ‘erfolgreich’ aussehen. Du merkst es Tage später.
Brauche ich eine JSON Schema Library?
Nicht sofort. Starte mit strict parse + Invariants. Schemas dort, wo Blast Radius hoch ist.
Wie hängt das mit Prompt Injection zusammen?
Corrupted Outputs enthalten oft untrusted Text. Validieren und als Data behandeln, nicht als Instructions.

Q: Ist Output Validation bei internen Tools nicht redundant?
A: Nein. Interne Tools driften auch. “Intern” heißt nur: der Bug gehört dir.

Q: Was ist der Worst Case ohne Validation?
A: Silent corruption: falsche Writes, die “erfolgreich” aussehen. Du merkst es Tage später.

Q: Brauche ich eine JSON Schema Library?
A: Nicht sofort. Starte mit strict parse + Invariants. Schemas dort, wo Blast Radius hoch ist.

Q: Wie hängt das mit Prompt Injection zusammen?
A: Corrupted Outputs enthalten oft untrusted Text. Validieren und als Data behandeln, nicht als Instructions.

Nicht sicher, ob das dein Fall ist?

Agent gestalten ->
⏱️ 5 Min. LesezeitAktualisiert Mär, 2026Schwierigkeit: ★★☆
In OnceOnly umsetzen
Guardrails for loops, retries, and spend escalation.
In OnceOnly nutzen
# onceonly guardrails (concept)
version: 1
budgets:
  max_steps: 25
  max_tool_calls: 12
  max_seconds: 60
  max_usd: 1.00
policy:
  tool_allowlist:
    - search.read
    - http.get
controls:
  loop_detection:
    enabled: true
    dedupe_by: [tool, args_hash]
  retries:
    max: 2
    backoff_ms: [200, 800]
stop_reasons:
  enabled: true
logging:
  tool_calls: { enabled: true, store_args: false, store_args_hash: true }
Integriert: Production ControlOnceOnly
Guardrails für Tool-Calling-Agents
Shippe dieses Pattern mit Governance:
  • Budgets (Steps / Spend Caps)
  • Kill switch & Incident Stop
  • Audit logs & Nachvollziehbarkeit
  • Idempotenz & Dedupe
  • Tool-Permissions (Allowlist / Blocklist)
Integrierter Hinweis: OnceOnly ist eine Control-Layer für Production-Agent-Systeme.
Beispiel-Policy (Konzept)
# Example (Python — conceptual)
policy = {
  "budgets": {"steps": 20, "seconds": 60, "usd": 1.0},
  "controls": {"kill_switch": True, "audit": True},
}
Autor

Diese Dokumentation wird von Engineers kuratiert und gepflegt, die AI-Agenten in der Produktion betreiben.

Die Inhalte sind KI-gestützt, mit menschlicher redaktioneller Verantwortung für Genauigkeit, Klarheit und Produktionsrelevanz.

Patterns und Empfehlungen basieren auf Post-Mortems, Failure-Modes und operativen Incidents in produktiven Systemen, auch bei der Entwicklung und dem Betrieb von Governance-Infrastruktur für Agenten bei OnceOnly.