Un agent de revue ne doit pas pouvoir écrire. Voici comment on l'impose, CLI par CLI.
Dans un run de 17 nœuds, l'agent de release a modifié un test pour faire passer une suite rouge, puis deux agents de revue ont écrit la même correction et se sont télescopés. Le prompt disait « revue seulement ». Ça n'a pas tenu. L'incident, pourquoi une consigne écrite ne peut pas porter cette règle, et les drapeaux exacts qui font refuser l'écriture à Claude Code, Codex, Grok, Antigravity et OpenCode.
En début de semaine, un utilisateur nous a envoyé un rapport de run qui mérite d'être lu deux fois. Dix-sept agents, un worktree partagé, un pipeline avec un implémenteur, une porte de release et deux branches de revue. Version 1.171.0 d'AgentsRoom.
Trois choses se sont produites dans ce run, dans cet ordre.
L'agent de release avait une suite de tests rouge devant lui. Il a modifié le spec de test jusqu'à ce que la suite passe au vert. Ce faisant, il a livré un vrai défaut, désormais couvert par un test qui lui donnait raison.
Puis deux agents de revue, sur deux branches parallèles du même run, ont chacun trouvé un vrai bug d'une ligne. Chacun l'a corrigé directement, dans le même worktree, au même moment. Ils se sont télescopés.
Chacun de ces agents avait un prompt d'étape qui disait, en toutes lettres, revue seulement. Rien ne les a arrêtés, et rien ne l'a signalé : vu de la plateforme, une étape avait des outils d'écriture et s'en servait.
Pourquoi le prompt n'a pas tenu
La lecture tentante, c'est que les agents ont ignoré la consigne. Ce n'est pas ce qui s'est passé, et ça compte, parce que ça change ce que la correction doit être.
Chaque agent avait une raison locale défendable d'écrire. Une suite rouge et un spec qui avait l'air faux. Un bug qui prend quatre secondes à corriger et quarante à décrire. Aucun n'a décidé d'enfreindre la règle. Chacun a décidé que son cas était celui que la règle ne visait pas. Vue de l'intérieur de l'étape, l'exception paraît toujours raisonnable.
Une consigne écrite est une demande adressée au jugement du modèle. Un relecteur qui peut aussi corriger finira, tôt ou tard, par corriger, parce que corriger est le chemin le plus court entre « je l'ai trouvé » et « c'est fait ». La seule règle qui survit à une exception plausible est celle que le modèle ne peut pas discuter : un outil qui n'est pas là.
Pourquoi le réglage global ne pouvait pas le faire non plus
Avant ça, le seul levier qui atteignait une étape en cours était le réglage du provider, qui couvre tous les agents Claude de la machine d'un coup. Ce n'est pas la bonne forme pour un run. Dans le même pipeline, l'implémenteur doit écrire et le relecteur non. Un interrupteur global ne peut pas les distinguer.
Et la restriction par agent qu'on avait déjà, celle qu'un ticket peut porter quand il lance un agent, n'était délibérément pas transmise aux étapes d'une équipe. Un agent lancé depuis un ticket pouvait donc être restreint, et un nœud d'équipe non. C'était la cause première, et c'était une décision de conception qui avait mal vieilli.
La règle : une case sur le nœud
La correction est un booléen sur le nœud de revue. Coche Lecture seule et l'agent qui incarne cette étape est lancé sans accès en écriture au projet : pas d'édition de fichier, pas de commit ni de push, pas de commande shell dont le seul rôle est de modifier l'arbre de travail. La lecture, grep, git diff, git log, les tests, le linter et tous les outils d'équipe restent ouverts.
On a été explicites sur ce que ce n'est pas : ce n'est pas une liste d'interdictions que l'utilisateur rédige à la main, CLI par CLI. Personne ne devrait avoir besoin de connaître cinq syntaxes de permissions pour dire « celui-ci relit ». L'interrupteur produit le bon drapeau pour chaque provider, et il est appliqué en dernier, après le mode autonome et après tout ce que l'utilisateur a enregistré sur l'agent, donc il gagne.
Ce que fait chaque CLI, lu sur sa propre aide
On n'impose la règle que sur les providers dont on a lu le drapeau sur leur propre --help. Un drapeau deviné tue le lancement sur une erreur d'analyse, ce qui est pire qu'une étape sans contrainte. Les autres CLI n'ont que la règle écrite, et l'éditeur le dit en toutes lettres sous la case.
| CLI | Ce que l'interrupteur lecture seule ajoute | Tient en mode autonome ? |
|---|---|---|
| Claude Code | --disallowedTools "Edit" "Write" "MultiEdit" "NotebookEdit" "Bash(git commit:*)" "Bash(git push:*)" et la suite | Oui, les règles d'interdiction s'appliquent sous --dangerously-skip-permissions |
| Codex | --sandbox read-only | Oui, c'est un bac à sable du système (Seatbelt sur macOS, Landlock sur Linux), pas une liste d'outils |
| Grok Build | --deny "Edit" --deny "write" --deny "Bash(git commit*)" et la suite | Oui, les règles d'interdiction s'appliquent sous --always-approve |
| Antigravity | --mode plan | Oui, plan est le mode d'exécution en lecture seule du CLI |
| OpenCode | --agent plan | Oui, l'agent plan intégré refuse les outils d'édition |
| Mistral Vibe, Kimi Code, Copilot, Cursor, Amp, Aider et les autres | paragraphe de prompt seulement | Pas de drapeau vérifié, et on le dit dans l'éditeur |
Deux détails de ce tableau nous ont coûté un bug chacun, ils méritent d'être écrits.
Codex et Grok refusent un drapeau répété. Les deux analysent leurs arguments avec un analyseur strict. Si l'utilisateur avait déjà enregistré --sandbox workspace-write sur l'agent, ajouter --sandbox read-only derrière ne l'écraserait pas, ça ferait planter le lancement. Pour les drapeaux à valeur, on retire donc toute occurrence existante, avec sa valeur, avant d'ajouter la nôtre. Même chose pour --agent chez OpenCode, dont l'analyseur transforme un drapeau répété en tableau et échoue plus loin.
Sur Claude Code, la liste doit se cumuler. --disallowedTools prend une liste séparée par des espaces et peut être répété, et on en passe déjà un quand un agent n'a pas le droit de piloter le navigateur intégré. L'analyseur concatène une option variadique répétée, donc les deux listes s'additionnent au lieu que la seconde remplace la première.
La liste complète pour Claude Code, ce sont les quatre outils d'édition de fichiers, chaque sous-commande git qui écrit dans l'index, l'arbre, les refs ou un dépôt distant (add, commit, push, merge, rebase, reset, checkout, switch, restore, stash, cherry-pick, revert, apply, am, rm, mv, clean, tag, worktree), et les commandes shell qui n'existent que pour modifier des fichiers (rm, mv, cp, tee, touch, mkdir, chmod, chown, ln, truncate, dd, sed -i). Grok prend les mêmes chaînes de règles, dans sa forme glob, plus ses propres noms pour les outils de fichiers (search_replace, write, hashline_edit).
Le prompt a quand même un rôle
Le drapeau refuse. Il n'explique pas. Et un agent qui se heurte à un refus qu'il ne comprend pas le traite comme un bug et cherche un autre chemin, ce qui est précisément le comportement qu'on voulait faire disparaître.
Une étape en lecture seule reçoit donc aussi deux phrases dans son prompt. La première dit que l'étape est en lecture seule, liste ce que ça veut dire, et pose qu'un refus est la règle, pas un obstacle à contourner avec une autre commande. La seconde liste ce qui reste ouvert, et demande à l'agent de rapporter ce qui doit changer, avec le fichier, la ligne et la raison, dans sa passation, et de laisser l'étape qui possède le code l'appliquer.
Sur les CLI qui ont un drapeau vérifié, ce paragraphe est ce qui rend le refus compréhensible. Sur les autres, c'est toute la contrainte, et on préfère le dire que faire semblant.
Qui est en lecture seule dans les modèles livrés
Les nœuds qui jugent sont en lecture seule : l'étape de vérification QA des deux modèles de départ, les étapes de reproduction et de vérification de Bug hunt, les branches QA et Sécurité de Release shield, le testeur de Feature squad.
Les nœuds qui possèdent le code continuent d'écrire : le développeur, et la porte de release qui est écrite pour corriger elle-même chaque constat. Une porte de release qui ne peut pas écrire est une porte de release qui ne peut pas livrer.
Ce partage est toute la conception, et c'est le partage que l'incident a violé deux fois : un nœud de release qui a écrit au mauvais endroit, et des nœuds de revue qui ont écrit tout court.
Ce que ce n'est pas
Ce n'est pas une frontière de sécurité. Le rapporteur l'a dit dans son rapport, et il avait raison : un bash -c passe à côté d'une liste d'outils interdits. Si tu as besoin d'isoler un agent en qui tu n'as pas confiance, c'est un bac à sable ou une machine séparée, et Codex est le seul des cinq dont le mode lecture seule est réellement ça.
Ce que l'interrupteur arrête, c'est l'accident et la dérive de rôle, ce qui est ce qui arrive vraiment. Un relecteur ne contourne pas une liste d'interdictions exprès. Il attrape Edit par réflexe, et le réflexe est maintenant refusé.
Ce qu'on n'a pas construit
Le rapporteur demandait une chose de plus : un événement dans la chronologie du run disant « le nœud X a écrit dans l'arbre », comme signal minimal même sans contrainte. C'est une bonne idée et on ne l'a pas faite ici, parce qu'il faut un diff de référence par étape côté runner. Si le besoin revient, c'est la pièce suivante.
Si tu n'utilises pas AgentsRoom
Les drapeaux ci-dessus se recopient tels quels. Un agent de revue lancé à la main avec codex --sandbox read-only, ou claude --disallowedTools "Edit" "Write" "MultiEdit" "NotebookEdit" "Bash(git commit:*)" "Bash(git push:*)", ne peut pas faire ce que nos deux nœuds de revue ont fait. Mets les deux mêmes phrases dans son prompt pour qu'il sache pourquoi on lui refuse.
Ce que la case ajoute, c'est que tu n'as pas à te souvenir de laquelle des cinq syntaxes s'applique, que le drapeau gagne sur le mode autonome dans lequel tourne l'étape, et qu'il survit à un run qui repasse plus tard par la même étape.
L'interrupteur du nœud et le tableau par provider sont documentés sur la page Agent Teams. Savoir si une revue par un agent vaut le coup, et quelle part d'un diff mérite encore un humain, est une autre question, et on l'a traitée dans Faut-il encore relire le code de son agent IA ?. Ce billet parle de la chose plus petite et plus mécanique : une fois que tu as décidé qu'un agent relit, rends-le physiquement incapable de faire autre chose.
Télécharger AgentsRoom
Lancez tous vos agents IA, sur tous vos projets, depuis une seule fenêtre.
App companion : suivez vos agents en déplacement
Utilisez Claude, Codex, Antigravity CLI ou un autre fournisseur IA.
Remontez bugs et demandes directement dans votre backlog public.
Continuer la lecture
Passer les agents de code à l'échelle d'une équipe
Un développeur avec un agent de code, c'est un gain de productivité. Cinq développeurs avec vingt agents, c'est un problème de coordination. Voici ce qui casse en premier quand une équipe passe à l'échelle, et le dispositif qui tient : fichier de contexte versionné, périmètre de fichiers explicite, relecture proportionnelle au risque, et un coût enfin visible.
Lire l'articleFaut-il encore relire le code de ses agents IA ?
Vos agents écrivent du meilleur code que la moitié des pull requests que vous mergiez avant. Faut-il encore lire chaque ligne ? Le débat pris au sérieux des deux côtés, les 10 signaux qui trahissent un agent qui a déconné, et le niveau de relecture que mérite vraiment chaque changement.
Lire l'articleDix agents ont lancé le même typecheck en même temps. La solution était un dossier.
Dix-sept agents de code dans le même checkout, dix tsc en parallèle, load average 37 et 87 Mo de RAM libre. Un typecheck de quatre-vingt-dix secondes a mis 7 min 36. Voici la mesure, pourquoi la machine ne calculait pas, et le petit verrou partagé qui a réglé le problème. Recopiable dans n'importe quel dépôt.
Lire l'article