La confiance n'exclut pas le contrôle.... surtout pas votre agent !

La confiance n'exclut pas le contrôle.... surtout pas votre agent !
Photo by Rohan Makhecha / Unsplash

Tout le monde connaît ce proverbe, généralement très prisé des micro-managers toxiques.

Dans le développement agentique, c'est notre pain quotidien. Et en vérité, on finit par oublier qu'on ne devrait jamais faire confiance à son agent.

Non pas parce qu'il est mauvais. Parce que la confiance suppose une mémoire et une responsabilité, et qu'il n'a ni l'une ni l'autre.

Voici comment on en arrive à ce constat. En trois étapes, dont deux que je n'avais pas prévues.

Étape un : la prose

Au début, il y a un fichier. Le mien s'appelle CLAUDE.md, il contient dix règles numérotées, et l'agent le relit à chaque session.

Sauf que ce fichier n'est pas un manuel de bonnes pratiques. C'est la liste de tout ce que mon agent a fait et que je ne veux plus qu'il refasse. Chaque règle est une cicatrice.

Prenez la cinquième :

Quand on déplace du code d'un fichier à un autre, il est interdit de le réécrire. Toujours faire un copier-coller exact. Ne jamais réécrire de mémoire.

Lisez-la en imaginant un développeur humain. Elle n'a aucun sens. Personne ne réécrit de mémoire un fichier qu'il déplace, on fait un couper-coller et on passe à autre chose.

Cette règle existe parce qu'un agent, lui, régénère. Il vous déplace une fonction et la retape au passage, avec des variations minuscules : un match devenu if let, un nom de variable ajusté, une branche d'erreur simplifiée. Rien qui saute aux yeux en revue. Tout ce qu'il faut pour introduire un bug dans un refactoring censé être neutre.

Même chose pour la quatrième, qui impose de vérifier exhaustivement qu'un code n'est utilisé nulle part avant de le supprimer, ni dans le Rust, ni dans les templates, ni dans le JS inline. Elle est là parce que l'agent supprime ce qui lui semble inutilisé, avec une confiance parfaite.

Ou la huitième, qui lui interdit de démarrer un serveur de développement de sa propre initiative. Adressée à un humain, la phrase serait absurde.

Ce fichier a été modifié trente-cinq fois. C'est un des plus retouchés du projet, devant la quasi-totalité du code métier. Chaque modification correspond à un moment où j'ai vu passer quelque chose que je ne voulais pas.

Et pendant des semaines, j'ai cru que ça suffisait.

Et ben non.

Pourquoi la prose ne tient pas avec un agent

Avec une équipe humaine, une convention écrite fonctionne à moitié, selon les contextes. Peu grâce à la discipline, plutôt grâce à la mémoire et à l'amour-propre. On se souvient de la remarque en revue de la semaine dernière, et on n'a pas très envie de se la refaire.

Un agent n'a rien de tout ça.

Il ne se souvient pas d'hier. Il n'est pas gêné d'avoir tort. Il applique ce qui se trouve dans son contexte au moment où il travaille, et rien d'autre. L'écart entre la règle écrite et la règle appliquée n'est donc jamais réduit par l'habitude. Il est rejoué intégralement à chaque session.

Ajoutez le volume. Une convention mal respectée sur dix commits par semaine, ça se rattrape en revue. Sur deux cent cinquante-huit commits en un mois, non. Le débit de production a dépassé le débit de relecture.

Une règle en prose demande un effort de rappel volontaire à chaque ligne. Multipliez par cinq cents commits et vous avez la réponse.

Étape deux : le script

Or un agent est très doué pour produire du code.
Autant donc lui lui faire écrire du code... pour valider le code qu'il va écrire ! Inception quand tu nous tiens.
Le 16 juin, j'ai donc arrêté d'ajouter des règles et j'ai écrit make check-arch.

Logiquement ça garde la taille du contexte d'execution de l'agent sous contrôle, en augmentant son efficacité.

C'est un script bash. Pas d'analyse syntaxique, pas de parcours d'arbre : des grep, un peu d'awk, trois cents lignes. Il vérifie aujourd'hui huit axes.

Le premier est la pureté du domaine. Un grep sur les imports des dossiers domain/, et le script échoue s'il trouve un use sqlx ou un use axum. Trois lignes de bash pour rendre inviolable une règle qu'aucune relecture ne garantissait.

Les autres suivent la même logique : souveraineté des données entre contextes, aucune route écrite en dur dans le front, projections écrites dans la même transaction que l'événement.

Et deux axes plus récents, qui m'amusent parce qu'ils vérifient mon propre outillage : l'un contrôle que ma carte d'impact des tests est exhaustive et sans entrée morte, l'autre que chaque contexte reste extractible.

L'outil s'est mis à surveiller les outils, et je pense n'en être qu'au début.

La nuance qui compte : tout ne bloque pas

Sur ces huit axes, six font échouer le script. Deux se contentent d'un avertissement.

Ce qui bloque : la pureté du domaine, la souveraineté des données, les routes typées, les projections transactionnelles. Ce qui avertit : l'usage systématique de value objects, et la taille maximale des fonctions.

Le critère n'est pas l'importance. On bloque ce qui est structurel et binaire : un contexte importe un autre contexte, ou il ne l'importe pas. Pas de cas particulier défendable, et la violation se propage.

On avertit sur ce qui est graduel : une fonction de vingt-deux lignes n'est pas un crime, elle mérite un regard, pas un refus de commit.

Cette distinction a une raison très concrète en contexte agentique. Un vérificateur qui bloque sur tout devient un obstacle que l'agent apprend à contourner, en découpant artificiellement des fonctions pour passer sous le seuil. On obtient du code conforme et pire qu'avant. Le seuil arbitraire produit du contournement zélé.

La preuve que je n'attendais pas

Il y a un moment où j'ai compris que l'outil valait mieux que moi.

J'avais écrit une carte, la 86, pour corriger les violations de souveraineté des données entre contextes. Rédigée à la main, en listant ce que j'avais repéré en relisant.

Cette carte a fini annulée. Pas par renoncement : parce qu'elle était insuffisante. Elle ne couvrait qu'une fraction des violations réelles. Elle a été remplacée par une série de cartes issues d'un audit exhaustif du script.

Ma revue humaine avait raté ce que trois lignes de grep ont trouvé en une seconde.

C'est là que le rapport s'inverse. Je ne relis pas assez vite, ni assez exhaustivement, pour suivre le rythme de ce que l'agent produit. Ce n'est pas un aveu de paresse, c'est une question de débit.

La dette accumulée a été soldée le 22 juillet, cartes 184 à 191. Depuis, la règle numéro neuf s'applique dans sa version stricte : lancer make check-arch sur l'ensemble du projet avant tout commit, sans exception.

Fin de l'histoire, non ?

Non.

Étape trois : celle que je n'avais pas vue

Pendant tout ce temps, il y avait un trou dans mon dispositif.

Le script tournait sur ma machine.

Uniquement sur ma machine.

Ma règle disait « avant tout commit ». Mon intégration continue lançait les tests unitaires, les tests de bout en bout, tout ce qu'il faut. Mais elle ne lançait pas make check-arch. Ni make lint.

Le garde-fou le plus important du projet reposait donc sur une seule chose : ma discipline personnelle. C'est-à-dire sur la seule pièce du système qui fatigue.

Et elle a dérivé. J'en ai la mesure exacte : le formatage du code avait glissé sur 288 fichiers sans que quoi que ce soit le signale. Pas un avertissement, pas un échec de build.

Deux cent quatre-vingt-huit fichiers, chez quelqu'un qui a écrit un vérificateur d'architecture et une règle qui dit de le lancer avant chaque commit.

Le 29 juillet, make lint et make check-arch sont entrés dans la CI.

Les trois niveaux de garantie

Une règle en prose est un vœu. Avec un humain elle tient à moitié, grâce à la mémoire. Avec un agent qui repart de zéro à chaque session, elle ne tient pas du tout.

Une règle outillée mais lancée à la main est une discipline. C'est nettement mieux, mais elle dépend d'un humain qui pense à l'exécuter un vendredi soir à 23h, après une session où l'agent a produit trois cents lignes.

Une règle dans l'intégration continue est une garantie. C'est le seul niveau où elle existe indépendamment de vous.

Je suis passé par les trois en quarante-cinq jours, et à chaque palier j'étais convaincu d'avoir résolu le problème.

Voilà ce que le développement agentique change vraiment. Ce n'est pas qu'il produit du mauvais code : il en produit du très correct. C'est qu'il produit à un débit où l'humain n'est plus assez souvent dans la boucle pour servir de garde-fou.

Alors on déplace le garde-fou. De la tête vers le fichier, du fichier vers le script, du script vers la CI. À chaque étape, on retire un peu de soi du chemin critique.

La confiance n'exclut pas le contrôle.

Avec un agent, il n'y a jamais eu que le contrôle.