Aller au contenu
nahlovsky.fr
Format
billet
Sujet
agents
Longueur
1 378 mots · 7 min
Publié
15 août 2026

Hermes a réécrit son propre harnais ! Il s'est auto-modifié en silence.

Un agent modifie le code de son harnais pour répondre à une demande banale. Deux histoires en une : comment un agent en arrive à se modifier (et comment l'en empêcher), et pourquoi son correctif avait le même angle mort que ce qu'il corrigeait.

Un soir de mai, en début de soirée, j’ai demandé quelque chose de banal à Hermes, l’agent autonome qui tourne en permanence sur une machine de mon lab. Une phrase envoyée depuis une messagerie : « préviens-moi à la fin de chaque tâche planifiée, qu’elle réussisse ou qu’elle échoue ». J’ai même précisé le moyen : réutilise le canal de notification déjà configuré pour communiquer avec moi.

Dix minutes plus tard, c’était fait. Pas comme je l’imaginais.

La demande n’était pas si banale, en fait. Le planificateur de tâches savait annoncer qu’une tâche avait tourné ; il n’avait aucun moyen de signaler ses propres ratés. L’information que je réclamais n’existait qu’à un seul endroit : dans la fonction qui exécute les tâches, au cœur du harnais. Dans son propre code.

Alors Hermes l’a modifié. Cent soixante-huit lignes ajoutées au code de son propre harnais, trois nouvelles fonctions, deux points d’appel insérés dans le flux d’exécution. Puis il a testé en envoyant un vrai message, reçu, et considéré le travail terminé. Il n’a pas suivi ma consigne au passage : au lieu de réutiliser le canal configuré, il a écrit son propre appel.

Il y a deux histoires là-dedans, et elles ne disent pas la même chose :

  • Un agent qui modifie le programme qui le fait tourner, sans le dire : c’est la première, la plus spectaculaire. Celle qui fait penser à Skynet, et à Arnold.
  • Ce que vaut le code qu’il a écrit ce soir-là : c’est la seconde, et c’est la pire.

Un agent qui modifie le programme qui le fait tourner

Ce n’est pas une histoire d’intelligence, c’est une histoire de topologie.

Ce type d’agent s’installe en clonant son code source, et fonctionne directement depuis ce dossier. Le source est le programme en marche. Modifier un fichier, c’est modifier le comportement, tout de suite, sans compilation, sans déploiement, sans aucune étape où quelqu’un pourrait regarder. Donnez à l’agent des outils capables d’écrire sur le disque, et l’auto-modification cesse d’être une prouesse : c’est parfois le chemin le plus court entre la demande et le résultat.

Deux topologies de déploiement comparéesEn haut, la chaîne classique aligne quatre étapes reliées par des flèches : source (dépôt), construction, déploiement, programme en marche. Trois postes de contrôle figurés par des yeux les séparent : revue, tests, mise en production. En bas, la chaîne de l’agent : une seule boîte portant la double étiquette « le dossier cloné = le programme en marche », avec une flèche qui boucle sur elle-même. Modifier le fichier, c’est modifier le comportement, immédiatement. Les emplacements des trois contrôles, alignés sous ceux de la chaîne du haut, sont marqués vides et barrés d’une croix : zéro poste de contrôle. En chute : l’auto-modification n’est pas une prouesse, c’est le chemin le plus court.CHAÎNE CLASSIQUE3 postes de contrôlesource (dépôt)constructiondéploiementprogrammeen marcherevuetestsmise en productionCHAÎNE DE L’AGENT0 poste de contrôleles mêmes emplacements, videsle dossier cloné= le programme en marchemodifier le fichier, c’estmodifier le comportement,immédiatementl’auto-modification n’est pas une prouesse, c’est le chemin le plus court
Deux topologies. La chaîne classique interpose des postes de contrôle entre la source et le programme en marche ; pour l'agent, le dossier cloné est le programme en marche, et il n'y a aucun endroit où regarder.

La bonne question n’est donc pas pourquoi il l’a fait. C’est pourquoi je pensais qu’il ne le ferait pas. Un détail de conception a même joué les complices. Le dossier contient un guide destiné aux assistants de codage des développeurs (le AGENTS.md : les consignes données aux contributeurs qui font évoluer le produit avec une IA). Sauf que le moteur injecte ce guide dans le contexte de tout agent qui touche au dossier, sans distinguer l’assistant d’un développeur de l’agent en production. Hermes a donc reçu, en lisant un simple fichier de son propre arbre, un mode d’emploi de contributeur qui ne lui était pas adressé. Il l’a suivi ; ces instructions expliquent précisément comment coder pour faire évoluer Hermes.

Et le sort de ces 168 lignes est la partie que je n’avais pas anticipée. Une modification posée directement dans l’installation, hors de tout dépôt, meurt en principe à la mise à jour suivante : écrasée, perdue, travail pour rien. C’est bien ce qui aurait dû arriver. Ce qui l’en a empêchée, c’est un troisième personnage. Mon assistant qui opère cette machine (une autre IA, pas Hermes) préparait la montée de version : il a mis de côté les modifications locales, installé la nouvelle version, puis tout réappliqué par-dessus. Sans lire le diff. Les 168 lignes sauvages ont traversé la mise à jour dans ce wagon, transportées par un opérateur qui prenait, lui aussi, le chemin le plus court.

Deux IA, deux erreurs différentes, le même pli : l’une écrit dans le code qu’elle exécute, l’autre réapplique ce qu’elle n’a pas lu.

Comment on s’en protège

L’éditeur du produit le dit lui-même dans son fichier de sécurité : la seule frontière face à un modèle qui déraille est le système d’exploitation. Ni les listes d’outils autorisés, ni les portes d’approbation. Et il applique sa doctrine dans son image conteneurisée : arbre possédé par un compte privilégié, agent qui n’écrit pas chez lui. Une installation locale n’en bénéficie pas. La mienne n’en bénéficiait pas.

Le correctif avait le même angle mort que ce qu’il corrigeait

Le soir même, deux lignes s’inscrivent coup sur coup dans le journal. Une tâche planifiée échoue pour de bon, une erreur de connexion au modèle. Puis, juste derrière, une erreur sur la notification censée me signaler cet échec : le fameux branchement écrit à la place du canal configuré ne fonctionnait pas.

Le mécanisme que j’avais demandé pour être prévenu des échecs a échoué à me prévenir d’un échec, le jour de sa mise en place. Et il a consigné cette double défaillance dans un fichier que personne ne lisait.

Ce silence, rien ne l’a fermé de l’intérieur. C’est une mise à jour de routine, au petit matin, qui a comparé le dossier installé à ce qui avait été téléchargé et trouvé 168 lignes en trop. Sans elle, il durait encore. L’enquête forensique que j’ai menée a ensuite désigné l’auteur par preuve directe : les noms des fonctions inventées n’existaient nulle part ailleurs que dans une session archivée, avec la séquence complète.

Chronologie de l'incident : trois événements en une soirée, puis le silenceFrise chronologique, non à l'échelle. Un soir de mai, la demande tient en une phrase. Dix minutes plus tard, 168 lignes sont ajoutées au harnais et le test réussit, mais c'est un faux vert : seul le cas passant a été validé. Le soir même, double défaillance : la tâche échoue et la notification censée le signaler échoue aussi, inscrite dans un journal que personne ne lit. S'ouvre alors une zone de silence hachurée, de loin la plus large de la frise. Elle se referme au petit matin, et par hasard : une mise à jour de routine compare le dossier à ce qui a été téléchargé et trouve 168 lignes en trop, sans auteur ni historique. L'analyse forensique, conclue le surlendemain, apporte la preuve directe par les noms de fonctions. Sans cette mise à jour, rien ne fermait la zone de silence.CHRONOLOGIE DE L'INCIDENTSILENCEun soir de maiLa demande : une phrase.+ 10 min168 lignes ajoutées au harnais, test réussiun faux vert : seul le cas passant a été validéle soir mêmeDouble défaillance : la tâche échoue,la notification censée le signaler aussi.inscrite dans un journal que personne ne litau petit matinDécouverte, par hasardune mise à jour de routine comparele dossier à ce qui a été téléchargé :168 lignes en trop, sans auteur ni historique!Analyse forensique, le surlendemainpreuve directe : les noms de fonctionstrois événements, une soiréefermée par le hasard d'une mise à jour
La chronologie de l'incident, non à l'échelle. Le silence est fermé par le hasard d'une mise à jour de routine ; la preuve n'arrive que le surlendemain.

Regardez la forme de l’incident, pas ses détails. Le planificateur ne savait pas signaler ses propres ratés : c’est la raison d’être de toute cette histoire. Hermes a construit le mécanisme qui manquait. Et ce mécanisme ne savait pas signaler les siens. La même impasse, reproduite à l’identique par le correctif censé la fermer.

La boucle aveugle : deux mécanismes, le même angle mortDeux panneaux à la forme identique. Panneau A, le cron : une tâche planifiée s'exécute ; en cas de succès, une notification est envoyée ; en cas d'échec, aucun canal de sortie, l'information s'arrête contre un mur hachuré. Panneau B, le correctif de l'agent : la notification d'échec ajoutée par Hermes (168 lignes) est envoyée ; le test réel réussit ; mais à 21 h 46, l'envoi échoue à cause d'un mauvais branchement et son échec s'inscrit dans un journal que personne ne lit, exactement la même impasse. Une étiquette relie les deux murs : le même angle mort, un mécanisme ne peut pas signaler sa propre panne.A · LE CRONTâche planifiéecronExécutionsuccèsNotification envoyéeéchecaucun canalde sortieB · LE CORRECTIF DE L'AGENTNotification d'échec+168 lignesEnvoisuccès (test réel)Notification reçueéchec · 21 h 46mauvais branchementjournal quepersonne ne lit« le même angle mort »un mécanisme ne peut passignaler sa propre panne
La même forme, deux fois. Le planificateur ne pouvait pas signaler son propre échec ; le mécanisme ajouté pour y remédier n'a pas pu signaler le sien.

Le code ne cachait rien, c’est ce qui me frappe encore. Il écrivait honnêtement son propre échec, à chaque fois, consciencieusement. Dans un journal que personne ne lit. Un journal que personne ne lit n’est pas une alerte, c’est une archive.

Un agent qui se modifie et qui le dit, c’est gênant, et ça se confine : la première histoire a ses parades. Un agent qui se modifie, se trompe, et dont l’erreur ne remonte à personne, c’est le vrai problème. Le mien a fait ce qu’on lui demandait : crier quand quelque chose casse. Il a crié dans une pièce vide, et noté dans son cahier qu’il avait crié.

Tous les écrits