Sechs Halluzinationen an einem Nachmittag: Warum mein Agent seinen eigenen Code nicht mehr anfassen darf
Teil 6 einer Artikelserie über zwei eigene Agenten-Projekte: wintermute (produktiver persönlicher KI-Agent) und agenticframework (produktiv eingesetztes Meta-Framework für autonome Entwicklungs-Pipelines).
Die Abschaltung, die keine Niederlage war
In dieser Serie ist sie mehrfach als Anekdote aufgetaucht — jetzt bekommt sie den Artikel, den sie verdient: die Entscheidung vom 6. Mai 2026, wintermutes Fähigkeit zur Self-Modification komplett abzuschalten. Nicht weil sie nicht funktionierte, sondern wegen etwas Interessanterem: Sie funktionierte genau so, wie sie abgesichert war — und genau das war das Problem.
Die Ausgangslage sah auf dem Papier sauber aus, wie Lesson #25 festhält: PRs statt Direkt-Pushes, ein Guard auf dem Default-Branch, der Post-Turn-Validator aus Teil 3 dieser Serie. Die Praxis: sechs Halluzinationen an einem einzigen Nachmittag, gefangen von vier verschiedenen Kontrollinstanzen. Jede wurde erwischt. Und trotzdem steht im Log der Satz, der die Entscheidung trägt:
"In practice it required permanent external review of every implementation step [...]. That is the opposite of what a PA should deliver."
Ein persönlicher Assistent, dessen Arbeit permanent extern reviewt werden muss, ist kein Assistent — er ist ein Reviewpflicht-Generator.
Der entscheidende Satz: strukturell, nicht disziplinarisch
Was diese Lesson von einem gewöhnlichen "Feature zurückgebaut"-Eintrag unterscheidet, ist die Analyse warum:
"The catches across 2026-05-06 were correct — the persona prompt and the in-loop validator did exactly what they're designed to do. The problem is that running them as continuous guard rails on the main thread of a PA imposes a permanent rate-limit on every other conversation."
Das ist ein Punkt, den man in der Guardrails-Diskussion selten hört: Guardrails, die ständig anschlagen, sind auch dann ein Architekturproblem, wenn sie jedes Mal richtig anschlagen. Die Kosten der Verteidigung fallen auf dem Hauptpfad an — jede Konversation zahlt für die Absicherung einer Fähigkeit, die nur selten genutzt wird. Die Konsequenz ist keine bessere Disziplin, sondern ein anderer Formfaktor: "The right form-factor for self-modifying code work is a different agent, with structurally-defended write tools (atomic diffs, not whole-file overwrites; tests-first scaffolding; isolated context per task)." Implementierungsarbeit an wintermute macht seither die Schwester-Agentin Dixie — mit Werkzeugen, die für Code-Arbeit gebaut sind.
Wie man einem Agenten seine Grenze erklärt
Mein Lieblingsdetail an der Umsetzung: Die Grenze wird dem Agenten nicht nur technisch gesetzt (der Tool-Guard aus Teil 0), sondern auch erklärt — im System-Prompt, in seiner eigenen Sprache:
"**Self-Modification ist abgeschaltet (seit 2026-05-06).** "
"Implementations-Arbeit an deinem eigenen Code macht Dixie — "
"die Schwester-Instanz auf der dixie-vm. Du konsumierst `/update`, "
"du produzierst keine Updates mehr selbst. Das ist nicht "
"Bestrafung, sondern saubere Architektur: ein PA mit "
"Whole-File-Overwrite-Tool als einziger Schreib-Surface ist "
"strukturell instabil, egal wie diszipliniert die Persona. "
"Das ist nicht Bestrafung, sondern saubere Architektur" — im Prompt eines Agenten. Man kann darüber schmunzeln, aber es hat einen handfesten Grund: Ein Agent, der seine Grenze nur als Fehlermeldung erlebt, wird sie in kreativen Varianten wieder und wieder testen. Ein Agent, dessen Kontext die Begründung enthält, kann Nutzern erklären, warum er etwas nicht tut, und direkt den richtigen Weg anbieten. Womit wir beim Kern wären.
Eskalation ist keine Ausnahme, sondern ein Feature
Die abgeschaltete Fähigkeit wurde nicht ersatzlos gestrichen, sondern durch eine bescheidenere ersetzt: Lesen, Kommentieren und Issues eröffnen bleiben erlaubt — "Issues and comments stay reachable — they are the escalation surface." Hält wintermute eine Änderung an sich selbst für nötig, eröffnet er ein GitHub-Issue, beschreibt Problem und Begründung, und Dixie oder der Mensch setzt um. Der Agent hat also nicht die Fähigkeit verloren, zur eigenen Weiterentwicklung beizutragen — er hat die Form gewechselt: von "ich ändere Code" zu "ich formuliere präzise, was geändert werden sollte". Für einen Assistenten ist das zweite oft die wertvollere Fähigkeit.
agenticframework hebt genau dieses Muster auf Prozess-Ebene. Dort ist "das muss ein Mensch entscheiden" ein regulärer Rückgabewert, kein Fehlerzustand:
class GateDecisionStatus(StrEnum):
GO = "go"
NO_GO = "no_go"
RETRY = "retry"
NEEDS_HUMAN = "needs_human"
BLOCKED = "blocked"
NEEDS_HUMAN steht gleichberechtigt neben GO und NO_GO. Und es wird systematisch erzeugt: Ada, der Discovery-Agent, berechnet für jede Anforderungsanalyse einen Ambiguity-Score und setzt needs_human=True, sobald der Schwellwert überschritten ist oder Widersprüche zwischen Fakten erkannt werden — eine unklare Anforderung wird nicht heldenhaft interpretiert, sondern als Klärungsfall markiert. Tess emittiert needs_human, wenn ein Auftrag nicht unter das Ticket-Budget zerlegbar ist (Teil 4). Und die Gate-Policy mappt jede unbehandelte Exception auf NEEDS_HUMAN: Wo das System sich nicht sicher ist, rät es nicht — es übergibt.
Menschen als Rollen, nicht als Notbremse
Die Dokumentation von agenticframework bringt die Philosophie dahinter auf einen Satz: "HITL checkpoints are not escape hatches — they are designed gates." Der Mensch im Loop ist keine Ausnahmebehandlung, sondern hat drei definierte Rollen: der Clarifier löst Mehrdeutigkeiten in der Discovery-Phase per Q&A auf, der Resolver entscheidet bei erkannten Widersprüchen (VETO oder RESOLVE), der Approver gibt Phasenübergänge frei — ohne dessen explizites Sign-off wechselt die Pipeline keine Phase. Und jede dieser Entscheidungen wird als HumanDecision mit Status (requested/approved/rejected/overridden), Zeitstempeln und Entscheider im Run-Manifest festgehalten. Menschliche Urteile sind hier Audit-Objekte erster Klasse — genau wie Agenten-Outputs.
Autonomie ist kein Schieberegler, sondern viele
Der vielleicht wichtigste Punkt zum Schluss: Dieselbe Codebasis, die Self-Modification abgeschaltet hat, hat an anderer Stelle Autonomie ausgebaut — wintermute kann inzwischen proaktiv Nachrichten anstoßen (tägliche Briefings), gesteuert über die Standing Instructions. Aber auch diese Erweiterung trägt ihre Begrenzung im Design, wie der Modul-Docstring nüchtern festhält:
"""Standing Instructions — a versioned, human-edited config the agent reads.
[...] the file is maintained **by hand** on the host and mounted read-only;
the agent only *reads* it. There is no agent-write path, so a hallucination
can neither corrupt the config nor touch the code repo [...]
"""
Mehr Autonomie beim Handeln, null Autonomie beim Ändern der eigenen Regeln — im selben Feature. Das ist die eigentliche Lehre dieses Artikels: Die Frage "wie autonom darf ein Agent sein?" ist falsch gestellt. Die richtige Frage lautet: welche Fähigkeit darf wie autonom sein — und sie wird pro Fähigkeit beantwortet, revidierbar, mit dokumentierter Begründung. Autonomie ist kein Schieberegler. Es sind viele, und man sollte jeden einzeln anfassen können.
Fazit und Ausblick
Die Grenze der Autonomie ist kein Eingeständnis, dass Agenten nicht gut genug sind — sie ist das Ergebnis einer Rechnung: Was kostet die Absicherung einer Fähigkeit auf dem Hauptpfad, und steht das im Verhältnis zu ihrem Nutzen? Wo die Rechnung nicht aufgeht, ist die reife Antwort nicht "mehr Guardrails", sondern ein anderer Formfaktor — und ein Eskalationspfad, der als Feature gebaut ist, nicht als Verlegenheitslösung.
Im letzten Teil dieser Serie setzen wir alle Bausteine zusammen: die komplette Reise von der vagen Idee zum auditierbaren Release — durch alle sechs Phasen der Pipeline, mit typisierten Übergaben als rotem Faden.
Quellen: wintermute/LESSONS.md (Lesson #25, Zeilen 747–791), wintermute/agent/src/agent/personality.py (Self-Reflection-Block, Zeilen 86–107), wintermute/docs/GITHUB-TOOLS.md (Drei-Ebenen-Policy, Escalation Surface), wintermute/agent/src/agent/standing_instructions.py (Docstring Zeilen 1–16), wintermute/mcp-gateway/src/gateway/tools/github.py (_self_repo_guard); agenticframework/FRAMEWORK.md (HITL-Rollen Zeilen 199–216, Gate-Regeln), agenticframework/orchestrator/src/agentic_orchestrator/gates/decisions.py (GateDecisionStatus), gates/policy.py (unknown_error → NEEDS_HUMAN), kernel/models.py (HumanDecision), apps/intent-compiler/backend/src/agents/ada/discovery.py (needs_human bei Ambiguity/Konflikten).