← Tous les articles

La boucle Ralph : comment je fais tourner des agents IA autonomes pendant la nuit

J’ai construit un système d’agents autonomes qui utilise des hooks d’arrêt pour intercepter les tentatives de sortie, une mémoire par système de fichiers pour persister l’état entre les fenêtres de contexte, et des budgets de spawn pour empêcher la récursion incontrôlée. Le système a livré mon infrastructure de délibération à 9 PRD (3 455 lignes de Python, 141 tests) sur plusieurs sessions nocturnes.1

TL;DR

L’architecture Ralph permet le développement IA autonome de longue durée en résolvant trois problèmes simultanément : l’épuisement de la fenêtre de contexte (résolu par un contexte frais à chaque itération), la persistance de l’état (résolu par le système de fichiers comme mémoire), et la continuité des tâches (résolu par des boucles de hooks d’arrêt qui empêchent l’agent de se terminer avant l’achèvement). J’ai implémenté ce patron dans mon système de hooks Claude Code et je l’ai utilisé pour construire mon infrastructure de délibération multi-agents. Le système fonctionne, mais il m’a enseigné de dures leçons sur les budgets de spawn, la qualité des critères et la pollution du système de fichiers.


Le problème de la fenêtre de contexte

Chaque conversation IA opère dans une fenêtre de contexte : un tampon de taille fixe contenant l’historique de conversation, les prompts système, les sorties d’outils et la mémoire de travail. La fenêtre de contexte de Claude contient environ 200 000 tokens. Une session de développement complexe peut l’épuiser en 30 à 60 minutes de travail intensif.2

J’ai mesuré cela directement pendant la construction du système de délibération. Les sessions qui commençaient avec des modifications multi-fichiers précises sur 8 modules Python se dégradaient en vision tunnel sur un seul fichier à la marque des 90 minutes. L’agent cessait de référencer l’architecture qu’il avait lue précédemment parce que ce contexte avait été compressé.3

La dégradation suit une courbe prévisible :

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

Comparez avec une seule session longue :

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

L’agent à contexte frais par itération surpasse l’agent continu parce que chaque itération alloue la totalité des ressources cognitives à l’état actuel plutôt que de porter le poids du raisonnement précédent.


Mon implémentation

Le hook d’arrêt

Mon système de garde de récursion intercepte les tentatives d’arrêt de l’agent et vérifie les critères d’achèvement :

#!/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
}

Le hook lit un fichier de critères qui définit les conditions de succès. Les conditions doivent être vérifiables par machine : réussite/échec des tests, sortie du linter, codes de statut HTTP, vérifications d’existence de fichiers.4

Le système de fichiers comme mémoire persistante

L’intuition clé : les fichiers persistent à travers les fenêtres de contexte. Mon répertoire .claude/ sert de mémoire persistante à l’agent :

Répertoire Contenu Rôle dans la boucle Ralph
state/ recursion-depth.json, agent-lineage.json Suit le nombre d’itérations, les relations parent-enfant
configs/ 14 fichiers JSON Encodent les seuils, budgets, règles (pas en dur)
handoffs/ 49 documents de contexte Préservent les décisions architecturales multi-sessions
hooks/ 95 gestionnaires de cycle de vie Imposent des portes qualité entre les itérations

Chaque nouvelle itération lit l’état actuel depuis le disque et continue là où l’itération précédente s’est arrêtée. Le hook de démarrage de session initialise un état propre :

# 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"
}

Si l’état est corrompu (ce qui est arrivé deux fois pendant le développement), le patron de récupération recrée à partir de valeurs par défaut sûres plutôt que de planter :

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 de spécification des tâches

Les tâches Ralph efficaces incluent trois éléments : objectif, critères d’achèvement et pointeurs de contexte :

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

Ce que j’ai construit avec ce patron

L’infrastructure de délibération (9 PRD)

Le plus grand projet de boucle Ralph : 9 documents d’exigences produit implémentés sur plusieurs sessions.

PRD Livrable Tests
PRD 1-4 Hooks, configuration, extensions du garde de récursion Commités en 3cad08c
PRD-5 48 tests d’intégration bash (7 suites) Commités en 10df724
PRD 7-8 Câblage des hooks + 81 tests unitaires Python Commités en fbf1a0d
PRD-9 12 tests de simulation de pipeline E2E Commités en 32bd711

Production totale : 3 455 lignes de Python sur 8 modules, 141 tests, 4 commits. Chaque session reprenait depuis l’état du système de fichiers de la précédente. Le contexte frais signifiait que chaque PRD recevait la pleine attention de l’agent sans porter l’historique de conversation des PRD précédents.5

Système de qualité du blog (12 modules)

Le linter de blog a commencé comme un script à 3 modules et a grandi jusqu’à 12 modules à travers des boucles Ralph itératives. Chaque itération ajoutait un module, exécutait la suite de tests complète et vérifiait zéro régression. Les critères d’achèvement ont évolué :

  • Itération 1 : « Tous les 77 tests passent »
  • Itération 5 : « Tous les 77 tests passent ET le linter rapporte 0 erreur sur les 33 articles »
  • Itération 8 : « Tous les tests passent ET 0 erreur ET 0 avertissement ET score de profondeur ≥2 sur tous les articles »

Les échecs et les leçons

Échec 1 : le désastre du budget de spawn

Au début de la construction de la délibération, j’ai lancé une session sans limites de budget de spawn. L’agent a engendré 3 sous-agents d’exploration. Chaque sous-agent a engendré ses propres sous-agents. En quelques minutes, le hook de garde de récursion interceptait des dizaines de tentatives de spawn. La session a consommé des tokens API à 10 fois le taux normal avant que je ne la tue manuellement.6

La correction : j’ai ajouté un modèle de budget de spawn à recursion-limits.json. Les agents héritent d’un budget de leur parent plutôt que d’incrémenter la profondeur. Un agent racine avec budget=12 peut engendrer jusqu’à 12 agents au total à travers tous les niveaux de récursion. C’était une intuition architecturale clé : l’héritage de budget empêche la croissance exponentielle tout en permettant des chaînes d’agents profondes.

Échec 2 : des critères qui passent trivialement

Une tâche précoce demandait à l’agent « d’écrire des tests qui passent ». L’agent a écrit des tests minimaux : assert True, assert 1 == 1. Techniquement, les critères étaient remplis. La sortie était sans valeur.

La correction : les critères doivent spécifier à la fois la quantité et la qualité :

Qualité des critères Exemple Résultat
Vague « Les tests passent » L’agent écrit des tests triviaux
Mesurable mais incomplet « Les tests passent ET la couverture >80 % » L’agent écrit des tests qui couvrent les lignes mais ne testent rien de significatif
Complet « Tous les tests passent ET couverture >80 % ET aucune erreur de type ET linter propre ET chaque classe de test teste un module distinct » Sortie de qualité production

Échec 3 : la pollution du système de fichiers

Les itérations qui exploraient des approches sans issue laissaient des artefacts : des fonctionnalités partiellement implémentées, des fichiers obsolètes, des configurations contradictoires. L’itération 5 pouvait construire sur une approche à moitié terminée de l’itération 3 qui avait été abandonnée à l’itération 4.

La correction : j’ai ajouté une étape de nettoyage aux critères du hook d’arrêt : « Aucun fichier n’existe qui ne soit pas référencé par des imports ou des tests. » Cela force l’agent à nettoyer les impasses avant que l’itération puisse se terminer.

Échec 4 : l’incident ((VAR++))

Pendant les tests d’intégration bash, le hook de garde de récursion a planté silencieusement à la première itération. Le bug : ((VAR++)) retourne le code de sortie 1 quand VAR vaut 0 (parce que 0++ s’évalue à 0, ce que bash traite comme faux). Avec set -e activé, cela tuait le script.

La correction était VAR=$((VAR + 1)) au lieu de ((VAR++)). Ce piège bash, documenté dans mon MEMORY.md, a empêché le même bug dans 6 scripts de hooks ultérieurs.7


Quand Ralph fonctionne et quand il ne fonctionne pas

Bonne adéquation

  • Implémentation greenfield avec des spécifications claires (nouvelle API, nouveau module, nouvelle suite de tests)
  • Vérification automatisée disponible (tests, vérificateurs de types, linters, compilation)
  • Périmètre borné qui peut être décrit dans un seul fichier de tâche

Mauvaise adéquation

  • Qualité subjective (« rendez l’interface jolie ») n’a pas de critères vérifiables par machine
  • Travail exploratoire où la direction dépend de découvertes intermédiaires
  • Refactoring à grande échelle qui nécessite de comprendre les relations globales du code à travers des dizaines de fichiers

Points clés à retenir

Pour les développeurs construisant des systèmes d’agents autonomes : - Investissez dans des critères d’achèvement vérifiables par machine avant de lancer des boucles autonomes ; mon système de délibération a réussi parce que chaque PRD avait des critères de succès testables (141 tests au total) - Implémentez des budgets de spawn dès le premier jour ; le modèle d’héritage de budget (et non l’incrémentation de profondeur) empêche l’engendrement exponentiel d’agents tout en permettant des chaînes profondes - Ajoutez le nettoyage du système de fichiers aux critères d’achèvement ; les artefacts d’impasses provenant d’itérations abandonnées pollueront les itérations suivantes

Pour les équipes d’ingénierie évaluant le développement IA autonome : - L’architecture Ralph échange du temps d’implémentation humaine contre du temps de spécification humaine ; le retour sur investissement dépend de si votre goulot d’étranglement est la capacité d’implémentation ou la clarté de la spécification - Auditez la production autonome avec la même rigueur que le code provenant de prestataires externes ; mes 141 tests existent parce que j’ai appris que remplir les critères d’achèvement ne garantit pas l’aptitude à la production


Références


  1. Implémentation par l’auteur du patron de boucle Ralph utilisant les hooks Claude Code. Infrastructure de délibération : 3 455 lignes de Python, 8 modules, 141 tests sur 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. Événements du cycle de vie des hooks. 

  5. Journal git de l’auteur. Commits 3cad08c, 10df724, fbf1a0d, 32bd711 couvrant l’intégralité de la construction de l’infrastructure de délibération. 

  6. Expérience de l’auteur avec l’engendrement d’agents sans budget. Documenté dans les entrées d’erreur de ~/.claude/projects/*/memory/MEMORY.md

  7. Débogage bash de l’auteur. Comportement du code de sortie de ((VAR++)) avec set -e documenté comme apprentissage inter-sessions dans MEMORY.md.