TL;DR : Mon agent IA avait un fichier d’instructions de 246 lignes pour gérer les issues dans Linear. 150 de ces lignes étaient des contournements : UUIDs codés en dur, fallbacks vers curl, notes de « la CLI ne supporte pas X ». Je ne les ai pas réécrites — j’ai construit un outil qui les a rendues inutiles. Ces 150 lignes sont maintenant à zéro.


As-tu déjà écrit un document d’instructions si long que sa propre longueur démontre que quelque chose cloche ?

Je ne parle pas de documentation légitime. Je parle de ces fichiers qui commencent en disant « utilise l’outil X » et consacrent ensuite 80% du texte à expliquer quand l’outil X ne fonctionne pas et que faire à la place. Des instructions qui sont, en réalité, une liste d’excuses pour l’outil qu’ils auraient dû construire.

J’en avais un de ce genre. Et c’était embarrassant.

Anatomie de 150 lignes de déchet

Le contexte : je travaille avec un agent IA (Claude Code) qui gère mes issues dans Linear. Pour que l’agent sache comment procéder, j’avais un skill — un fichier d’instructions que l’agent lit quand il doit créer, lister ou mettre à jour des issues.

Le fichier faisait 246 lignes. De celles-ci, environ 100 étaient de la documentation légitime : quelles commandes existent, quelles équipes il y a, quels labels utiliser. Raisonnable.

Les 150 autres étaient des déchets défensifs. Trois catégories :

~30 lignes d’UUIDs codés en dur. La CLI que j’utilisais ne supportait pas --project. Donc le skill incluait 17 UUIDs (5 équipes + 12 projets) dans un tableau XML. L’agent devait chercher le bon UUID et construire une mutation GraphQL à la main pour assigner un projet. Une opération qui devrait être --project Tokamak nécessitait de mémoriser un UUID de 36 caractères.

~25 lignes de fallbacks vers curl. La CLI n’avait pas de recherche. Ni de filtrage par projet. Ni d’assignation de projet en create. Trois opérations de base, trois blocs de curl avec des queries GraphQL intégrées, escaping de guillemets, et en-têtes d’authentification. Chacun était une bombe à retardement attendant que l’agent avale un guillemet.

~15 lignes de « NE supporte PAS X ». Cinq avertissements de « la CLI NE supporte PAS » et deux de « OBLIGATOIRE » (–sort et –no-pager à chaque list). Attention bien : je documentais les lacunes de l’outil dans les instructions d’utilisation de l’outil. C’est comme si le manuel d’une voiture consacrait trois pages à expliquer que l’essuie-glace ne fonctionne que si tu donnes d’abord un coup au tableau de bord.

~80 lignes de contexte défensif. Une section entière intitulée « quand utiliser l’API au lieu de la CLI ». Tableaux de mapping répertoire→UUID. Heuristiques pour choisir les labels. Règles sur quoi faire quand la CLI plante. Du matériel qui n’existait que parce que l’outil était incapable.

Le panneau « attention, marche »

Quand un outil a une interface malcommode, la réaction naturelle est de documenter les contournements. Tu écris des instructions. Tu mets des avertissements. Tu crées une section « erreurs courantes ». Et plus la documentation est détaillée, plus tu te convaincs que le problème est résolu.

Mais il ne l’est pas. Tu as mis un panneau « attention, marche » au lieu de réparer la marche.

Et quand l’utilisateur de ces instructions est un LLM, le problème se multiplie. Un humain lit « NE supporte PAS –project » et s’en souvient (plus ou moins). Un LLM le lit, le traite, et trois tours de conversation plus tard utilise --project de toute façon. Ce n’est pas qu’il soit bête — c’est qu’il optimise pour compléter la tâche, et --project est le chemin logique pour assigner un projet. L’interdiction est du bruit dans un océan de signaux.

J’ai déjà écrit à ce sujet dans un autre post : les instructions verbeuses à un LLM sont l’équivalent exact de mettre des panneaux. Le LLM ne les ignore pas par rébellion. Il les ignore parce que sa fonction est de trouver le chemin le plus direct, et « n’utilise pas –project, à la place cherche l’UUID dans ce tableau puis fais un curl avec cette query GraphQL » n’est pas un chemin direct — c’est du bricolage.

La solution n’était pas un meilleur skill

J’aurais pu réécrire le skill avec de meilleures instructions. Plus claires. Avec des exemples. Avec des diagrammes. J’aurais pu passer de 246 à 400 lignes et couvrir chaque cas limite.

Ça aurait été comme agrandir le panneau.

Ce que j’ai fait, c’est construire lql — une CLI en Rust conçue spécifiquement pour qu’un agent IA (ou un humain, mais surtout un agent) puisse interagir avec Linear sans avoir besoin d’un manuel de survie.

La philosophie de conception tenait en une seule phrase : le mauvais chemin ne doit pas être interdit, il doit être impossible.

Pour être clair : tu n’interdis pas --status dans la documentation — tu fais en sorte que ça fonctionne. Tu ne documentes pas que --project n’existe pas dans create — tu fais en sorte qu’il existe. Tu ne maintiens pas un tableau d’UUIDs — tu résous automatiquement les noms. Tu n’offres pas de fallbacks vers curl — il n’y a rien que l’outil ne puisse pas faire. Tu ne mets pas « OBLIGATOIRE : –sort » — tu mets un default sensé.

Ce qui a disparu

Voici l’inventaire de ce que j’ai éliminé :

Déchet défensifLignes suppriméesMotif de suppression
UUIDs codés en dur (17 IDs)~30lql résout automatiquement les noms
Fallbacks vers curl + GraphQL~25lql a search, project, relate natifs
Notes « NE supporte PAS X » (5)~15Tout ce que l’agent attend, existe
Flags « OBLIGATOIRES » (2)~5Defaults sensés, pas de flags obligatoires
Section « quand utiliser API vs CLI »~15Il n’y a pas de « vs » — lql peut tout
Tableau de mapping contexte→UUID (XML)~20Auto-détection depuis config TOML
Heuristiques et règles défensives~40L’outil est tolérant, elles sont superflues
Total~150

Ce qui reste, c’est de la documentation légitime : quelles commandes existent, quelles équipes il y a, quels labels utiliser. Zéro contournement. Zéro excuse.

Pourquoi ça fonctionne (la partie intéressante)

La réduction de lignes est spectaculaire, mais ce n’est pas l’important. L’important, c’est pourquoi les lignes étaient superflues.

Chaque ligne de contournement dans l’ancien skill existait parce que l’outil sous-jacent était fragile et intolérant. Fragile parce qu’il échouait face à des inputs raisonnables (--status au lieu de --state). Intolérant parce qu’il rejetait sans alternative (--project n’existe pas, débrouille-toi).

Quand tu remplaces un outil fragile par un tolérant, les instructions se simplifient automatiquement. Tu n’as pas à réécrire le manuel — le manuel se réécrit tout seul parce qu’il n’y a plus rien à signaler.

C’est le même principe qui explique pourquoi le manuel d’un iPhone fait 10 pages et celui d’une imprimante 200. Ce n’est pas qu’Apple écrive de meilleure documentation. C’est que l’iPhone n’a pas besoin qu’on lui explique comment charger du papier, aligner des têtes, ou nettoyer le tambour.

Un outil tolérant génère une documentation courte. Un outil fragile génère des manuels de survie.

Et quand l’utilisateur est un LLM, cela compte doublement. Chaque ligne d’instructions est une ligne qu’il peut mal interpréter, oublier ou contredire. Un skill avec 150 lignes de contournements lui donne 150 occasions de mal suivre un contournement. Un avec zéro contournement lui donne… zéro occasion de se tromper.

Le modèle général

Ceci n’est pas exclusif aux CLIs ni à Linear. Le modèle est universel :

  1. Tu as un outil avec une interface malcommode
  2. Tu écris des instructions détaillées pour compenser
  3. Les instructions deviennent un manuel de survie
  4. Quelqu’un (humain ou LLM) ignore une partie du manuel
  5. Les choses se cassent
  6. Tu ajoutes plus d’instructions
  7. Retour à l’étape 4

La sortie de la boucle n’est pas d’écrire de meilleures instructions. C’est de réparer l’outil.

Si ton CLAUDE.md a plus de 20 lignes consacrées à expliquer comment ne pas utiliser quelque chose, cette chose doit être réécrite. Si ton skill a une section « erreurs courantes et comment les éviter », ces erreurs devraient être impossibles, pas documentées.

Chaque panneau « attention, marche » est un aveu que tu n’as pas réparé la marche.

À ton tour

La prochaine fois que tu te surprends à écrire des instructions verbeuses pour compenser un outil malcommode — que ce soit un CLAUDE.md, un README, ou un wiki interne — arrête-toi un moment et demande-toi :

  • Est-ce que je documente comment utiliser l’outil, ou comment survivre à l’outil ?
  • Combien de lignes disparaîtraient si l’outil acceptait les inputs que l’utilisateur lui donnerait naturellement ?
  • Est-ce que je mets un panneau ou répare la marche ?

Si plus de 30% de tes instructions sont des contournements, l’outil est cassé. Pas l’utilisateur. Pas la documentation. L’outil.

Répare la marche.


Série : Adversarial Programming