← Alle Beitrage

Der Ralph-Loop: Wie ich autonome KI-Agenten über Nacht betreibe

Ich habe ein autonomes Agentensystem gebaut, das Stop-Hooks nutzt, um Beendigungsversuche abzufangen, Dateisystem-Speicher, um den Zustand über Kontextfenster hinweg zu persistieren, und Spawn-Budgets, um unkontrollierte Rekursion zu verhindern. Das System hat meine 9-PRD-Deliberationsinfrastruktur (3.455 Zeilen Python, 141 Tests) über mehrere nächtliche Sitzungen hinweg ausgeliefert.1

TL;DR

Die Ralph-Architektur ermöglicht langfristig laufende autonome KI-Entwicklung, indem sie drei Probleme gleichzeitig löst: Erschöpfung des Kontextfensters (gelöst durch frischen Kontext pro Iteration), Zustandspersistenz (gelöst durch das Dateisystem als Speicher) und Aufgabenkontinuität (gelöst durch Stop-Hook-Schleifen, die den Agenten daran hindern, vor der Fertigstellung zu terminieren). Ich habe dieses Muster in meinem Claude Code Hook-System implementiert und damit meine Multi-Agenten-Deliberationsinfrastruktur gebaut. Das System funktioniert, aber es hat mir harte Lektionen über Spawn-Budgets, Kriterienqualität und Dateisystem-Verschmutzung erteilt.


Das Kontextfenster-Problem

Jede KI-Konversation operiert innerhalb eines Kontextfensters: einem Puffer fester Größe, der Konversationsverlauf, Systemaufforderungen, Tool-Ausgaben und Arbeitsspeicher enthält. Claudes Kontextfenster fasst ungefähr 200.000 Token. Eine komplexe Entwicklungssitzung kann dieses innerhalb von 30–60 Minuten intensiver Arbeit erschöpfen.2

Ich habe dies direkt während des Baus des Deliberationssystems gemessen. Sitzungen, die mit präzisen Mehrdatei-Bearbeitungen über 8 Python-Module hinweg begannen, verschlechterten sich bis zur 90-Minuten-Marke zu Einzeldatei-Tunnelblick. Der Agent hörte auf, Architektur zu referenzieren, die er zuvor gelesen hatte, weil dieser Kontext wegkomprimiert worden war.3

Die Verschlechterung folgt einer vorhersehbaren Kurve:

Iteration 1: [200K tokens] → writes code, creates files
Iteration 2: [200K tokens] → reads files from disk, continues
Iteration 3: [200K tokens] → reads updated files, continues
...
Iteration N: [200K tokens] → reads final state, verifies criteria

Im Vergleich dazu eine einzelne lange Sitzung:

Minute 0:  [200K tokens available] → productive
Minute 30: [150K tokens available] → somewhat productive
Minute 60: [100K tokens available] → degraded
Minute 90: [50K tokens available]  → significantly degraded
Minute 120: [compressed, lossy]    → errors accumulate

Der Agent mit frischem Kontext pro Iteration übertrifft den kontinuierlichen Agenten, weil jede Iteration die vollen kognitiven Ressourcen dem aktuellen Zustand widmet, anstatt das Gewicht vorheriger Schlussfolgerungen mitzutragen.


Meine Implementierung

Der Stop-Hook

Mein Rekursionsschutz-System fängt Beendigungsversuche des Agenten ab und prüft Abschlusskriterien:

#!/bin/bash
# From recursion-guard.sh - simplified
CONFIG_FILE="${HOME}/.claude/configs/recursion-limits.json"
STATE_FILE="${HOME}/.claude/state/recursion-depth.json"

# Safe defaults with config override
MAX_DEPTH=2
MAX_CHILDREN=5
DELIB_SPAWN_BUDGET=2
DELIB_MAX_AGENTS=12

# Load config with validation
load_config() {
    if [[ -f "$CONFIG_FILE" ]] && command -v jq &>/dev/null; then
        config_depth=$(jq -r '.max_depth // 2' "$CONFIG_FILE")
        if [[ "$config_depth" =~ ^[0-9]+$ ]] && [[ "$config_depth" -gt 0 ]]; then
            MAX_DEPTH="$config_depth"
        fi
    fi
}

Der Hook liest eine Kriteriendatei, die Erfolgsbedingungen definiert. Die Bedingungen müssen maschinell verifizierbar sein: Testergebnisse (bestanden/nicht bestanden), Linter-Ausgabe, HTTP-Statuscodes, Dateiexistenzprüfungen.4

Das Dateisystem als persistenter Speicher

Die entscheidende Erkenntnis: Dateien überdauern Kontextfenster. Mein .claude/-Verzeichnis dient als persistenter Speicher des Agenten:

Verzeichnis Inhalt Rolle im Ralph-Loop
state/ recursion-depth.json, agent-lineage.json Verfolgt Iterationszähler, Eltern-Kind-Beziehungen
configs/ 14 JSON-Dateien Kodieren Schwellenwerte, Budgets, Regeln (nicht hartcodiert)
handoffs/ 49 Kontextdokumente Bewahren architektonische Entscheidungen über mehrere Sitzungen hinweg
hooks/ 95 Lebenszyklus-Handler Erzwingen Qualitäts-Gates zwischen Iterationen

Jede neue Iteration liest den aktuellen Zustand von der Festplatte und setzt dort fort, wo die vorherige Iteration aufgehört hat. Der Session-Start-Hook initialisiert einen sauberen Zustand:

# From session-start.sh - recursion state initialization
RECURSION_STATE_FILE="$RECURSION_STATE_DIR/recursion-depth.json"
# Initialize with safe defaults
{
  "depth": 0,
  "agent_id": "root",
  "parent_id": null,
  "initialized_by": "session-start"
}

Wenn der Zustand beschädigt wird (was während der Entwicklung zweimal passierte), stellt das Wiederherstellungsmuster den Zustand aus sicheren Standardwerten wieder her, anstatt abzustürzen:

if ! jq -e '.depth' "$RECURSION_STATE_FILE" &>/dev/null; then
    # Corrupted state file, recreate with safe defaults
    echo "- Recursion state recovered (was corrupted)"
fi

Format der Aufgabenspezifikation

Effektive Ralph-Aufgaben umfassen drei Elemente: Ziel, Abschlusskriterien und Kontextverweise:

OBJECTIVE: Implement multi-agent deliberation with consensus validation.

COMPLETION CRITERIA:
- All tests in tests/test_deliberation_lib.py pass (81 tests)
- post-deliberation.sh validates consensus above 70% threshold
- recursion-guard.sh enforces spawn budget (max 12 agents)
- deliberation-pride-check.sh passes 5 quality checks
- No Python type errors (mypy clean)

CONTEXT:
- Follow patterns in lib/deliberation/state_machine.py
- Consensus thresholds in configs/deliberation-config.json
- Spawn budget model: agents inherit budget, not increment depth

Was ich mit diesem Muster gebaut habe

Die Deliberationsinfrastruktur (9 PRDs)

Das größte Ralph-Loop-Projekt: 9 Product Requirement Documents, implementiert über mehrere Sitzungen hinweg.

PRD Ergebnis Tests
PRDs 1–4 Hooks, Konfiguration, Rekursionsschutz-Erweiterungen Committed als 3cad08c
PRD-5 48 Bash-Integrationstests (7 Suiten) Committed als 10df724
PRDs 7–8 Hook-Verdrahtung + 81 Python-Unit-Tests Committed als fbf1a0d
PRD-9 12 E2E-Pipeline-Simulationstests Committed als 32bd711

Gesamtausgabe: 3.455 Zeilen Python über 8 Module, 141 Tests, 4 Commits. Jede Sitzung knüpfte an den Dateisystemzustand der vorherigen an. Der frische Kontext bedeutete, dass jedes PRD die volle Aufmerksamkeit des Agenten erhielt, ohne Konversationsverlauf früherer PRDs mitzutragen.5

Blog-Qualitätssystem (12 Module)

Der Blog-Linter begann als 3-Modul-Skript und wuchs durch iterative Ralph-Loops auf 12 Module. Jede Iteration fügte ein Modul hinzu, führte die vollständige Testsuite aus und verifizierte null Regressionen. Die Abschlusskriterien entwickelten sich weiter:

  • Iteration 1: „Alle 77 Tests bestehen”
  • Iteration 5: „Alle 77 Tests bestehen UND Linter meldet 0 Fehler bei allen 33 Beiträgen”
  • Iteration 8: „Alle Tests bestehen UND 0 Fehler UND 0 Warnungen UND Tiefenwert ≥2 bei allen Beiträgen”

Die Fehlschläge und Lektionen

Fehlschlag 1: Das Spawn-Budget-Desaster

Früh im Deliberationsbau führte ich eine Sitzung ohne Spawn-Budget-Limits durch. Der Agent erzeugte 3 Explorations-Subagenten. Jeder Subagent erzeugte seine eigenen Subagenten. Innerhalb von Minuten fing der Rekursionsschutz-Hook Dutzende von Spawn-Versuchen ab. Die Sitzung verbrauchte API-Token mit der 10-fachen normalen Rate, bevor ich sie manuell beendete.6

Die Lösung: Ich fügte ein Spawn-Budget-Modell zu recursion-limits.json hinzu. Agenten erben ein Budget von ihrem Eltern-Agenten, anstatt die Tiefe zu inkrementieren. Ein Wurzel-Agent mit Budget=12 kann insgesamt bis zu 12 Agenten über alle Rekursionsebenen hinweg erzeugen. Dies war eine zentrale architektonische Erkenntnis: Budget-Vererbung verhindert exponentielles Wachstum, erlaubt aber dennoch tiefe Agentenketten.

Fehlschlag 2: Kriterien, die trivial bestehen

Eine frühe Aufgabe forderte den Agenten auf, „Tests zu schreiben, die bestehen.” Der Agent schrieb minimale Tests: assert True, assert 1 == 1. Technisch waren die Kriterien erfüllt. Das Ergebnis war wertlos.

Die Lösung: Kriterien müssen sowohl Quantität als auch Qualität spezifizieren:

Kriterienqualität Beispiel Ergebnis
Vage „Tests bestehen” Agent schreibt triviale Tests
Messbar, aber unvollständig „Tests bestehen UND Abdeckung >80%” Agent schreibt Tests, die Zeilen abdecken, aber nichts Sinnvolles testen
Umfassend „Alle Tests bestehen UND Abdeckung >80% UND keine Typfehler UND Linter sauber UND jede Testklasse testet ein eigenes Modul” Produktionsreifes Ergebnis

Fehlschlag 3: Dateisystem-Verschmutzung

Iterationen, die Sackgassen-Ansätze erkundeten, hinterließen Artefakte: teilweise implementierte Funktionen, veraltete Dateien, widersprüchliche Konfigurationen. Iteration 5 baute möglicherweise auf einem halbfertigen Ansatz aus Iteration 3 auf, der in Iteration 4 aufgegeben worden war.

Die Lösung: Ich fügte den Stop-Hook-Kriterien einen Bereinigungsschritt hinzu: „Es existieren keine Dateien, die nicht von Imports oder Tests referenziert werden.” Dies zwingt den Agenten, Sackgassen zu bereinigen, bevor die Iteration abgeschlossen werden kann.

Fehlschlag 4: Der ((VAR++))-Vorfall

Während der Bash-Integrationstests stürzte der Rekursionsschutz-Hook bei der ersten Iteration lautlos ab. Der Fehler: ((VAR++)) gibt Exit-Code 1 zurück, wenn VAR 0 ist (weil 0++ zu 0 ausgewertet wird, was Bash als falsch behandelt). Mit aktiviertem set -e beendete dies das Skript.

Die Lösung war VAR=$((VAR + 1)) anstelle von ((VAR++)). Diese Bash-Falle, dokumentiert in meiner MEMORY.md, hat denselben Fehler in 6 nachfolgenden Hook-Skripten verhindert.7


Wann Ralph funktioniert und wann nicht

Gute Passung

  • Greenfield-Implementierung mit klaren Spezifikationen (neue API, neues Modul, neue Testsuite)
  • Automatisierte Verifizierung existiert (Tests, Typprüfer, Linter, Kompilierung)
  • Begrenzter Umfang, der in einer einzelnen Aufgabendatei beschrieben werden kann

Schlechte Passung

  • Subjektive Qualität („mach die Benutzeroberfläche ansprechend”) hat keine maschinell verifizierbaren Kriterien
  • Explorative Arbeit, bei der die Richtung von Zwischenentdeckungen abhängt
  • Großflächiges Refactoring, das globales Codeverständnis über Dutzende von Dateien hinweg erfordert

Zentrale Erkenntnisse

Für Entwickler, die autonome Agentensysteme bauen: - Investieren Sie in maschinell verifizierbare Abschlusskriterien, bevor Sie autonome Schleifen starten; mein Deliberationssystem war erfolgreich, weil jedes PRD testbare Erfolgskriterien hatte (141 Tests insgesamt) - Implementieren Sie Spawn-Budgets vom ersten Tag an; das Budget-Vererbungsmodell (nicht Tiefen-Inkrementierung) verhindert exponentielles Agenten-Spawning, erlaubt aber dennoch tiefe Ketten - Fügen Sie Dateisystem-Bereinigung zu den Abschlusskriterien hinzu; Sackgassen-Artefakte aus aufgegebenen Iterationen verschmutzen nachfolgende Iterationen

Für Engineering-Teams, die autonome KI-Entwicklung evaluieren: - Die Ralph-Architektur tauscht menschliche Implementierungszeit gegen menschliche Spezifikationszeit; der ROI hängt davon ab, ob Ihr Engpass die Implementierungskapazität oder die Spezifikationsklarheit ist - Prüfen Sie autonome Ausgaben mit derselben Sorgfalt, die Sie auf Code von externen Auftragnehmern anwenden; meine 141 Tests existieren, weil ich gelernt habe, dass das Erfüllen von Abschlusskriterien keine Produktionsreife garantiert


Referenzen


  1. Implementierung des Ralph-Loop-Musters durch den Autor unter Verwendung von Claude Code Hooks. Deliberationsinfrastruktur: 3.455 Zeilen Python, 8 Module, 141 Tests über 4 Commits (2025–2026). 

  2. Anthropic, “Claude Models,” 2025. 

  3. Liu, Nelson F. et al., „Lost in the Middle: How Language Models Use Long Contexts,” TACL, 2024. 

  4. Anthropic, “Claude Code Documentation,” 2025. Hook-Lebenszyklus-Ereignisse. 

  5. Git-Log des Autors. Commits 3cad08c, 10df724, fbf1a0d, 32bd711 über den gesamten Aufbau der Deliberationsinfrastruktur. 

  6. Erfahrung des Autors mit unbudgetiertem Agenten-Spawning. Dokumentiert in ~/.claude/projects/*/memory/MEMORY.md-Fehlereinträgen. 

  7. Bash-Debugging des Autors. Exit-Code-Verhalten von ((VAR++)) mit set -e, dokumentiert als sitzungsübergreifendes Lernen in MEMORY.md.