Guides et capteurs : la grille qui dit où va ton attention
Guides et capteurs : la grille qui dit où va ton attention
La grille de Birgitta Böckeler, guides et capteurs, calculés ou inférés, comme boussole pour décider où va l'attention d'un développeur qui travaille avec des agents, avec les exemples de phax.
Partie de la série : Attention is all we have · Voir toutes les parties
Précédemment dans cette série : Attention is all we have
Thèse. Toute pièce du harness se range dans une case d'une grille à quatre cases : guide ou capteur, calculé ou inféré. Le progrès consiste à faire passer chaque jugement vers une case calculée, de préférence avant le code.
- Un harness d'agent n'a que deux leviers : orienter avant, vérifier après.
- Chaque levier est calculé ou inféré, et seul le calculé te rend ton attention.
- Un capteur calculé ne vaut que ce qu'il vérifie : il faut le séparer de celui qui fait.
- Un capteur inféré coûte, et ne vaut que pour ce qu'aucun capteur calculé ne couvre.
- Le cran suivant, ce sont des guides calculés, qui agissent avant que le code existe.
- Quand les modèles progressent, les capteurs calculés restent et les guides deviennent un réglage.
Je ne lis pas le code que mes agents écrivent. Depuis des mois, je n'en ai ni l'énergie ni l'attention. Je donnais un plan à l'agent, il l'exécutait phase après phase, et je me retrouvais devant le résultat. Les tests passaient, et pourtant ça ne marchait pas. Je voyais l'erreur sans pouvoir aller la corriger : l'agent était mes seules mains. Je lui disais « corrige ça », il corrigeait, et une autre erreur surgissait ailleurs. Dans la liste des fichiers modifiés, je ne savais même pas pourquoi tel fichier avait été touché. Chaque erreur est donc devenue une question : qu'est-ce qui ferait que l'agent la corrige, et que ce genre d'erreur ne revienne plus ?
Ce qui m'a aidé à y répondre, c'est une grille. Elle est de Birgitta Böckeler, dans Harness engineering for coding agent users (martinfowler.com, avril 2026), et je m'en sers depuis comme d'une boussole. Elle parle du harness utilisateur : ce qu'on met autour de l'agent pour l'orienter et le vérifier, à distinguer du harness du fournisseur, la boucle et les outils dans lesquels tourne le modèle. Chaque pièce que j'ai ajoutée à phax y tient dans une case. phax est l'orchestrateur open source que je construis en public (sur GitHub) : il fait exécuter un plan par un agent, phase par phase, chacune dans son worktree, et ne commite une phase que si ses vérifications passent. La comparaison de phax avec les pratiques agentiques les recense une à une.
Un harness d'agent n'a que deux leviers : orienter avant, vérifier après
Quand l'agent dérive, le réflexe est d'écrire un meilleur prompt. C'est un levier parmi deux. Böckeler les appelle les guides et les capteurs (guides et sensors). Un guide anticipates the agent's behaviour and aims to steer it before it acts : il agit avant que l'agent écrive. Un capteur observes after the agent acts and helps it self-correct : il agit sur ce qui a été écrit.
Un plan est un guide. Un skill aussi, comme le CLAUDE.md ou le prompt de phase. Un gate qui lance pnpm typecheck est un capteur, comme une revue de code ou un test d'acceptation. Ce que j'appelle un gate, c'est une quality gate : les vérifications qu'un changement doit passer avant d'être commité.
Chaque levier est calculé ou inféré, et seul le calculé te rend ton attention
La deuxième dimension de la grille sépare ce qu'un programme décide de ce qu'un modèle juge. Un levier calculé (computational) est deterministic and fast, run by the CPU : il répond vrai ou faux, et il répond la même chose à chaque fois. Un levier inféré (inferential) passe par un modèle : un skill qu'il lit, une revue qu'il fait.
Deux dimensions. Un guide agit avant l'agent, un capteur après. Chacun est inféré, jugé par un modèle, ou calculé, décidé par un programme. Les guides inférés sont un skill, le CLAUDE.md, un plan que l'agent lit ; un guide calculé est un brief calculé à partir du code. Les capteurs inférés sont une revue par un modèle ou une personne ; les capteurs calculés sont le type checker, le linter, les tests et les fitness functions. Chaque pratique fait passer un jugement vers le calcul, et le capteur calculé est l'optimum.
Je l'ai apprise dans l'ordre le plus coûteux. Au début, je n'avais mis que de l'inférence. Des skills, des plans détaillés, des consignes d'architecture, en espérant que l'agent les suive. Prends une règle simple : le domaine n'importe pas l'infrastructure. Écrite dans un skill, l'agent la lit. Il la suit la plupart du temps. À la quarantième itération d'une phase difficile, avec un contexte saturé, il importe un client HTTP depuis le domaine parce que c'était le chemin le plus court vers un test vert. Rien ne le signale. La règle est toujours dans le skill, et je ne le découvre que quand quelque chose casse.
La même règle peut vivre dans une autre case. Elle devient une commande, pnpm audit:architecture, qui vérifie les frontières entre les couches et échoue si le domaine touche l'infrastructure. On la met dans le profil de gate. Le tout premier phax.json du projet, le 12 mai 2026, la contenait déjà. Elle y côtoyait pnpm typecheck, pnpm lint et pnpm knip. Désormais, à chaque phase, phax lance la commande. Si elle échoue, la phase ne commite pas : l'échec retourne à la même session de l'agent, qui corrige dans la limite de son budget de tentatives.
Dans le gate, c'est le CPU qui la porte. Ensuite, j'ai verrouillé tout ce que le langage et les outils savaient vérifier : le type checker en mode strict, le linter, le formateur, la détection du code mort. Chaque règle passée d'un skill à un gate, c'est une famille d'erreurs qui ne revient plus.
Un capteur calculé ne vaut que ce qu'il vérifie : il faut le séparer de celui qui fait
Un gate vert dit que les commandes passent. Il ne dit pas que les commandes vérifient la bonne chose. Et un agent qui a le droit de modifier ses propres tests a un chemin très court vers le vert : modifier le test qui échoue.
phax a pris ce problème par deux bouts. Le premier, c'est la réconciliation du planifié et du fait. Depuis juin, phax compare les fichiers que chaque phase a vraiment changés avec ceux que son plan annonçait (le prévu et le fait). Prévu mais pas fait, fait mais pas prévu, supprimé, renommé : chaque écart est listé, et l'agent doit le justifier dans son rapport de fin de phase. Devant la liste des fichiers modifiés, je sais maintenant pourquoi chacun a été touché.
Le second, ce sont les tests d'acceptation écrits avant le code, ce que la littérature appelle l'ATDD (acceptance test-driven development), arrivés fin octobre. Une phase écrit les tests qu'une phase suivante devra satisfaire. Ils sont jugés deux fois, par un fournisseur que tu configures : d'abord ils doivent échouer, puisque le code n'existe pas encore, puis ils doivent passer. La phase qui écrit le code ne touche pas aux tests.
Un capteur inféré coûte, et ne vaut que pour ce qu'aucun capteur calculé ne couvre
Restent les jugements qu'aucune commande ne sait porter. Le travail respecte-t-il l'intention du plan ? Le nommage est-il juste ? La solution est-elle la bonne ? Pour ceux-là, il faut un capteur inféré : un modèle qui relit.
phax en a deux. La revue de conformité, arrivée en juin avec phax review-compliance, lit le travail contre le plan et ne modifie rien. La revue de code headless, arrivée en octobre, tourne dans une session en lecture seule. Si la session a changé quoi que ce soit dans le worktree, phax remet les fichiers en place et refuse sa réponse. Les deux sont optionnelles par projet, et chacune prend son propre modèle et son propre effort.
Un capteur inféré coûte des tokens, du temps, et il peut se tromper. Si une revue par modèle passe son temps à signaler une erreur de format, c'est qu'un formateur manque dans le gate.
Le cran suivant, ce sont des guides calculés, qui agissent avant que le code existe
Les capteurs calculés, même bien séparés, ont une limite : ils arrivent après le code. C'est aussi vrai des fitness functions, au sens de Building Evolutionary Architectures (Ford, Parsons et Kua), que j'ai ajoutées ensuite. Une fitness function vérifie une caractéristique de l'architecture, automatiquement, à chaque changement. L'agent a déjà écrit le code, il a déjà consommé ses tokens, et la correction coûte une tentative de plus.
J'avais besoin de quelque chose qui agisse avant, et qui ne repose pas sur l'inférence. C'est la case la moins remplie de la grille, celle où j'ai le plus patiné, et celle où je travaille maintenant. phax y a mis trois choses.
phax plans lint, en septembre, refuse un plan mal formé avant qu'un run démarre : une phase qui modifie un fichier qu'aucune phase précédente ne crée, une autre qui crée un fichier qui existe déjà. Les bornes d'affectation, en octobre, permettent au propriétaire du dépôt de tenir certains fichiers à un modèle et à une plage d'effort. Une phase qui s'écarte de sa borne sans en donner la raison est refusée, par plans lint comme au démarrage du run, avant d'avoir coûté quoi que ce soit.
Le troisième est le plus important : un feed-forward calculé, que phax appelle le brief, arrivé en octobre avec phax brief. Avant qu'une phase écrive, un fournisseur de brief calcule à partir du code les garanties qui couvrent les fichiers qu'elle va toucher, avec leur état. L'agent ne reçoit plus un skill générique sur l'architecture, et le gate vérifiera ensuite les mêmes garanties.
Quand les modèles progressent, les capteurs calculés restent et les guides deviennent un réglage
Une objection revient : les modèles s'améliorent, tout ce harness deviendra inutile. Anthropic le dit de son côté : every component in a harness encodes an assumption about what the model can't do on its own (Harness design for long-running application development). Leur propre harness a abandonné des morceaux à mesure que les modèles progressaient.
La grille dit lesquels. Un gate n'encode aucune hypothèse sur le modèle. Il encode ce que le changement doit passer. Un modèle meilleur le passe plus souvent, donc il coûte moins de tentatives. Et un modèle meilleur dans son travail est aussi meilleur pour tromper un capteur faible, ce qui est une raison de plus de garder le juge séparé de celui qui fait.
Les guides, eux, deviennent un réglage. Combien le plan détaille, quel modèle exécute chaque phase : ce sont des choix qui changent avec les modèles et leurs prix. Un plan très détaillé, écrit une fois par un modèle fort, peut laisser un modèle moins cher exécuter les phases. Un plan plus léger s'appuie davantage sur les gates et la boucle de correction.
Ce que la grille ne dit pas
La grille classe les pratiques. Elle ne dit pas quoi y écrire. Savoir quelle règle d'architecture vaut la peine d'être calculée, c'est encore ton métier.
Elle ne dit pas non plus quand un capteur est écrit. Ses « avant » et « après » disent quand un levier agit, pas quand on l'a posé. Les règles du type checker et du linter sont posées avant, et un test d'acceptation l'est par définition : c'est un contrat, et le code n'a pas pu l'influencer. Les tests unitaires s'écrivent pendant, et souvent les fitness functions aussi, parce qu'il faut que les choses soient en place pour pouvoir les écrire. Validés une première fois, ils tiennent ensuite pour les phases suivantes. Mais au moment où ils naissent, ils peuvent épouser le code au lieu de le juger. Le capteur le plus fort est celui qu'on contractualise avant d'écrire le code.
La même grille, son capteur calculé coupé selon le moment où il est écrit. Écrit avant le code, c'est un contrat que le code doit passer et qu'il n'a pas pu influencer : les règles du type checker et du linter, les tests d'acceptation ; c'est le plus fort. Écrit avec le code, il peut épouser le code au lieu de le juger : les tests unitaires, et souvent les fitness functions.
Les cases ne sont pas étanches. Une spec est un guide inféré, puisque l'agent la lit, mais une personne l'a approuvée, et phax enregistre contre quoi. Je ne sais pas encore quelle part du jugement finira calculée.
Pour chaque jugement que tu portes encore à la main, demande-toi dans quelle case il pourrait passer.
Une remarque après lecture ?
Si vous souhaitez envoyer un mot au sujet de cet article, vous pouvez écrire ici. Je partage ici parce que le sujet m’intéresse et que je veux apprendre des autres. Merci pour vos retours, surtout lorsqu’ils sont formulés avec soin.