Von "wir bräuchten mal..." zum auditierbaren Release: die Pipeline am Stück
Teil 7 (Finale) einer Artikelserie über zwei eigene Agenten-Projekte: wintermute (produktiver persönlicher KI-Agent) und agenticframework (produktiv eingesetztes Meta-Framework für autonome Entwicklungs-Pipelines).
Alle Teile zusammensetzen
Sechs Teile lang habe ich einzelne Aspekte herausgegriffen: Sicherheitsgrenzen, Halluzinations-Abwehr, Kostenmodell, Autonomie-Grenzen. Zum Abschluss die Frage, für die agenticframework eigentlich gebaut ist: Was passiert zwischen dem Satz "wir bräuchten mal eine Möglichkeit, X zu tun" und einem Release, dessen Zustandekommen man drei Wochen später noch lückenlos nachvollziehen kann?
Die Antwort ist eine Pipeline aus sechs Phasen, jede mit einem verantwortlichen Agenten: Discovery (Ada) → Architektur (Daedalus) → Zerlegung (Tess) → Orchestrierung und Coding (Seldon + Case) → Review und Security (Argus + Molly) → Validierung und Integration (Turing + Forge). Das Interessante ist aber nicht die Liste — es ist das, was zwischen den Phasen passiert.
Das Bindegewebe: typisierte Übergaben
Jede Phase hat genau ein Eingabe- und ein Ausgabedokument, und alle teilen denselben Umschlag:
kind: string - discriminator for routing (e.g. "intent_handover")
schema_version: string - contract version used for validation/migration
pipeline_stage: string - e.g. "phase1->phase2", "phase2->phase3"
hitl_approved: bool - must be true before the next phase starts
generated_at: ISO-8601 UTC timestamp
source_agent_id: string
source_agent_version: string
trace_id: string - correlates artifacts to a PipelineRunManifest
Dieser Umschlag ist die halbe Architektur. kind und pipeline_stage machen jede Übergabe eindeutig adressierbar, schema_version erlaubt Migration, hitl_approved erzwingt die Freigabe-Disziplin aus Teil 6, und trace_id verbindet jedes Artefakt mit seinem Pipeline-Lauf. Agenten sind dadurch vollständig entkoppelt: Daedalus weiß nichts über Adas Innenleben — er kennt nur den IntentHandover-Vertrag. Man kann jeden Agenten austauschen, solange der Vertrag hält (und dass er hält, prüft die Schema-Validierung aus Teil 3 an jeder Grenze).
Phase 1: Aus Vagheit wird ein Vertrag
Am Anfang steht das unschärfste Artefakt der Softwareentwicklung: menschliche Absicht. Ada zerlegt sie in strukturierte Datensätze — Ziele, Fakten, Konflikte — und bewertet jede Analyse mit einem Ambiguity-Score. Unklares erzeugt gezielte Rückfragen, Widersprüche landen beim Menschen zur VETO/RESOLVE-Entscheidung (die Resolver-Rolle aus Teil 6). Das Ergebnis ist bewusst schmal:
class IntentHandover(HandoverEnvelope):
kind: Literal["intent_handover"] = "intent_handover"
pipeline_stage: Literal["phase1->phase2"] = "phase1->phase2"
source_agent_id: Literal["ada"] = "ada"
hitl_approved: bool
goals: list[str]
scoped_facts: list[str]
open_conflicts: list[str]
Ein Detail mit Tiefgang: scoped_facts enthält nur die Fakten, die der Mensch explizit für den Scope ausgewählt hat — die vollständige Liste bleibt für Audit-Zwecke erhalten. Scope-Entscheidungen sind damit dokumentierte Entscheidungen, kein Nebeneffekt dessen, was der Agent zufällig für relevant hielt. Daedalus macht daraus anschließend das Architektur-Paket: Domain-Modell, ADR-Referenzen, Modul-Briefs und eine Zerlegungsstrategie für die nächste Phase.
Phase 3: Ein Graph, der sich gegen Zyklen wehrt
Tess zerlegt die Architektur in atomare Issues (die Sizing-Budgets kennen Sie aus Teil 4) plus einen Abhängigkeitsgraphen. Und dieser Graph validiert sich selbst — Zyklenfreiheit ist keine Konvention, sondern Teil des Pydantic-Schemas:
@model_validator(mode="after")
def dependency_graph_is_acyclic(self) -> DecomposerHandover:
issue_ids = {issue.issue_id for issue in self.atomic_issues}
# ... keys must match issue ids, no unknown dependencies ...
visiting: set[str] = set()
visited: set[str] = set()
def visit(node: str) -> None:
if node in visiting:
raise ValueError("dependency graph must be acyclic")
# ... DFS ...
Ein Zerlegungsplan mit Zirkelbezug ("A braucht B, B braucht A") kann die Phasengrenze physisch nicht passieren — er ist kein gültiges Dokument. Das ist dasselbe Prinzip wie überall in dieser Serie: Eigenschaften, auf die man sich verlassen will, werden nicht erhofft, sondern am Typ erzwungen.
Phase 4: Warum es atomare Diffs sein müssen — die 22-KB-Geschichte
Dass Case, der Coding-Agent, ausschließlich Unified Diffs produziert und niemals ganze Dateien überschreibt, hat eine konkrete Vorgeschichte in wintermute: Beim Self-Modification-Experiment (Teil 6) ließ das damals verwendete Modell bei Dateien ab etwa 22 KB stillschweigend den content-Parameter aus dem Tool-Call fallen. Kein Fehler, keine Warnung — der Schlüssel fehlte einfach. Ein disziplinierter Plan, ein korrekter Prompt, und trotzdem landete nichts Committbares. Diese Erfahrung steht heute wörtlich als Constraint im Routing-File von agenticframework:
constraints:
- "Atomic diffs only, never whole-file writes. See section 1.5 Wintermute lessons for rationale."
- "Output must stay within ~500 tokens per model call; larger changes must be chunked."
- "Client-side schema validation before tool invocation and after model output."
Und die Skepsis reicht bis in die Tests: Ein eigener Testfall stellt sicher, dass das CodeHandover seine files_changed-Liste aus dem geparsten Diff bezieht — nicht aus den Metadaten, die der Modell-Provider behauptet. Selbst wenn das Modell falsche Dateinamen meldet, zählt, was im Diff tatsächlich steht. Vertrauen ist gut, Parsen ist besser.
Phase 5 und 6: Gates und das Ende der Reise
Die parallelen Qualitäts-Gates (Argus/Molly, inklusive des nicht überstimmbaren Security-Vetos) haben ihren eigenen Artikel in Teil 2. Danach übernimmt Phase 6: Turing führt die Integrationstests aus und protokolliert Kommandos, Ergebnisse und ein Go/No-Go-Verdict im ValidationHandover; Forge übernimmt die Integration und liefert das IntegrationResult mit Zusammenfassung und Referenzen auf alle integrierten Artefakte. Erst hier wird aus einer Kette validierter Dokumente ein Release.
Der Audit-Trail: Jeder Lauf erzählt seine Geschichte selbst
Was diese Pipeline von einem Skript mit sechs Schritten unterscheidet, ist die Buchführung. Jeder Lauf hat ein Manifest, das festhält: den Eingabe-Handover, die aktuelle Phase, Agent-Versionen, Modell-Auswahlen, alle Artefakt-Referenzen, alle Gate-Entscheidungen, alle menschlichen Entscheidungen, Kostenschätzungen und strukturierte Fehler. Parallel dazu läuft ein append-only Event-Log (NDJSON) mit Phasenübergängen, Agent-Starts, Retries und Eskalationen. Beides liegt — zusammen mit jedem Handover-Dokument — im "Transient Repository", einem Git-gestützten Ablagesystem:
runs/<run-id>/manifest.json ← PipelineRunManifest
runs/<run-id>/events.ndjson ← RunEventLog (append-only)
runs/<run-id>/artifacts/<phase>/... ← jedes Handover-Dokument, versioniert
Jeder Schreibvorgang ist ein Commit; jeder Zustand der Pipeline ist reproduzierbar und zurückspulbar; alle Dokumente sind Markdown und JSON, für Menschen lesbar. Die Frage "warum hat das System vor drei Wochen diese Entscheidung getroffen?" beantwortet sich per Checkout — nicht per Meeting-Archäologie.
Der ehrliche Schluss: Für wen sich das lohnt — und für wen nicht
Nach sieben Teilen bin ich Ihnen ein letztes Stück Ehrlichkeit schuldig. Diese Maschinerie — typisierte Verträge, dreifach geprüfte Ticket-Budgets, Manifeste, Event-Logs — ist für ein Wochenend-Feature absurdes Overengineering. Ihr Wert entsteht dort, wo drei Dinge zusammenkommen: Volumen (Teil 4: die Unit Economics greifen ab Dutzenden Läufen), Nachweispflicht (der Audit-Trail ist für Compliance-Kontexte gebaut, nicht für Hobby-Projekte) und Arbeitsteilung über Rollen hinweg (die Verträge lohnen sich, wenn nicht eine Person alles im Kopf hat). Und: Die Pipeline ist nur so gut wie ihre erste Phase. Ein sauber durchvalidierter, lückenlos auditierter Lauf auf Basis einer schlecht geklärten Anforderung produziert das falsche Feature — mit exzellenter Dokumentation. Deshalb beginnt die Pipeline mit Ada und einem Ambiguity-Score, und deshalb begann diese Serie mit der Frage nach dem Warum, nicht mit der Technik.
Serien-Fazit
Sieben Teile, zwei Repositories, ein roter Faden: Behauptungen werden geprüft, Entscheidungen werden begründet, Grenzen werden technisch durchgesetzt, und Scheitern wird dokumentiert. Nichts davon ist an KI-Agenten gebunden — es ist Software-Engineering, angewendet auf eine Technologie, die zum Abkürzen verführt wie keine zweite. Wenn Sie aus der Serie einen einzigen Satz mitnehmen: Der Unterschied zwischen einem Agenten-Demo und einem Agenten-System liegt nicht im Modell, sondern in allem drumherum.
Danke fürs Mitlesen. Die beiden Lessons-Logs wachsen weiter — und wenn sich genug Neues angesammelt hat, gibt es einen Nachschlag.
Quellen: agenticframework/FRAMEWORK.md (Phasenmodell, Handover-Envelope Zeilen 454–488, Manifest/Event-Log Zeilen 162–174, Transient Repository Zeilen 678–757), apps/intent-compiler/INTENT_COMPILER.md (Ada-Discovery-Mechanik), apps/intent-compiler/backend/src/api/models/state.py (IntentHandover Zeilen 164–193), orchestrator/src/agentic_orchestrator/phases/results.py (ArchitectHandover, DecomposerHandover inkl. Zyklen-Validator, ValidationHandover, IntegrationResult), orchestrator/src/agentic_orchestrator/kernel/models.py (PipelineRunManifest, RunEventLog), model_routing.yml (Atomic-Diff-Constraints), apps/intent-compiler/backend/tests/test_case_diff_validation.py (Parser-Metadaten statt Provider-Behauptung); wintermute/LESSONS.md (Lesson #25: die 22-KB-Geschichte).