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
Le test le plus simple, et faites-le, 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.
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.