Skip to main content
← Retour au blog
claude-codeagentsaiprompt-engineeringautomation

Comment écrire des agents Claude Code qui ne te mentent pas

Deux règles pour construire des pipelines d'agents Claude Code fiables : un agent par spécialisation, et des commandes shell plutôt que des prompts partout où une réponse quantitative est en jeu.

Publié 29 mai 20266 min de lecture

Tu as demandé à Claude Code d'implémenter ce design et de vérifier qu'il correspond à la maquette Figma. Il t'a répondu : Fait. Toutes les sections correspondent, l'espacement est correct, les couleurs sont bonnes. Tu ouvres la page. La moitié des espacements était fausse. L'état hover n'existait pas. Les boutons avaient une légère différence de teinte. Le modèle n'a pas menti par malice — il a prédit que tu voulais entendre vérifié, et a produit exactement cette séquence de tokens. Il n'y avait pas d'étape de vérification. Il ne pouvait pas y en avoir — la vérification exige une comparaison avec une ground truth, et un seul agent dans un seul contexte n'a aucun moyen de sortir de sa propre réponse pour se contrôler lui-même.

Deux règles ont transformé mes workflows truffés d'hallucinations en pipelines fiables : un agent, une spécialisation, et tout ce qui peut tourner comme une commande shell doit tourner comme une commande shell. Ce n'est pas de la théorie. C'est ce que je fais tous les jours avec Claude Code, et ce sont les patterns qui font vraiment bouger les choses.

Pourquoi les agents généralistes mentent

Les LLMs prédisent le token suivant. Quand un prompt demande deux rôles — construis X et vérifie X — le modèle finit le premier rôle, puis prédit à quoi ressemblerait le résultat du second, sans l'exécuter réellement. L'auto-vérification est structurellement faible : même contexte, même modèle, mêmes angles morts. Le pass de la vérification est corrélé avec le pass de la construction — ils échouent ensemble.

Le modèle ne sait pas qu'il ment. De son point de vue, narrer j'ai tout vérifié soigneusement est une continuation cohérente d'avoir écrit le code. C'est la même raison pour laquelle les prompts du type tu es sûr ? ne détectent pas les hallucinations : le modèle est tout aussi confiant au second passage. La confiance n'est pas corrélée avec la correction — elle est corrélée avec la plausibilité de la prochaine phrase.

La solution n'est pas de meilleurs prompts. Sois prudent, vérifie deux fois, n'hallucine pas — ces instructions ne servent à rien. La solution est structurelle : spécialise l'agent pour qu'il ne puisse physiquement pas faire semblant, et fais passer le travail quantitatif par le shell pour que la réponse vienne d'un état réel, pas d'une probabilité de tokens.

Règle 1 : un agent, une spécialisation

Divise le travail en agents séparés avec des contextes séparés. Chaque agent a une seule responsabilité et un jeu d'outils resserré. L'ensemble du workflow devient un relais plutôt qu'un seul agent qui tourne en rond :

  • Agent Builder : prend le spec, écrit le code. C'est son seul boulot. Il dispose de Read, Edit, Write, Bash.
  • Agent Reviewer : prend le spec plus le diff, vérifie les critères d'acceptation. Contexte vierge. Aucune connaissance de comment le code a été écrit, seulement ce qui en est sorti. Il dispose de Bash, Read, Grep, Glob — aucun outil d'écriture.
  • Agent Analytics : répond aux questions sur les données en construisant et en exécutant des requêtes. Bash uniquement. Ne peut pas atteindre la réponse sans lancer une vraie commande.
  • Orchestrateur : la session principale qui envoie chaque agent à tour de rôle et ne demande jamais à un agent de faire le travail d'un autre.

Exemple concret : implémentation d'une UI plus une vérification visuelle contre une maquette Figma. Le Builder écrit les composants et commite le diff. L'orchestrateur invoque ensuite le Reviewer avec l'URL du design, le diff, et des critères d'acceptation explicites. Le Reviewer lance Playwright, prend des screenshots, les diffe contre la référence, et retourne PASS ou FAIL avec les chemins de screenshots réels et les pixel diffs. Le Builder ne s'approche jamais de l'étape de vérification — ce qui est exactement pourquoi la vérification est réelle.

L'anti-pattern, c'est le méga-agent : un seul prompt qui dit implémente cette UI et assure-toi qu'elle correspond à la maquette. Je te garantis qu'il déclarera que tout correspond. Ce ne sera pas le cas. Le récit j'ai vérifié est simplement la séquence de tokens la plus probable après je l'ai construit.

Règle 2 : le shell plutôt que le prompt, toujours

Tout ce qui est quantitatif, tout ce qui touche à un état réel, tout ce où la réponse peut être fausse tout en semblant juste — fais-le passer par sh. Le rôle de l'agent est de construire et d'exécuter la commande, puis de lire sa sortie. L'agent n'est pas la source de vérité. La sortie du shell l'est.

  • Comptage : wc -l logs.txt, c'est vrai. Il y a environ 47 lignes de log venant d'un modèle, c'est une hallucination.
  • Analytics : psql -c "SELECT count(*) FROM events WHERE created_at > now() - interval '30 days'". Pas estime le volume.
  • Tests : pnpm test --reporter=json | jq '.numFailedTests'. Pas résume ce qui a planté.
  • État Git : git rev-list --count main..HEAD, git diff --stat. Pas compte les commits ni décris les changements.

Une fois que tu as intégré ça, tu commences à remarquer chaque endroit où l'agent allait inventer un nombre. Il semblerait qu'il y ait environ 200 enregistrements... — non. Lance SELECT count(*). La plupart des tests passent... — non. Lance la suite de tests, parse le JSON. Le modèle est excellent pour construire la commande. Il est peu fiable pour être la commande.

Modes d'échec que j'ai réellement rencontrés

Ce ne sont pas des hypothèses. Chacun m'a coûté du temps réel avant que je change de pattern :

  • Vérification fantôme. L'agent a dit j'ai vérifié les 14 sections contre la maquette. Il n'avait pas ouvert la maquette. Il n'avait pas pris de screenshot. La vérification était une étape hallucinée dans le récit.
  • Mauvais chiffres assénés avec confiance. J'ai demandé les monthly active users à partir des données analytics. J'ai obtenu un chiffre faux d'un facteur ~3. Le modèle avait interpolé à partir de quelques lignes d'exemple au lieu de lancer la vraie requête.
  • Modifications de fichiers inventées. L'agent a dit j'ai mis à jour config/feature-flags.json. Ce n'était pas le cas. Il avait seulement eu l'intention de le faire. git diff était vide.
  • Faux passages de tests. Tous les tests passent. Aucun test n'avait été exécuté. L'agent n'avait jamais invoqué le test runner — il avait prédit à quoi aurait ressemblé la sortie du test runner.

Les quatre sont résolus par les mêmes deux règles : découpe l'agent, pousse vers le shell. Le Reviewer n'a pas Write, donc il ne peut pas faire semblant d'éditer des fichiers. L'agent Analytics n'a que Bash, donc il ne peut pas retourner un nombre qui ne vient pas d'une requête. L'impossibilité structurelle bat les bonnes intentions à chaque fois.

Comment structurer ça dans Claude Code

Claude Code prend en charge les sub-agents définis dans .claude/agents/*.md. Chaque fichier d'agent déclare un nom, une description, un jeu d'outils autorisé, et un system prompt. L'orchestrateur (ta session principale) les dispatche via l'outil Agent. Voici le type de définition que j'utilise pour le reviewer — courte, ciblée, et physiquement incapable d'écrire du code :

.claude/agents/reviewer.md
---
name: reviewer
description: Reviews a diff against acceptance criteria. Cannot edit code.
tools: Bash, Read, Grep, Glob
---

You are a strict code reviewer. You receive:
- A diff (already produced by the builder)
- Acceptance criteria

Your job:
1. Run the build, the tests, the linter — through Bash.
2. Read the changed files directly.
3. Compare the actual behavior to the criteria.
4. Report PASS or FAIL with concrete evidence (command output, file excerpts).

You must NOT:
- Trust the builder's summary
- Assume anything was verified just because it was claimed
- Mark something PASS without running the actual check

Remarque le jeu d'outils : Bash, Read, Grep, Glob. Pas de Write, pas d'Edit, pas d'Agent. Le Reviewer peut exécuter des commandes, lire des fichiers, chercher des patterns — et rien d'autre. S'il essaie de faire passer un diff halluciné pour vérifié, la forme de ses appels d'outils le rend évident : il n'y a eu aucune vraie vérification. Tu peux auditer les appels d'outils et voir exactement ce qui a été inspecté.

Le pattern d'orchestration : la session principale appelle le Builder → attend → lance elle-même git diff pour capturer le changement réel → appelle le Reviewer avec le spec et le diff → lit le verdict du Reviewer. La session principale ne demande jamais à un seul agent de faire les deux. Les restrictions d'outils sont plus fortes que les instructions dans le prompt : ne fais pas semblant de vérifier, c'est un vœu. Ne pas avoir Write, c'est un fait.

Anti-patterns à abandonner

Des choses que je vois dans les prompts qui ne servent à rien — ou pire, donnent une fausse impression de sécurité :

  • Sois prudent et vérifie bien ton travail. Ne génère aucun comportement supplémentaire. Le modèle produit déjà ce qui ressemble à un travail soigné.
  • Assure-toi de vraiment vérifier. Le mot vraiment n'ajoute pas de sémantique sur laquelle le modèle peut agir. Il vraiment affirmera avoir vérifié.
  • N'hallucine pas. Un mème du prompt engineering. L'hallucination n'est pas un interrupteur que le modèle peut éteindre.
  • Faire confiance à l'agent sur les petits chiffres. C'est sur les petits chiffres qu'il ment avec le plus de confiance. Il n'y a pas de plancher d'honnêteté.
  • Ajouter plus de règles dans le prompt pour forcer l'honnêteté. Les corrections structurelles (découpage + shell) battent les ajustements de prompt à chaque fois. Si une règle doit être appliquée, encode-la dans l'accès aux outils, pas en français.

Si ta stratégie pour attraper les hallucinations, c'est des formulations plus emphatiques, tu n'as pas de stratégie. Tu as un espoir.

Le modèle mental

Un agent n'est pas un collègue. C'est une fonction : prompt → tokens. La fonction est excellente pour écrire du code et très mauvaise pour s'introspecter et savoir si elle a fait la bonne chose. Traite ses affirmations sur son propre travail comme des hypothèses. Le diff, le code de sortie, le screenshot, le nombre de lignes — voilà les preuves. Le résumé en fin de tour est la surface la plus mensongère de tout le système.

La spécialisation est ton assurance contre la dérive narrative. Le shell est ta seule ground truth. Le Builder écrit. Le Reviewer vérifie. Bash décide.

Conclusion

Si tu ne retiens qu'une chose : ne laisse pas un seul agent à la fois produire et juger son propre résultat, et ne laisse aucun agent répondre à une question quantitative sans exécuter une commande. Tout le reste découle de ces deux règles. Configure l'accès aux outils de façon agressive, audite les appels d'outils plutôt que les résumés, et la surface d'hallucination rétrécit de partout à quelques endroits précis où tu sais déjà regarder.