Aller au contenu principal
Architecture IA

Hooks et skills : remettre du déterminisme dans un agent qui part en vrille

Pourquoi une consigne dans le prompt ne suffit pas, et comment bloquer mécaniquement les actions dangereuses d'un agent IA avec des hooks.

Par Xavier Agapé10 min de lecture

Tu as écrit dans ton prompt : « Ne supprime jamais de fichiers sans demander. » Trois heures plus tard, l’agent a supprimé un dossier.

Il n’a pas désobéi. Il a simplement traité ta phrase pour ce qu’elle est techniquement : un morceau de texte parmi des dizaines de milliers d’autres dans son contexte, sans statut particulier. Une consigne n’est pas une contrainte. Et cette distinction est la ligne qui sépare un agent utilisable d’un agent qu’on ne peut pas laisser tourner seul.

TL;DR

  • Une instruction dans le prompt est une intention. Un hook est une garantie. Sur les règles critiques, seule la garantie compte.
  • Trois hooks couvrent l’essentiel des incidents : blocage des actions destructrices, lecture obligatoire avant écriture, détection de boucle.
  • Le hook ne dit pas seulement « non » : il renvoie à l’agent un message d’erreur exploitable, qui lui indique quoi faire à la place.
  • Un hook mal calibré est pire que pas de hook : trop strict, il provoque exactement la boucle infinie qu’il devait empêcher.

Pourquoi une consigne dans le prompt ne tient pas

Trois mécanismes, indépendants les uns des autres, font qu’une règle écrite dans le prompt finit par être ignorée.

La dilution. Plus le contexte s’allonge, plus le poids relatif de chaque instruction diminue. Une règle écrite au tour 1 concurrence, au tour 40, des milliers de tokens de code, de sorties de commandes et de messages d’erreur. Sur un petit modèle, cette dégradation est particulièrement rapide ; sur un modèle frontière elle est plus lente, mais elle existe.

Le conflit d’instructions. « Ne supprime rien » et « répare le build cassé » peuvent entrer en contradiction quand le build est cassé par un dossier corrompu. Le modèle arbitre, et il ne t’a pas demandé ton avis.

L’interprétation. « Ne supprime jamais de fichiers » couvre-t-il un git checkout qui écrase des modifications locales ? Un npm install qui réécrit un fichier de verrouillage ? Le modèle tranche selon sa lecture, pas selon ton intention.

La conclusion est structurelle : tout ce qui doit être vrai à 100 % doit sortir du prompt et passer dans le code qui exécute les actions.

Qu’est-ce qu’un hook, concrètement ?

Un hook est un point de contrôle placé entre la décision de l’agent et son exécution. L’agent demande une action ; le hook l’inspecte ; il l’autorise, la refuse, ou la modifie.

La séquence :

  1. L’agent demande à exécuter une action (commande shell, écriture de fichier, appel d’outil).
  2. Le hook reçoit cette demande avant exécution.
  3. Il applique une règle déterministe, du code, pas un modèle.
  4. Il laisse passer, ou il refuse avec un message d’erreur destiné à l’agent.

Ce quatrième point est le plus important, et le plus souvent bâclé. Un hook qui refuse en silence produit un agent perdu. Un hook qui répond « suppression récursive interdite ; pour retirer un fichier, utilise la corbeille du projet » produit un agent qui corrige sa trajectoire tout seul.

Le hook est un contrat d’interface entre l’agent et l’environnement. Il ne rend pas l’agent plus intelligent : il rend son environnement plus sûr, ce qui n’est pas la même chose, et c’est bien plus fiable.

Les trois hooks qui règlent 80 % des incidents

Hook 1 : Blocage des actions destructrices

Ce qu’il fait : il refuse toute commande capable de détruire du travail non récupérable, suppression récursive, réinitialisation forcée d’un dépôt, écrasement d’un fichier de configuration sensible.

Pourquoi il est indispensable : c’est le seul type d’erreur qui n’est pas rattrapable. Un mauvais code se corrige. Un dossier supprimé, non.

Le piège : raisonner par liste noire. Interdire rm -rf est facile à contourner sans intention de nuire, une variable, un chemin relatif, un script intermédiaire, et la commande passe. La bonne approche est l’inverse : une liste blanche de ce qui est autorisé, en refusant tout le reste. C’est le principe classique de validation aux frontières, celui-là même que l’OWASP recommande pour toute entrée non fiable, et la sortie d’un modèle est, par définition, une entrée non fiable.

Le message de refus doit indiquer l’alternative, sans quoi l’agent va simplement reformuler la même commande jusqu’à trouver une variante qui passe.

Hook 2 : Lecture obligatoire avant écriture

Ce qu’il fait : il refuse toute modification d’un fichier qui n’a pas été lu dans le tour courant.

Pourquoi : un agent modifie souvent un fichier à partir de ce qu’il croit être son contenu, généralement ce qu’il a écrit lui-même plus tôt. Entre-temps, un autre processus, un formateur automatique ou un humain a pu le changer. La modification est alors appliquée sur une version qui n’existe plus, et le travail existant est écrasé silencieusement.

Le piège, et il est réel : ce hook est le plus susceptible de créer une boucle. Si l’agent ne comprend pas pourquoi il est bloqué, il retente la même écriture indéfiniment. Deux conditions pour l’éviter :

  • Le message d’erreur nomme explicitement l’action attendue : « fichier non lu dans ce tour, lis-le avant de le modifier ».
  • Une lecture partielle doit suffire à débloquer l’écriture de la portion concernée, sinon un gros fichier devient impossible à modifier.

Hook 3 : Détection de boucle

Ce qu’il fait : il compte les actions identiques consécutives et interrompt au-delà d’un seuil.

Pourquoi : un agent qui rencontre une erreur qu’il ne comprend pas répète. Sans information nouvelle dans son contexte, il n’a aucune raison de produire une réponse différente : c’est une propriété du mécanisme, pas un bug.

Ce qui doit se passer à l’interruption, et c’est la partie utile : ne pas se contenter de stopper, mais injecter de l’information nouvelle. Forcer une recherche documentaire sur le message d’erreur, ou remonter le problème à un humain. Une interruption sèche laisse l’agent dans le même état ; une interruption avec information nouvelle lui donne une chance de sortir de l’impasse.

Hooks et skills : deux outils, deux rôles

La confusion est fréquente, alors qu’ils répondent à des besoins opposés.

Skill Hook
Nature Information Contrainte
Moment Avant l’action, pour informer Pendant l’action, pour autoriser
Fiabilité Probabiliste (le modèle peut ne pas l’appliquer Déterministe) le code s’exécute toujours
Bon usage « Voici comment on structure un composant ici » « Cette commande est interdite »
Mauvais usage « Ne supprime jamais rien » Encoder une préférence de style

Une skill transmet une méthode, un contexte, une convention, les mécanismes de chargement à la demande sont décrits dans la documentation Anthropic sur les Agent Skills. Elle est puissante pour élever la qualité du travail, et inadaptée pour garantir une règle de sécurité.

La règle de partage : si l’infraction à la règle est rattrapable, c’est une skill. Si elle ne l’est pas, c’est un hook.

Cette séparation entre ce qui informe et ce qui contraint est exactement la même que celle qui structure une organisation d’agents pilotée par des boucles ITIL : la procédure guide, le contrôle bloque.

Le hook qui manque presque partout : la validation d’installation

Un agent qui décide d’installer une dépendance ne vérifie pas qu’elle existe vraiment. Il propose un nom plausible, et un nom plausible peut être un nom inventé, comme le montre l’affaire des packages NPM hallucinés adoptés par des centaines de dépôts.

Le hook correspondant est simple à écrire et résout définitivement le problème : avant toute installation, interroger le registre officiel. Le package existe-t-il ? Depuis quand ? Combien de téléchargements ? En dessous d’un seuil, on refuse et on remonte à l’humain.

C’est cinq lignes de code, et c’est la différence entre un agent qui peut installer des dépendances et un agent auquel on ne peut pas laisser cette permission.

Comment calibrer sans se bloquer

Un hook trop strict rend l’agent inutilisable ; trop laxiste, il ne sert à rien. La méthode qui fonctionne :

  1. Commence par observer sans bloquer. Journalise ce que le hook aurait refusé, pendant plusieurs sessions réelles. Tu découvriras des faux positifs auxquels tu n’aurais pas pensé.
  2. Active le blocage sur la règle la plus critique uniquement. Une seule à la fois.
  3. Mesure les boucles. Si un hook déclenche des répétitions, le problème est presque toujours son message d’erreur, pas sa règle.
  4. Traite les faux positifs par des exceptions nommées, pas en assouplissant la règle générale.

Checklist : équiper un agent de garde-fous

  • Toute règle dont l’infraction est irréversible est implémentée en hook, pas en prompt.
  • Le blocage des actions destructrices fonctionne par liste blanche, pas par liste noire.
  • Chaque refus renvoie un message qui indique l’action alternative attendue.
  • Un hook impose la lecture d’un fichier avant sa modification.
  • Une lecture partielle suffit à débloquer la modification correspondante.
  • Un compteur détecte les actions identiques répétées.
  • L’interruption de boucle injecte une information nouvelle, elle ne se contente pas de stopper.
  • Toute installation de dépendance est validée contre le registre officiel.
  • Chaque hook a d’abord tourné en mode observation avant d’être activé.

FAQ

Les hooks ralentissent-ils l’agent ?

Marginalement en temps d’exécution, un contrôle de ce type se compte en millisecondes. En revanche, ils ralentissent bel et bien un agent mal calibré, en le forçant à relire des fichiers ou à reformuler des commandes. Ce ralentissement-là est un bon signal : il indique un message d’erreur peu clair ou une règle trop large, pas un problème de performance.

Faut-il des hooks avec un modèle frontière, ou seulement avec un petit modèle ?

Dans les deux cas, mais pour des raisons différentes. Un petit modèle a besoin de hooks pour ne pas dériver au quotidien. Un modèle frontière suit beaucoup mieux les consignes, mais il agit sur des périmètres plus larges et de façon plus autonome, l’incident est plus rare et son ampleur plus grande. La règle ne change pas : ce qui doit être vrai à 100 % ne se demande pas, il s’impose.

Comment gérer un hook qui bloque une action légitime ?

Par une exception nommée et documentée, jamais en désactivant la règle. Concrètement : une liste explicite de chemins ou de commandes autorisés, versionnée avec le projet et relue comme du code. Un hook qu’on désactive « juste pour cette fois » ne se réactive jamais, et c’est précisément la session où il aurait servi.

Peut-on remplacer les hooks par une simple demande de confirmation à l’humain ?

C’est complémentaire, pas équivalent. La confirmation humaine est adaptée aux actions rares et à fort impact : un déploiement, une suppression volontaire. Elle ne tient pas sur les actions fréquentes, un humain sollicité cent fois par heure valide sans lire, ce qui revient à ne rien contrôler. Les hooks traitent le flux courant, la confirmation traite l’exception.

Conclusion

La fiabilité d’un agent ne vient pas de la qualité de son prompt : elle vient de ce que son environnement l’autorise à faire.

Un prompt bien écrit améliore la qualité moyenne du travail. Il ne borne pas le pire cas. C’est le rôle des hooks, et cette borne conditionne tout le reste, parce que c’est elle qui détermine le degré d’autonomie qu’on peut raisonnablement accorder.

Commence par un seul hook : celui qui bloque ce que tu ne pourras pas récupérer. Fais-le tourner en observation une semaine. Tu sauras alors exactement quels autres écrire.

Cette approche est mise en œuvre en direct dans le live sur le développement avec un modèle local, où les hooks sont construits au fur et à mesure des blocages rencontrés.

À lire aussi