Aller au contenu
Tous les articles

Par Gustavo Paixão

Vérifier le travail de l'IA avec un agent qui ne l'a pas fait

Avant que je coche une tâche, un deuxième agent la confronte au code réel. L'idée est venue d'un article scientifique sur la détection d'IA trompeuse, dont je ne peux pas faire tourner la méthode. Ce que j'en ai retenu, ce que l'agent a trouvé et ce que ça coûte.

Partager

Le problème

Quand un agent d'IA termine une tâche, il me dit ce qu'il a fait. La plupart du temps, c'est exact. Parfois, non : un test qui ne couvre pas ce qu'il prétend couvrir, un cas que personne n'a essayé, un plan qui ne correspond plus au code. Sur Ronne AI Marketplace, 143 des 1 522 affirmations que l'agent d'implémentation a faites sur son propre travail se sont révélées vraies en partie seulement, ou pas vraies du tout.

Alors, avant que je coche une tâche, un autre agent la vérifie. Il n'écrit pas le code, il ne le corrige pas, et il ne croit personne sur parole : il lit les fichiers et exécute les commandes lui-même. Je l'appelle le témoin d'état (state witness), d'après l'article d'où vient l'idée. Son compte rendu va dans un WITNESS.md à côté de la spécification et du plan de la fonctionnalité, dans le même commit que la tâche, et une vérification dans le hook de pré-commit et en intégration continue refuse une tâche cochée à moins que la dernière passe du témoin n'ait confirmé toutes les affirmations.

J'écris la spécification et je marque les tâches à risque; l'agent d'implémentation lance le témoin et colle son compte rendu dans le fichier.

D'où est venue l'idée

J'ai entendu parler de StateWitness pour la première fois dans un Reel Instagram de Vinicius Pasquantonio (@pasquadev). C'est un article scientifique (Chen et al., 2026) sur la détection de la tromperie dans les modèles de raisonnement. Un deuxième modèle lit les activations du modèle audité (ses états cachés) et répond à des questions comme « cette réponse cache-t-elle quelque chose? ». Sur sept bancs d'essai de tromperie, la méthode a atteint un AUROCArea Under the Receiver Operating Characteristic Curve (aire sous la courbe ROC)En IA et en apprentissage automatique, une mesure de la capacité d'un modèle de classification à distinguer deux classes, comme :Commit avec bug ou commit propreTest instable ou fiablePaquet malveillant ou sûrCode vulnérable ou sûrRéponse d'IA trompeuse ou honnête, comme dans cet article moyen de 0,916, contre 0,821 pour le meilleur juge qui ne lit que le texte.

Je ne peux pas faire tourner ça. La méthode ne fonctionne que sur un modèle dont on peut lire les activations :

Modèles à poids ouverts

Exemples
gpt-oss-20b et Gemma, les deux de l'article
Ce qu'on obtient
Les poids. On fait tourner le modèle soi-même, donc on peut lire ses activations.
Un témoin complet
Possible, avec un décodeur entraîné pour ce modèle précis, et des GPU : les auteurs font état d'environ 190 heures-GPU A100 d'entraînement.

Modèles commerciaux

Exemples
GPT, Gemini et Claude, le modèle derrière Claude Code
Ce qu'on obtient
Du texte, par une application ou une API.
Un témoin complet
Pas de l'extérieur. Seule l'entreprise qui exploite le modèle voit ses activations.

Les mêmes entreprises font les deux types : gpt-oss et GPT viennent d'OpenAI, Gemma et Gemini, de Google. Avec Claude Code, le lecteur d'activations est hors de portée, et il reste les idées qui fonctionnent sur du texte.

L'article répond aussi à une autre question. Il cherche à savoir si un modèle est trompeur, et moi, j'ai besoin de savoir si une tâche est terminée.

Ce que je pouvais utiliser, c'étaient trois constats sur la vérification du travail d'autrui, plus une règle de mon cru.

Ce que j'en ai retenu

ConstatDans l'articleDans le témoin
Le récit ancre le vérificateurUn juge textuel a fait moins bien quand il lisait aussi le raisonnement du modèle : 0,789 contre 0,809 sur gpt-oss-20bIl commence à l'aveugle : le Done when de la tâche (la ligne du plan qui dit ce qui compte comme terminé), les lignes de la spécification et où chercher, jamais les notes de l'agent d'implémentation
Deux vérificateurs différents ratent moins qu'un seulCombiner le lecteur d'activations et le juge textuel a fait passer le rappel, à un taux de fausses alertes de 1 %, de 0,430 à 0,562Les tâches à risque (connexion, rôles, migrations, suppression de données, tout ce qui s'exécute en root) ont droit à une deuxième passe, dont la seule consigne est de briser les affirmations
Un vérificateur peut sembler sûr de lui avec des preuves faiblesLes auteurs le disent dans la section sur les limitesChaque affirmation exige une preuve : la commande et ce qu'elle a montré, ou un fichier et une ligne. Chaque passe nomme le commit qu'elle a vérifié

Le premier constat est le plus faible des trois. Sur l'autre modèle de l'article, Gemma, le juge a fait légèrement mieux avec le raisonnement.

Un juge textuel, avec et sans le raisonnement du modèle
Réponse finale seulementRéponse et raisonnement
gpt-oss-20b0,8090,789
Gemma 4 26B0,8260,829

AUROC tiré des résultats principaux de l'article : 1,0 détecte chaque réponse trompeuse sans aucune fausse alerte, 0,5 correspond au hasard. Les barres partent de zéro.

J'ai quand même gardé le départ à l'aveugle. Il ne coûte rien, et mes propres chiffres, plus bas, vont dans le même sens.

La règle qui est la mienne, pas celle de l'article : après ses verdicts, le témoin lit les notes de l'agent d'implémentation et indique quelles affirmations elles contenaient. Une affirmation en échec que les notes contenaient est une erreur de l'agent d'implémentation. Ce sont les 143 du début.

Comment se déroule une passe

Un nouvel agent reçoit le Done when de la tâche, les lignes de la spécification qu'elle couvre, où chercher et le commit. Il en tire des affirmations distinctes, une par ligne, et vérifie chacune en lisant le code et en exécutant lui-même les tests, les compilations et de petites sondes. Des tests au vert ne comptent pas à eux seuls : il vérifie qu'un test couvre bien l'affirmation et, quand il le peut, il brise le code dans une copie jetable pour voir le test échouer.

Chaque verdict est l'un des quatre suivants : confirmé, en partie, non satisfait ou impossible à vérifier ici (il faut Windows, GitHub ou une publication). Ces lignes proviennent d'une vraie passe adversariale sur un changement apporté au résolveur de dépendances :

#AffirmationDans les notes?VerdictPreuve
30La suite principale passe, avec le test aux nombreux demandeursnonconfirmé350 réussis
31Le changement passe pnpm lintnonnon satisfaitnoAssignInExpressions à resolve.ts:224
32Le budget compte les vérifications de plage, donc de nombreux demandeurs ne peuvent pas faire durer l'exécutionnonconfirméN=100/300/500 → 454 / 1159 / 4391 ms
33Le nouveau test échoue quand les vérifications comptent +1 par versionnonconfirmé→ 11 543 ms, échoue

Les tests étaient au vert. Le lint, non.

Ce qu'il a trouvé

Tous les chiffres de ce texte proviennent des comptes rendus tels qu'ils étaient dans le dépôt le 11 octobre à 22 h 21, heure de l'Est (commit 149e14a (s'ouvre dans un nouvel onglet)), huit jours après le début du témoin, et des transcriptions de Claude Code jusqu'à ce commit. Le dépôt est public, donc les chiffres des comptes rendus peuvent être recomptés.

Pendant ces huit jours, le témoin a effectué 408 passes sur 3 490 affirmations : 3 122 confirmées, 268 en partie, 89 non satisfaites et 8 qu'il ne pouvait pas vérifier ici (3 lignes anciennes portent un verdict que le format n'admet plus). Les 1 522 affirmations du début sont celles, parmi les 3 490, que les notes de l'agent d'implémentation avaient faites. Les 408 passes viennent de 251 exécutions du témoin : une revérification revient d'habitude à l'agent qui a fait la passe, avec les corrections, plutôt qu'à un nouveau.

En partie est l'échec le plus courant, et il couvre un large éventail. Dans le compte rendu : un test qui existe, mais ne vérifie pas le champ dont parle l'affirmation; un test de concurrence instable sur SQLite, qui échoue une fois sur douze; une section de la documentation numérotée « quatrième » alors que c'était la troisième. Certains sont des erreurs de l'agent d'implémentation, d'autres tiennent à la rigueur du témoin, et le compte rendu ne dit pas lesquels.

La première version donnait au témoin les notes de l'agent d'implémentation en même temps que la tâche. Après avoir lu ses 55 premières passes, sur 42 tâches, j'ai changé la règle pour qu'il commence à l'aveugle, et la part des tâches dont la première passe laissait au moins une affirmation non confirmée a fortement augmenté.

Tâches avec une affirmation non confirmée à leur première passe
Tâches
Témoin avec les notes (42 premières tâches)14 % (6 sur 42)
Témoin à l'aveugle (125 tâches suivantes)58 % (73 sur 125)

Un avant-après, pas un test contrôlé : les fonctionnalités suivantes, des espaces de travail avec rôles et permissions, étaient aussi plus difficiles. Faire passer les mêmes tâches des deux façons est encore sur ma liste.

La deuxième passe a aussi mérité sa place. Sur 11 des 38 tâches à risque, la passe adversariale a trouvé des problèmes après que la passe à l'aveugle avait jugé tout satisfait. En termes généraux : des informations qui fuyaient entre espaces de travail, un cache partagé entre administrateurs qui aurait dû être séparé, et des interblocages sur certains serveurs de bases de données quand deux changements arrivaient en même temps. Chaque problème a été corrigé avant que sa tâche soit cochée.

Ce n'est pas rapide. Une tâche a demandé 2,4 passes en moyenne, et la pire en a demandé 17.

Ce que ça coûte

J'utilise Claude avec le Max plan, donc le témoin n'ajoute rien à une facture. Il puise dans le forfait : pendant ces huit jours, 23 % de toute l'utilisation de Claude sur le projet est allée au témoin. C'est mesuré sur les mêmes transcriptions et aux mêmes prix : les jetons du témoin par rapport à tout ce que Claude Code a enregistré pour le projet. Il prend aussi du temps. Une exécution du témoin dure 5 minutes en médiane, et le dixième le plus lent, 29 minutes ou plus : 50 heures-agent en tout. Une tâche ne peut pas entrer dans un commit avant le retour de sa passe. Les corrections qu'il déclenche sont le travail de l'agent d'implémentation et ne sont pas comptées ici; je les tiens pour le but de l'exercice, pas pour son coût.

Si vous payez au jeton, voici ce que les mêmes exécutions coûteraient aux prix de l'API de Claude Opus 5.5 :

Type d'exécutionExécutionsCoûtPar exécution
À l'aveugle173186 $ US1,08 $ US
Adversariale39107 $ US2,75 $ US
Revérification par un nouvel agent3926 $ US0,65 $ US
Toutes251319 $ US

Le coût d'une exécution comprend les revérifications que le même agent a faites ensuite. Une tâche à risque a reçu sa revérification adversariale d'un nouvel agent plutôt que du même, ce qui explique les 39 exécutions adversariales pour 38 tâches à risque.

Comment je l'ai calculé

Voici les jetons que les transcriptions de Claude Code ont enregistrés, avec les prix de Claude Opus 5.5 indiqués sur la page des tarifs d'Anthropic :

Type d'exécutionLectures du cacheÉcritures dans le cacheEntréeSortie (estimée)
À l'aveugle266,7 M16,86 M0,01 M2,44 M
Adversariale176,8 M8,97 M0,004 M1,35 M
Revérification par un nouvel agent36,5 M2,32 M0,001 M0,33 M
Prix par million0,20 $ US5 $ US4 $ US20 $ US

Multipliez chaque colonne par son prix, puis additionnez le tout. Pour les exécutions à l'aveugle :

266,7 M de lectures du cache × 0,20 $ US + 16,86 M d'écritures dans le cache × 5 $ US + 0,01 M en entrée × 4 $ US + 2,44 M en sortie × 20 $ US = 186 $ US.

  • Les lectures du cache représentent la plus grande partie des jetons, parce que presque tout ce qu'un agent lit vient du cache. À 0,20 $ US par million, elles coûtent quand même moins cher que les écritures.
  • Les écritures dans le cache sont facturées au tarif du cache de 5 minutes, 5 $ US par million plutôt que les 8 $ US du cache d'une heure : les transcriptions enregistrent la durée que chaque écriture a achetée, et aucune de celles du témoin n'a utilisé la plus longue.
  • La sortie est une estimation. Les transcriptions ne l'enregistrent pas pour les agents de vérification, alors j'ai utilisé le taux de jetons par caractère de mes sessions principales, qui, elles, l'enregistrent.
  • Les transcriptions vont du 4 octobre, premier jour du témoin, jusqu'au commit ci-dessus.

Est-ce que ça en valait la peine?

Sur l'ensemble des 38 tâches à risque, les exécutions adversariales ont coûté environ 107 $ US aux prix de l'API et ont trouvé 51 affirmations qui ne tenaient pas et 104 qui ne tenaient qu'en partie, dont les fuites entre espaces de travail. Pour un logiciel dont le rôle consiste notamment à tenir le travail d'une équipe à l'écart de celui d'une autre, une seule fuite en production coûterait bien plus que ça.

Ce que je ne peux pas encore mesurer, c'est ce qui échappe au témoin, ou la fréquence de ses erreurs. Mon processus prévoit un test à chaque jalon : glisser exprès un bug que la tâche devrait détecter et voir si une nouvelle passe le trouve. Je ne l'ai pas encore lancé. C'est la prochaine étape.

Ce que je changerais

  • Un deuxième vérificateur vraiment différent. Le gain de l'article venait de deux moniteurs qui lisaient des signaux différents. Le mien lit le même signal deux fois : même modèle, mêmes consignes, mandat différent. Je vais essayer un autre modèle pour la passe adversariale, ainsi que les tests de mutation, qui modifient légèrement le code et vérifient que les tests s'en aperçoivent.
  • Des passes adversariales au-delà des tâches que je considère à risque. La passe adversariale a trouvé des problèmes dans 11 tâches à risque sur 38. Je ne connais pas le taux pour les autres, et un échantillon aléatoire me le dirait.
  • Une revérification complète avant de cocher. Aujourd'hui, une revérification peut ne couvrir que les affirmations qui ont échoué, si bien que les affirmations précédentes ne sont pas revérifiées sur le commit final.
  • Un registre des erreurs du témoin lui-même. Rien dans une passe ne dit si un non satisfait s'est avéré être une erreur du témoin, donc je ne peux pas donner son taux de fausses alertes. Une colonne de plus suffirait.
  • Une gravité pour chaque constat. Aujourd'hui, une maladresse de formulation et une fuite de données comptent autant dans le compte rendu.

Les consignes du témoin se trouvent dans le dépôt, avec les raisons derrière chaque règle.

Si vous vérifiez le travail de vos agents autrement, j'aimerais bien en discuter avec vous.

Partager

Envie d'en discuter?

Si cet article a soulevé des questions ou des idées, je serai ravi d'échanger.