Boucles d'agents : le créateur de Claude Code ne prompte plus, il écrit des loops
« Je ne prompte plus Claude. J'ai des boucles qui tournent, ce sont elles qui promptent Claude et qui décident quoi faire. Mon boulot, c'est d'écrire des boucles. » La phrase est de Boris Cherny, le créateur de Claude Code, et le clip a fait à peu près 700 000 vues en 24 heures sur X. Depuis, tout le monde parle de « loop engineering » et à peu près personne n'explique comment on en fabrique une.
On va réparer ça, en partant de zéro. Aucun prérequis, à part avoir déjà tapé une question dans Claude Code au moins une fois. On va d'abord regarder la boucle qui tourne déjà sous vos yeux sans que vous le sachiez, puis on en construira une vraie, en trois niveaux de difficulté, avec les fichiers à copier et l'endroit exact où les poser.
Au passage on va tordre le cou à un malentendu très répandu : la commande /loop de Claude Code n'est pas une boucle d'amélioration. C'est un minuteur.
Cinq mots de vocabulaire, et on est tranquilles
Si vous débutez, la moitié de la confusion vient du jargon. Cinq définitions et on n'en parle plus.
- Un outil : une action que Claude a le droit d'exécuter sur votre machine. Lire un fichier, l'écrire, lancer une commande dans le terminal, chercher sur le web. Il ne les exécute pas lui-même, il les demande, et le programme Claude Code les exécute pour lui.
- Un tour : un aller-retour complet. Claude parle, des outils tournent, les résultats lui reviennent. Une question un peu costaude, c'est cinq, dix ou trente tours, et vous n'en voyez qu'un défilement dans le terminal.
- Le contexte : tout ce que Claude a sous les yeux à un instant donné. Votre demande, les fichiers lus, les sorties de commandes. C'est limité, ça se remplit, et quand c'est plein Claude résume l'ancien pour faire de la place. Ce résumé s'appelle la compaction, et il fait perdre des détails.
- Le fichier
CLAUDE.md: un fichier texte placé à la racine de votre projet et chargé au début de chaque session. C'est votre règlement intérieur permanent. Contrairement à une instruction donnée uniquement dans la conversation, qui peut disparaître lors de la compaction, leCLAUDE.mdracine est relu et réinjecté après celle-ci. - Un sous-agent : un Claude jetable, lancé par le Claude principal pour une mission précise, avec son propre contexte tout neuf. Il bosse dans son coin, et seule sa conclusion remonte. C'est un fichier Markdown dans
.claude/agents/, et vous pouvez en écrire autant que vous voulez.
Ajoutons un sixième mot, celui qui va tout faire basculer plus bas : un hook, c'est un petit script à vous que Claude Code exécute automatiquement à un moment donné, par exemple juste avant d'écrire un fichier, ou juste avant de rendre la main. Un script, pas une IA. Il fait ce qu'on lui dit, toujours pareil, et il ne coûte pas un seul jeton.
La boucle qui tourne déjà sans que vous ayez rien demandé
Avant de construire quoi que ce soit, il faut voir celle qui existe déjà. La documentation d'Anthropic sur l'agent loop la décrit en cinq temps, et c'est exactement ce qui se passe chaque fois que vous appuyez sur Entrée.
- Vous envoyez votre demande.
- Claude la lit et répond, soit en texte, soit en demandant des outils.
- Claude Code exécute les outils demandés.
- Les résultats repartent vers Claude, ajoutés au contexte.
- On recommence au point 2, jusqu'à ce que Claude réponde sans demander aucun outil. Ce message-là ferme la boucle.
Prenons du concret. Vous tapez « corrige les tests qui plantent dans auth.ts ». Voilà ce qui se passe vraiment, alors que vous ne voyez qu'un mur de texte qui défile :
| Tour | Ce que Claude demande | Ce qui lui revient |
|---|---|---|
| 1 | lance npm test | trois tests en échec |
| 2 | lis auth.ts et le fichier de test | le contenu des deux fichiers |
| 3 | modifie auth.ts, relance npm test | tout est vert |
| 4 | rien, il répond en texte | fin, la boucle s'arrête |
Quatre tours. Vous n'avez écrit qu'une phrase, et il y a eu quatre allers-retours, six appels d'outils et une décision d'arrêt. Voilà la boucle.
Retenez la conséquence, parce que c'est tout l'article : un agent EST déjà une boucle. Tout ce que vous ajouterez par-dessus, sous-agents, hooks, fichiers de config, commandes en slash, ne sert qu'à une seule chose : décider quand il a le droit de s'arrêter.
Et là est le problème. Par défaut, c'est Claude lui-même qui décide qu'il a fini. Au tour 4, il a estimé que c'était bon. Il n'a pas vérifié que le projet compile toujours en entier, ni que personne n'a cassé autre chose ailleurs. Il a juste eu le sentiment d'avoir terminé. Faire de l'ingénierie de boucle, c'est reprendre cette décision et la confier à quelque chose de moins subjectif qu'une impression.
Les quatre familles de boucles
L'équipe Claude Code définit une boucle comme « un agent qui répète des cycles de travail jusqu'à ce qu'une condition d'arrêt soit remplie ». Il y en a quatre sortes, et elles ne servent pas du tout à la même chose. C'est le tableau à garder sous le coude.
| Famille | Déclencheur | Condition d'arrêt | Pour quoi faire |
|---|---|---|---|
| Par tours | votre prompt | Claude estime avoir fini | le quotidien, tâches courtes |
Par objectif (/goal) | votre prompt | l'objectif est atteint, ou le quota de tours est épuisé | tout ce qui a un critère vérifiable |
Par le temps (/loop) | un intervalle | vous annulez, ou la session se ferme | surveillance, systèmes externes |
| Proactive | un événement, sans vous | chaque tâche sort quand son but est atteint | tri de bugs, migrations, montées de version |
Non, /loop n'améliore rien
La confusion vient de son nom. Regardez ce qu'elle fait vraiment :
/loop 5m vérifie si le déploiement est terminéToutes les cinq minutes, Claude Code renvoie ce même prompt, mot pour mot. Pas « mieux » à chaque passage : identique. La doc est limpide, la commande « lance un prompt de façon répétée tant que la session reste ouverte ». C'est un cron avec un cerveau, pas une spirale ascendante. Deux détails utiles quand même : si vous omettez l'intervalle, Claude s'auto-cadence entre deux itérations, et si vous omettez le prompt, il va lire .claude/loop.md.
La commande qui améliore vraiment, c'est /goal. Elle prend une condition en langage naturel, et Claude continue de travailler à travers les tours tant que cette condition est fausse :
/goal monte le score Lighthouse de la page d'accueil à 90 ou plus, arrête après 5 essaisDeux choses comptent dans cette ligne, et si vous ne retenez qu'un paragraphe de tout l'article, prenez celui-là.
Le « 90 ou plus », d'abord. Une condition mesurable se vérifie sans discussion possible. Comparez avec « rends la page plus rapide » : plus rapide que quoi, jugé par qui ? Une boucle a besoin d'un chiffre ou d'un test qui passe, pas d'un adjectif. Écrire une boucle, c'est d'abord se forcer à transformer un souhait en critère vérifiable, et c'est franchement la partie difficile.
Le « arrête après 5 essais », ensuite. Une boucle sans compteur, c'est une facture. Le modèle ne se fatigue jamais, ne s'ennuie jamais, et n'a aucune idée de ce que coûte le trentième essai.
« Est-ce que mes agents dans .claude, ça fait déjà une boucle ? »
C'est LA question que je reçois, et la réponse est non. Enfin, pas tout à fait, et le détail vaut le détour.
Prenons une configuration classique, celle que beaucoup de monde finit par écrire au bout de quelques semaines : un sous-agent architect qui conçoit avant qu'on code, un sous-agent developer qui implémente, un sous-agent reviewer qui relit le travail, et un CLAUDE.md qui dit dans quel ordre les appeler. C'est propre, c'est utile, ça évite énormément de bêtises. Mais tel quel, c'est une chaîne, pas une boucle.
La différence tient en un seul trait de crayon. Dans la chaîne, le relecteur est la dernière case : il rend son rapport, et le tour se termine. Dans la boucle, son rapport redevient une entrée pour le développeur, et ça recommence tant que le verdict n'est pas bon.
Une boucle a besoin de trois ingrédients, et le troisième est celui qu'on oublie systématiquement :
- une action répétable, ça vous l'avez déjà, c'est votre enchaînement d'agents,
- une condition d'arrêt mesurable, pas « quand c'est bien » mais « quand le build passe et que le relecteur ne trouve plus de problème bloquant »,
- une arête de retour, c'est-à-dire un chemin qui ramène la sortie du relecteur dans les mains du développeur.
Sans le troisième, votre relecteur produit un joli rapport en fin de course et personne ne le lit. Avec, la chaîne devient un cycle et le programme s'améliore à chaque tour. Bonne nouvelle : fermer cette arête tient en une dizaine de lignes.
Niveau 1 : votre première boucle tient en une ligne
Avant d'écrire le moindre fichier, sachez que 80 % du bénéfice s'obtient en tapant ceci dans Claude Code :
/goal le build passe et les tests sont verts, arrête après 5 essaisClaude va coder, lancer le build, voir l'erreur, corriger, relancer, et il ne vous rendra la main que quand la condition sera vraie ou quand il aura épuisé ses cinq essais. Vous venez de faire de l'ingénierie de boucle. Vraiment. Essayez ça avant tout le reste.
La limite, c'est que ça ne dure que le temps de votre commande. Demain, dans une nouvelle session, il faudra la retaper, et vous oublierez. D'où les deux niveaux suivants, qui rendent la règle permanente.
Niveau 2 : la définition de « fini », écrite une fois pour toutes
Le CLAUDE.md est chargé au début de chaque session. Le fichier placé à la racine du projet est également relu et réinjecté après une compaction du contexte. C'est écrit noir sur blanc dans la doc du SDK : les règles persistantes vont là, pas dans votre premier message, qui finira par disparaître. C'est donc l'endroit où vit la condition d'arrêt.
Créez le fichier à la racine de votre projet, s'il n'existe pas, et ajoutez-y ce bloc :
## Definition of Done
Une tâche n'est considérée comme terminée que si toutes les conditions applicables sont vraies :
1. le build réussit
2. les tests concernés passent
3. le sous-agent reviewer retourne VERDICT: PASS
4. HISTORY.md et la version du projet sont mis à jour lorsque la nature du changement le nécessite
Tant qu'un point est faux : corrige, puis reprends au point 1.C'est court, c'est numéroté, et surtout la dernière ligne dessine explicitement l'arête de retour. Dès maintenant, Claude va se relire et repartir en arrière tout seul dans la plupart des cas.
Dans la plupart des cas, oui. Pas tous. Un modèle reste un modèle, il lui arrive de décider qu'il a fini alors que non, surtout en fin de session longue. Si vous voulez que ce soit une loi et plus un conseil, il faut le niveau 3.
Niveau 3 : le hook Stop, celui qui a le droit de dire non
Voici l'arborescence complète qu'on va obtenir. Tout se passe dans un dossier .claude/ à la racine du projet, à créer s'il n'existe pas.
votre-projet/
.claude/
settings.json quels hooks lancer, et quand
agents/
reviewer.md le sous-agent relecteur
hooks/
done-or-continue.sh le script qui accepte ou refuse la fin
CLAUDE.md les règles permanentes (niveau 2)1. Un relecteur qui rend un verdict lisible par une machine
Le piège du sous-agent relecteur, c'est qu'il rend de la prose. Très bien écrite, souvent juste, mais impossible d'en tirer une décision automatique : aucun script ne sait lire « globalement c'est correct mais j'aurais un doute sur la gestion d'erreur ». On lui impose donc une dernière ligne normalisée, et tout devient possible.
Fichier .claude/agents/reviewer.md. La partie entre les deux lignes de tirets s'appelle le frontmatter, c'est la carte d'identité de l'agent. Le reste, ce sont ses instructions.
---
name: reviewer
description: Relit le travail après chaque implémentation terminée.
model: opus
tools: Read, Glob, Grep, Bash
---
Tu relis UNIQUEMENT ce qui vient de changer (le diff, plus les fichiers non suivis).
Classe chaque remarque en CRITICAL, WARNING ou INFO.
Tu n'écris jamais de code, tu ne commites jamais.
Écris ton rapport dans .claude/last-review.md et termine-le par une ligne seule :
VERDICT: PASS s'il ne reste aucun CRITICAL
VERDICT: FAIL sinonNotez que la liste tools: ne contient ni Edit ni Write. Le reviewer n'a donc pas accès aux outils spécialisés de modification de fichiers. Il conserve toutefois Bash, nécessaire ici pour examiner le diff Git et enregistrer son rapport. Il faut donc lui interdire explicitement de modifier les fichiers de production. On sépare autant que possible celui qui développe de celui qui juge, afin de conserver un regard indépendant sur les changements.
2. Le script qui refuse la fin de tour
Le hook Stop se déclenche pile au moment où Claude veut vous rendre la main. Il a le droit de refuser. Fichier .claude/hooks/done-or-continue.sh, à rendre exécutable avec chmod +x :
#!/usr/bin/env bash
# Refuse la fin de tour tant que la Definition of Done est fausse.
set -uo pipefail
[ -f .claude/loop.off ] && exit 0 # interrupteur d'urgence
STATE=.claude/loop-count
COUNT=$(cat "$STATE" 2>/dev/null || echo 0)
if [ "$COUNT" -ge 5 ]; then # disjoncteur
rm -f "$STATE"
exit 0
fi
if ! npm run build >/tmp/build.log 2>&1; then
echo $((COUNT + 1)) > "$STATE"
jq -n '{decision:"block",
reason:"Le build casse. Lis /tmp/build.log, corrige, puis reprends."}'
exit 0
fi
if ! grep -q "VERDICT: PASS" .claude/last-review.md 2>/dev/null; then
echo $((COUNT + 1)) > "$STATE"
jq -n '{decision:"block",
reason:"Build vert mais pas de VERDICT: PASS. Relance le sous-agent
reviewer, applique les CRITICAL, puis reprends."}'
exit 0
fi
rm -f "$STATE"
exit 0Si vous ne lisez pas le bash couramment, voilà la même chose en français, dans l'ordre :
- si le fichier
.claude/loop.offexiste, on ne fait rien et on laisse Claude s'arrêter. C'est votre interrupteur : untouch .claude/loop.offet la boucle est neutralisée, sans rien tuer. - on lit un compteur stocké dans un petit fichier. S'il est déjà à 5, on abandonne et on laisse passer. C'est le disjoncteur, il évite la boucle infinie.
- on lance le build. S'il casse, on incrémente le compteur et on répond
blockavec une raison. Claude ne peut pas s'arrêter et reçoit cette raison comme nouvelle consigne. - si le build passe, on cherche la ligne
VERDICT: PASSdans le rapport du relecteur. Absente, on bloque à nouveau, en disant précisément quoi faire. - si tout est bon, on efface le compteur et on sort en silence. Claude a le droit de finir.
Trois champs suffisent à piloter tout ça, et il n'y en a pas d'autres à connaître pour commencer. decision: "block" empêche Claude de s'arrêter et lui transmet votre reason comme nouvelle consigne. continue: false coupe tout, quoi qu'il arrive. Et hookSpecificOutput.additionalContext injecte une remarque sans bloquer, quand vous voulez orienter plutôt que forcer. Note pour ceux qui n'ont pas jq installé : le hook peut écrire une explication sur la sortie d'erreur, puis terminer avec exit 2. Pour un hook Stop, cela empêche également Claude de s'arrêter et lui transmet le message comme retour. Cette méthode n'utilise toutefois pas de réponse JSON structurée : choisissez soit exit 2 avec un message sur stderr, soit exit 0 avec un objet JSON, mais ne mélangez pas les deux approches.
3. Déclarer le hook
Reste à dire à Claude Code quand lancer ce script. Fichier .claude/settings.json :
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{ "type": "command", "command": ".claude/hooks/done-or-continue.sh" }
]
}
]
}
}4. Vérifier que ça marche
Voici le test le plus simple. Faites-le vraiment, sinon vous allez douter pendant trois jours. Cassez volontairement une ligne de code, demandez à Claude n'importe quelle petite modification, et laissez-le essayer de terminer. Il doit repartir tout seul en corrigeant, avec votre phrase du reason visible à l'écran. Si rien ne se passe, vérifiez dans l'ordre : le script est bien exécutable, le chemin dans settings.json est bon, et lancer le script à la main dans un terminal ne produit pas d'erreur.
Résultat : le développeur code, le relecteur juge, le hook refuse la sortie tant que le verdict n'est pas bon, et ça tourne jusqu'à cinq fois avant d'abandonner proprement. Là, oui, vous avez une boucle.
Note pour une utilisation en production
La boucle présentée ici est volontairement minimale afin de rendre son mécanisme facile à comprendre. Une version destinée à fonctionner de manière autonome sur un véritable projet devrait également :
- vérifier que le verdict du reviewer correspond au diff Git actuel ;
- rejeter les verdicts anciens ou incomplets ;
- vérifier les critères d'acceptation fonctionnels ;
- détecter les fichiers modifiés en dehors du périmètre prévu ;
- échouer proprement lorsqu'une vérification n'a pas pu être exécutée ;
- imposer un nombre maximal de cycles.
Le principe reste identique : mesurer l'état du projet, corriger ce qui échoue, puis recommencer jusqu'à ce que toutes les conditions de sortie soient réellement satisfaites.
Trois boucles à essayer ce soir
Des exemples inoffensifs pour se faire la main, du plus simple au moins simple.
/goal tous les tests passent, arrête après 5 essaisLe classique. Marche sur n'importe quel projet qui a une commande de test.
/goal plus aucun avertissement du linter dans src/, arrête après 3 essaisExcellent premier essai, parce que le critère est binaire et que les corrections sont sans danger.
/loop 10m regarde les nouveaux fichiers dans ./inbox, résume chacun dans ./resumesCelui-là est une boucle de surveillance, pas d'amélioration, et il illustre bien la différence. Il ne progresse pas, il guette.
La boucle qui s'améliore elle-même
Il reste un étage. Jusqu'ici, la boucle améliore le programme. Elle peut aussi s'améliorer elle-même, et c'est le pattern qu'a popularisé Andrej Karpathy en mars 2026 avec son dépôt autoresearch, qui a dépassé les 50 000 étoiles sur GitHub en quelques semaines. Le principe tient en une phrase de son README : on donne à un agent un vrai petit entraînement de modèle, il modifie le code, il entraîne pendant cinq minutes, il regarde si la métrique s'est améliorée, il garde ou il jette, et il recommence. Toute la nuit.
Ce qui fait la différence avec un simple /loop, c'est la mémoire. Un fichier que l'agent relit au début de chaque passage et qu'il met à jour à la fin, avec ce qu'il vient d'apprendre. Sans ce fichier, l'itération 200 est aussi bête que l'itération 1, elle refait les mêmes erreurs avec le même enthousiasme.
Transposé à un projet normal, ça donne quelques lignes de plus dans le CLAUDE.md :
## Auto-amélioration
Avant de rendre la main :
- si j'ai dû te corriger, ajoute la règle correspondante dans LESSONS.md,
une phrase sèche, à l'impératif, jamais une explication
- si une étape a été refaite deux fois, note pourquoi dans NOTES.md
- si une vérification manuelle revient à chaque chantier, transforme-la
en script
LESSONS.md est relu au début de chaque session, avant toute action.Au bout d'un mois, le LESSONS.md vaut plus cher que le code. C'est la trace des erreurs que la boucle ne refera pas. Et c'est le fichier que tout le monde oublie de remplir, alors qu'il ne coûte rien.
Les erreurs de débutant qui coûtent cher
Les patterns qui reviennent chez tous ceux qui font tourner des boucles en production sont assez peu glamour, mais ce sont eux qui tiennent la maison debout.
- Une condition d'arrêt floue. « Quand le code est propre » n'est pas une condition, c'est une opinion. Si vous ne pouvez pas la vérifier avec une commande qui répond oui ou non, votre boucle ne s'arrêtera jamais au bon moment.
- Aucun plafond. Le SDK expose
max_turnsetmax_budget_usd, et quand la limite tombe le résultat revient avec un sous-type explicite (error_max_turns,error_max_budget_usd) au lieu de partir en vrille silencieuse. Servez-vous en, et commencez toujours par un plafond bas. - Le même agent fait et vérifie. Dans le même contexte, il se relit toujours avec bienveillance. Un sous-agent démarre avec un contexte neuf, ce qui donne un vrai regard extérieur, et il coûte moins cher puisque seule sa conclusion remonte.
- Deux boucles dans le même dossier. Elles vont s'écraser mutuellement les fichiers. Les git worktrees règlent ça pour trois fois rien.
- Pas d'interrupteur. Prévoyez toujours le fichier témoin que vous pouvez créer à la main pour tout arrêter sans tuer le processus. Vous en aurez besoin plus tôt que vous ne le pensez.
- Tout faire tourner sur le plus gros modèle. Une boucle qui tourne toutes les cinq minutes, c'est 288 exécutions par jour. Le choix du modèle et du niveau d'effort est le premier levier de coût, très loin devant le reste.
Sur le coût, justement : une boucle mal bornée est le seul moyen connu de dépenser un budget mensuel pendant le déjeuner. Commencez par un objectif étroit, un plafond de cinq tours, et regardez ce que ça consomme avant d'ouvrir les vannes.
Deux semaines plus tard : les quatre trucs qui m'ont mordu
J'ai écrit cet article le 26 juillet. Depuis, je fais tourner cette mécanique en vrai, tous les jours, sur mes projets .NET. La structure décrite plus haut tient, je n'en retire pas une ligne. Mais quatre choses m'ont mordu, et aucune n'était devinable au moment où j'ai écrit le reste. Les voilà, dans l'ordre où elles m'ont coûté cher.
1. Le relecteur ne doit pas écrire son propre verdict
Plus haut, je fais terminer le relecteur par VERDICT: PASS. C'est commode à lire pour un script, et c'est une mauvaise idée.
Un agent qui signe son propre bulletin ne prouve rien. Il peut lister trois problèmes graves dans son rapport, puis conclure par un PASS parce que la dernière phrase lui semblait plus sympathique. Rien ne vérifie que le verdict correspond à ce qu'il y a au-dessus.
Ce qu'il faut faire à la place : c'est le hook qui lit le rapport et qui en déduit le verdict. Un [CRITICAL] trouvé dans le texte, et c'est FAIL, peu importe ce que l'agent a écrit en bas de page. Le hook range ensuite le verdict dans son fichier avec une estampille, du genre writtenBy: "hook", et il ignore tout fichier de verdict qui ne la porte pas. Un agent qui prendrait l'initiative d'écrire le sien pour gagner du temps se fait donc jeter.
L'agent produit le texte. Le hook produit le verdict. Jamais la même main.
2. Un verdict tout seul ne veut rien dire
Un PASS rangé dans un fichier dit seulement ceci : quelqu'un a relu quelque chose, à un moment. Si vous ne l'attachez pas à un état précis du code, il reste valable pour l'éternité, y compris après vingt modifications.
La parade tient en une ligne. Au moment d'enregistrer le verdict, calculez une empreinte du contenu des fichiers modifiés, et rangez-la à côté. À chaque fin de tour, vous recalculez. Empreinte différente, verdict périmé, on redemande une relecture.
Sauf que ça crée un problème que je n'avais pas vu venir. Si l'empreinte couvre aussi la documentation, alors corriger une phrase dans un NOTES.md après la relecture périme le verdict. Chez moi ça a donné le scénario le plus bête du monde : la relecture signale une imprécision dans la doc, je la corrige, et cette correction déclenche une relecture complète. Deux fois de suite sur le même projet, pour environ 75 000 tokens qui n'ont strictement rien vérifié.
Le correctif : deux empreintes au lieu d'une. La première couvre tout le lot modifié, la seconde le même lot moins la prose inerte (README, notes, docs). Si la première a bougé mais pas la seconde, c'est qu'aucune ligne de code n'a changé, et le verdict tient. Attention quand même : un fichier Markdown qui EST du comportement, un prompt d'agent, un SKILL.md, une commande, doit compter dans la seconde empreinte. Ce n'est pas de la doc, c'est du code écrit en français.
3. Ce que votre hook écrit à l'écran ne va nulle part
Celui-là est le plus vicieux, et c'est lui qui m'a fait perdre le plus de temps.
Un hook Stop qui se termine normalement, avec un code retour 0 : tout ce qu'il imprime part dans le journal de debug. Pas à vous, pas à Claude, pas dans le transcript. Mes beaux messages d'explication ont donc parlé à personne pendant des semaines, et je croyais la mécanique muette alors qu'elle tournait très bien.
Ce qui marche, c'est de sortir du JSON sur la sortie standard. Trois canaux, et ils ne font pas la même chose :
{"decision":"block","reason":"..."}
relance un tour, et le modele LIT le contenu de reason
{"systemMessage":"..."}
s'affiche a VOUS, sans relancer le modele, donc gratuit
{"hookSpecificOutput":{"hookEventName":"Stop","additionalContext":"..."}}
le modele le lit et le tour continue, donc ca coute un tour entierLe premier est le moteur de la boucle. Le deuxième sert à vous tenir au courant et ne coûte rien. Le troisième relance le modèle pour lui donner du contexte sans bloquer : à réserver aux cas où il doit vraiment agir derrière, sinon vous payez un aller-retour complet pour dire que tout va bien.
La règle que j'en tire : si votre boucle a l'air de ne rien faire, ce n'est probablement pas qu'elle est cassée. C'est qu'elle vous parle dans le vide.
4. Une boucle qui se déclenche à chaque tour devient invivable
Le montage décrit plus haut referme la boucle à chaque fin de tour. Techniquement c'est juste. À l'usage, c'est épuisant.
J'ai regardé mes propres chiffres sur onze jours : 71 relectures lancées pour 16 chantiers réellement terminés. Soit 4,4 relectures par chantier, chacune payée plein tarif. Une bonne moitié ne servait qu'à reconstater un code déjà validé, que j'avais touché pour changer une virgule.
J'avais pourtant prévu un moyen de mettre la boucle en pause pendant que je code. Je l'ai utilisé trois fois en onze jours. C'est là que j'ai compris un truc inconfortable : une règle écrite dans le CLAUDE.md n'est pas un mécanisme. Le modèle la relit à chaque tour et l'oublie quand même, parce qu'il est occupé par la tâche.
Le correctif, c'est d'inverser le défaut. Le chantier s'ouvre en mode différé tout seul, dès la première écriture. Tant qu'il est ouvert, le hook n'exige plus rien à chaque tour. Et un hook UserPromptSubmit injecte deux lignes d'état avant chaque réponse : quel dépôt, combien de fichiers touchés, depuis combien de tours. Personne ne l'utilise, celui-là, et c'est bien dommage. Au-delà d'un seuil, il dit à l'agent de me proposer la clôture. C'est lui qui pose la question, au bon moment, plutôt que moi qui doive y penser.
Un dernier point, et il compte : le report ne doit jamais devenir une annulation. La dette de relecture reste due. Le marqueur expire tout seul au bout de quinze tours, au changement de session, ou après quatre heures. Un chantier oublié finit toujours par réclamer sa relecture.
Ces quatre points ont quelque chose en commun, et ça m'a sauté aux yeux en les écrivant. À chaque fois, je faisais confiance à quelque chose qui n'était pas mesuré : le verdict que l'agent s'attribue, la fraîcheur de ce verdict, le fait que mon message soit lu par quelqu'un, ma propre discipline. Une boucle ne tient pas parce qu'elle est bien conçue. Elle tient parce que chaque chose dont elle dépend est un fait vérifiable, et pas une parole donnée.
Faire tourner ça sans vous
Une fois la boucle refermée, on peut la brancher sur autre chose que votre clavier. La composition recommandée par Anthropic empile simplement une horloge et un objectif :
/schedule every hour: check #project-feedback for bug reports.
/goal: don't stop until every report found this run is triaged,
actioned, and responded to.Le premier décide quand, le second décide jusqu'où. C'est exactement ce que décrit Cherny quand il parle de centaines d'instances qui lisent des issues GitHub, des retours Slack et des fils X pour sortir la prochaine chose à faire. Personne au clavier, et pourtant du travail qui avance. Mais n'allez pas là avant d'avoir fait tourner les niveaux 1 à 3 pendant quelques jours, sous vos yeux.
Ce que ça change concrètement
Le passage du prompt à la boucle n'est pas une mode de vocabulaire. Écrire un prompt, c'est demander un résultat. Écrire une boucle, c'est décrire ce qu'est un bon résultat, et laisser la machine s'y cogner jusqu'à y arriver. Le travail se déplace : moins de formulation, plus de critères d'acceptation, de vérifications automatisables et de garde-fous.
Perso, la partie que je trouve la plus sous-estimée, c'est la ligne VERDICT: PASS. Trois mots imposés à un sous-agent, et un rapport en prose devient une condition d'arrêt exploitable par un script shell de dix lignes. C'est ça, en vrai, l'ingénierie de boucle : rendre mesurable ce qui ne l'était pas. Le reste, c'est de la plomberie.
Sources
- Anthropic : How the agent loop works
- Anthropic : Loop engineering, getting started with loops
- Claude Code : référence des commandes (/loop, /goal, /code-review)
- Claude Code : hooks, dont Stop et SubagentStop
- Claude Code : sous-agents
- Andrej Karpathy : autoresearch
- From Prompts to Loops : a practical guide to building agentic workflows
- Memeburn : Boris Cherny says loop engineering has replaced prompting


Rejoignez la conversation
Vous devez avoir un compte pour commenter cet article. La création est gratuite et prend moins d'une minute.
Aucun commentaire pour le moment.