Tippfehler-Cluster (02–05, 09, 12, 23, 27–28) und Terminologie (Outcomes 16↔18, Budget 16↔23, prompt_version, Coding-Agent, fester Workflow). Handoff: Git-Remote, P0/P1A/P1B erledigt, nächster Slice Faktencheck.
14 KiB
Orchestrierung im Code
Prompt, RAG, Tools, Workflow und optional Fine-Tune stehen (Kapitel 11–15). Im Review wirkt das Feature „fertig“: Demo-Happy-Path, Schema meist grün, ein Tool, ein Modell. In Produktion: Timeout beim Provider, kaputtes JSON nach Model-Update, doppelte Buchung nach Retry, Repair-Schleife ohne Budget, und niemand weiß, ob der Fallback jemals feuerte.
Die Bausteine sind notwendig — ohne Orchestrierung bleiben sie lose Enden. Orchestrierung ist der Control Flow, der probabilistische Knoten einklammert: wann rufen, was validieren, wie oft reparieren, wohin ausweichen, wann abbrechen.
Kern in einem Satz: Thin orchestration im Code — Control Flow, State, Caps, Validate/Repair/Fallback und Telemetrie gehören euch; das Modell füllt Contracts an benannten Stationen, es steuert nicht das System (T5, T6).
Dieses Kapitel bündelt die Bausteine zu einem Harness. Patterns aus Kapitel 07 werden hier implementierbar. Eval-Tiefe → Kapitel 17; Security-Guardrails → Kapitel 19.
Bridge: Klassisches SE → AI Engineering
| Klassisches SE | Orchestrierung bei LLMs … |
|---|---|
| Service-Orchestrator / Saga | Harness: Reihenfolge, State, Compensation, Caps |
| Request Validation + DTO | Validate vor und nach dem Modell (Schema, Policy) |
| Retry mit Backoff / Circuit Breaker | Retry-Budget + Provider-Failover — nicht blindes Re-Generate |
| Dead-letter / Fallback-Handler | Repair (begrenzt) → Fallback (Template, Regel, Mensch, refuse) |
| Idempotency-Key | Pflicht bei Write-Tools und Retry über Tool-Grenzen |
| Feature-Flag / Kill-Switch | Flag pro Capability + hard stop bei Budget/Policy |
| Health checks | Model/Provider-Latency, error classes, repair rate |
| Transaction boundaries | Side-Effect-Klassen und HITL vor irreversiblen Writes |
Die Brücke: ihr orchestriert unsichere Worker (T2). Mehr Magic im Framework ersetzt keine State-Maschine, keine Timeouts und keine harten Validatoren.
Was Orchestrierung ist — und was nicht
| Ist Orchestrierung | Ist nicht Orchestrierung |
|---|---|
| Control Flow und State außerhalb des Transcripts | 400 Zeilen System-Prompt als „Workflow“ |
| Validate / Repair / Fallback mit Caps | „Bitte antworte korrekt“ ohne Parser |
| Timeouts, Budgets, Kill-Switch | unbegrenzter Agent-Loop |
| Routing zu Model-Tier und Provider | immer das stärkste Modell „für Qualität“ |
| Trace-IDs, Versionen, Fehlerklassen | Demo-Happy-Path als Architektur |
Harness (kanonisch): Software-Schicht ums Modell — Orchestrierung, Policies, Telemetrie. Kein Produktname. Frameworks (LangGraph, Semantic Kernel, eigene Thin Layer, … — Stand August 2026) mappen unterschiedlich; die Verantwortlichkeiten bleiben.
Request
→ Input-Gates (AuthZ, Rate, Guardrails)
→ Context bauen (Slots, Retrieval, Memory)
→ Model call(s) an benannten Knoten
→ Validate Output
fail → Repair (budget) oder Fallback
→ Side effects nur nach Policy / HITL
→ Response + Telemetrie
Thin Orchestration
Dünn heißt: wenige, lesbare Schritte; Substanz in Schemas, Tool-Contracts, Policies und Eval — nicht in Framework-Spaghetti und nicht in Prompt-Prosa.
Do
- ein klarer Graph oder Pipeline pro Capability
- deterministische Schritte im Code, LLM nur wo Spec es braucht
- Caps:
max_model_calls,max_repairs,max_tool_steps,max_cost, wall-clock timeout - jeder Knoten: Eingabe-Schema, Ausgabe-Schema, Fehlerklasse
Don’t
- „der Agent findet den Prozess schon“ ohne Caps (Kapitel 14)
- Business-Rules nur im Prompt („nie Rabatt > 10 %“) ohne Code-Check
- Retry = denselben Call 10× ohne Diagnose
- State nur im Chat-Log
Faustregel: Wenn On-Call den Ablauf nicht in einer Seite skizzieren kann, ist die Orchestrierung zu dick — oder unsichtbar im Modell.
Schichten im Harness (implementierbar)
Anschluss an den Production Stack (Kapitel 07):
| Schicht im Code | Verantwortung | Typische Artefakte |
|---|---|---|
| Entry / API | AuthN/Z, Rate Limit, Request-Schema | Middleware, Feature-Key |
| Orchestrator | Graph, State, Caps, Flags | run_capability(ctx) |
| Adaptation adapters | Prompt-Template, RAG, Tool-Bindings | versionierte Config |
| Model access | Tier, Pin, Provider-Failover | Router, client wrappers |
| Validators | Schema, Business rules, Grounding-Checks | pure functions, tests ohne LLM |
| Effectors | Tool-Ausführung, HITL-Queue | Contracts (Kapitel 13) |
| Telemetry | Trace, Tokens, Costs, Outcomes | spans + redacted payloads |
Trennung zahlt sich aus: Validatoren und Tool-Adapter testet ihr ohne Modell. Model Access wechselt ihr hinter einer schmalen Schnittstelle. Orchestrierung bleibt lesbar, wenn Adaptation und Effects nicht in einer 800-Zeilen-Funktion vermischt sind.
Validate → Repair → Fallback
Das Kernmuster für Structured Output und kontrollierte Wirkung (Kapitel 07, Generate-then-Validate; Kapitel 11).
Validate (hart)
| Prüfung | Beispiel |
|---|---|
| Schema / Typen | JSON Schema, Enums, Pflichtfelder |
| Business rules | Betrag ≤ Limit, Status-Übergang erlaubt |
| Grounding | Claim nur mit Citation / Snippet-ID |
| Policy | keine PII im öffentlichen Reply; Safety-Block |
| Tool-Args | vor Ausführung gegen Contract |
Validate ist Code, nicht „Modell, bitte prüfe dich selbst“ als einzige Linie.
Repair (begrenzt)
Bei Validate-Fail: gezielter Repair-Call mit Fehlerdiagnose (maschinenlesbar: welche Felder, welche Regel) — nicht den Original-Prompt nochmal.
- Cap: typisch 1–2 Repairs, feature-spezifisch
- gleiches Schema, enger Task: „korrigiere nur X“
- Telemetrie:
repair_count,repair_reason
Repair ist teurer (Latenz + Tokens) und kein Ersatz für schlechte Contracts.
Fallback (explizit)
Wenn Budget erschöpft oder Fehlerklasse „nicht reparierbar“:
| Fallback | Wann |
|---|---|
| Template / Regelwerk | enge Klassifikation, bekannte Defaults |
| schwächeres/anderes Modell | nur wenn Eval das stützt; sonst Provider-Failover |
| Mensch (Queue) | Gelb/Rot, hohe Wirkung |
Refuse / unable |
ehrlicher als Halluzination |
| Degraded UX | „Entwurf nicht verfügbar“ statt leere 200 mit Müll |
Jeder Fallback ist spezifiziert in der Feature-Spec — nicht still im Catch-Block erfunden.
generate → validate
│ fail
├─ repairs left? → repair → validate …
└─ else → fallback (template | human | refuse | other model*)
Retry, Timeouts, Idempotenz
Was ihr wiederholt
| Fehlerklasse | Retry? | Hinweis |
|---|---|---|
| Provider 429 / transient 5xx | ja, Backoff + jitter, Cap | Circuit breaker pro Provider |
| Timeout (kein Response) | vorsichtig | Idempotenz bei bereits ausgelösten Tools |
| Validate fail | Repair, nicht blind Retry desselben | |
| 4xx Auth / Policy | nein | fix config / deny |
Tool business error (not_found) |
meist nein; an Modell als structured error | kein Re-Fire des Writes |
Retry-Budget und Repair-Budget sind getrennt. Beides multipliziert Kosten und Latenz (T7).
Timeouts
- wall-clock pro Request und pro Model-/Tool-Call
- Streaming ändert UX, nicht die Notwendigkeit von Deadlines
- Agent/Pipeline: Step-Timeout und Gesamt-Timeout (Kapitel 14)
Idempotenz
Retries über Netzwerkgrenzen erzeugen Doppel-Wirkung. Write-Tools: Idempotency-Key, upsert-Semantik, „at-most-once“-Gates vor HITL. Ohne das ist „einfach nochmal“ ein Incident.
Patterns und Trade-offs
Pattern: Capability als Funktion
Eine öffentliche Operation: triage_ticket(input) -> Result. Intern Pipeline; außen ein Contract. Prompts und Modelle sind Implementierungsdetails hinter der Version.
Trade-off: etwas mehr Struktur; klare Ownership und Testbarkeit.
Pattern: Pure validators, impure edges
Schema- und Rule-Checks pure und unit-testbar. I/O (Model, Tools, DB) an den Rändern.
Trade-off: etwas Boilerplate; On-Call und CI werden einfacher.
Pattern: Budget object im State
Budget: {
max_cost_per_request, # bzw. max_cost_eur
max_tokens, # pro Request / Pfad
max_steps, # inkl. max_model_calls / Tool-Steps
max_repairs,
deadline_at
}
Felder und Tenant-Tagescaps: Kapitel 23. Jeder Call dekrementiert; bei 0 → Fallback/Abort. Kein implizites „noch ein Versuch“.
Trade-off: Disziplin im Code; schützt p95 und Rechnung.
Pattern: Explicit outcome taxonomy
Outcomes: success, success_degraded, refuse, needs_human, error_provider, error_validation_exhausted, … — für Metrics und UX, nicht nur HTTP 200.
Trade-off: Mapping-Aufwand; messbare Produktion (Kapitel 18).
Pattern: Shadow path für Orchestrierungs-Änderungen
Neue Validate-Regel oder Repair-Logik zuerst loggen (shadow), dann enforce — analog Model-Canary.
Trade-off: doppelte Logik kurzfristig; weniger Big-Bang-Incidents.
Decision Frame: noch ein Repair — oder Fallback?
| Signal | Tendenz |
|---|---|
| Schema-Fehler, klare Diagnose | 1 Repair |
| semantisch unsicher / out of scope | refuse oder human |
| transient Provider | retry provider, nicht repair content |
| Write bereits unsicher ausgelöst | kein blindes Retry; reconcile |
| Repair-Rate steigt nach Model-Change | Contract/Eval, nicht Cap erhöhen |
Trade-off: Framework-Orchestrierung vs. eigene Thin Layer
| Framework-Graph | Eigene dünne Schicht |
|---|---|
| schnell sichtbar | volle Kontrolle, weniger Magie |
| Defaults werden Architektur | mehr Code ownership |
| Vendor-Lifecycle | passt zu eurem Stack |
| gut für Exploration | oft besser ab festem Production-Graph |
Wählt das, was Caps, State und Telemetrie explizit macht — nicht das mit dem beeindruckendsten Diagramm-Generator (T6).
Anti-Patterns
| Anti-Pattern | Symptom | Besser |
|---|---|---|
| Prompt as Orchestrator | Ablauf nur in Prosa | Graph im Code |
| Infinite Repair | validate-fail → ewige Schleife | Cap + Fallback |
| Retry everything | 10× gleicher Call | Fehlerklassen trennen |
| Happy-Path only | kein Fallback in Spec | Outcome-Taxonomy |
| Chat as State | Business-State im Transcript | externes State-Objekt |
| SDK in the Controller | UX ruft Provider direkt | Model Access + Orchestrator |
| Silent 200 | Müll oder leerer Body | refuse / degraded UX |
| Budget im Bauchgefühl | Rechnung überrascht | Budget object + Alerts |
| Idempotenz später | Doppel-Refunds | Keys vor erstem Write-Tool |
| Framework = Design | niemand kennt den echten Graph | eine Seite Architektur-Skizze |
Production Notes
Cost. Jeder Repair und Retry ist ein Multiplikator. Misst calls_per_success, repair_rate, €/capability. Caps in der Spec-Envelope (Kapitel 06); Alerts bevor Finance anruft (T7).
Latency. p95 bricht zuerst an sequentiellen Model+Tool-Ketten und an Repair. Parallelisiert nur wo unabhängig; setzt Deadlines; async für lange Pipelines.
Observability. Minimum: Request/Trace-ID, capability, model_id, prompt_version, step, validate/repair counts, outcome, token in/out, cost estimate — redacted (observability-minimum.md). Ohne Outcome-Taxonomy sind Dashboards Kosmetik. Tiefe: Kapitel 22.
Security. Orchestrierung erzwingt Trust Boundaries: untrusted slots, Tool-Allowlist, Output nicht ungeprüft an Shell/SQL/HTML. Kill-Switch und Policy-Gates gehören in den Graphen, nicht „ins Prompt-Update nächste Woche“ (Kapitel 19, T8).
Lifecycle. Orchestrator-Config (Caps, Fallbacks, Flags) versionieren wie Code. Model-Update: Canary auf Task Success und repair_rate / fallback_rate (T9). Named Owner für Capability-Graph und für Prompt/Eval (T10).
Key Takeaways
- Orchestrierung schlägt Magic (T6): Control Flow, Caps und Fallbacks leben im Code.
- Thin orchestration: lesbarer Graph; Substanz in Contracts, Validators und Eval.
- Validate → Repair (cap) → Fallback ist das Standardmuster um probabilistische Knoten.
- Retry ≠ Repair; Fehlerklassen und Idempotenz trennen.
- Harness-Schichten trennen Testbarkeit (pure validators) von Model Access und Effects.
- Jeder Outcome und Fallback ist spezifiziert — Silent Success ist ein Incident-Muster.
- Bausteine 11–15 werden hier gebündelt; Qualität beweist Kapitel 17.
Praktische nächste Schritte
- Zeichne eure wichtigste Capability als Graph (max. eine Seite): Knoten, Caps, Fallback.
- Implementiert Validate als pure Funktion mit Unit Tests — ohne LLM.
- Setzt
max_repairs, wall-clock und cost budget vor dem nächsten Prod-Traffic. - Führt eine Outcome-Taxonomy ein und loggt sie (redacted) pro Request.
- Prüft Write-Pfade auf Idempotenz-Keys und HITL-Gates.
- Legt fest: was passiert bei Provider-Outage? (Failover, queue, refuse) — und testet den Pfad einmal.
- Nächster Baustein-Abschluss: Offline-Eval und CI-Gates in Evaluation und Testing.