J’ai un agent de code —Claude Code— qui interagit avec Linear, mon gestionnaire de tickets, environ 800 fois par mois : il liste des tâches, crée des tickets, change des statuts, ajoute des commentaires. J’ai analysé 165 de ses sessions et compté plus de 500 erreurs et plus de 370 tentatives réitérées.

Aucun de ces échecs n’était dû à une erreur de l’API de Linear. Toutes ces erreurs étaient liées à l’interface : l’agent communiquait avec la ligne de commande, mais cette dernière ne comprenait pas sa demande.

L’estimation conservatrice du coût de ces erreurs est d’environ 700 000 tokens par mois consommés exclusivement à cause de conflits avec l’outil : refaire des tentatives, lire le message d’erreur, corriger, réessayer. Un coût invisible sur les factures, mais qui se fait ressentir à chaque session.

Contexte : l’agent est désormais l’utilisateur principal

Une CLI, ou interface en ligne de commande, est historiquement conçue pour un humain. Et un humain est un utilisateur étonnamment robuste. Si une commande échoue, il consulte l’aide avec --help. Si le message d’erreur est obscur, il va chercher une solution. Si l’outil a un comportement particulier, il apprend à l’anticiper et ne commet plus la même erreur.

Un agent IA ne fait pratiquement rien de tout cela. Il n’accumule pas d’expérience d’une session à l’autre comme une personne le ferait. Il lit la documentation avec beaucoup moins d’attention que vous l’imaginez. Et lorsqu’il rencontre un problème, il ne s’arrête pas pour enquêter : il improvise ce qui lui semble être la solution la plus probable.

Cela change fondamentalement qui est le client principal de votre outil. Si un agent l’appelle 800 fois par mois et que vous l’utilisez manuellement seulement trois fois, le principal consommateur de votre interface est l’agent. Concevoir une CLI pour l’utilisateur humain tout en espérant que l’agent s’y adapte équivaut à optimiser pour un utilisateur minoritaire.

Concevoir consciemment pour cet utilisateur particulier a un nom : agentic experience. C’est pour les agents ce que l’expérience utilisateur (UX) est pour les personnes et ce que l’expérience développeur (DX) est pour ceux qui travaillent avec votre API. Et son meilleur outil d’évaluation n’a pas besoin d’être créé : il est déjà disponible. C’est le journal des erreurs de l’agent.

Les erreurs ont une logique

J’ai compté comme erreur toute invocation de la CLI se terminant par un code de sortie différent de zéro. En appliquant ce critère, les plus de 500 erreurs relevées ne semblaient pas être aléatoires : la plupart se répartissaient en trois grandes catégories.

Modèle d’erreurCe que faisait l’agentCe que cela révèle du design
Flags inventésÉcrivait --status au lieu de --state ; --priority urgent au lieu de --priority 1Le flag réel n’était pas ce qu’on aurait naturellement deviné
Opérations inexistantesEssayait de rechercher du texte, filtrer par projet, ou assigner un projet lors de la créationL’outil ne couvrait pas le flux de travail réel
Flags obligatoires oubliésOubliait --sort, --no-pager, --no-interactiveDes choix obligatoires que l’outil aurait pu déduire

Quand l’agent écrivait --status, il ne devinait pas aléatoirement : il faisait une supposition logique à propos de l’interface. --status est, objectivement, un nom aussi raisonnable que --state. L’agent pariait sur l’option la plus probable ; mais mon design ne correspondait pas à cette probabilité.

Un quatrième problème, non mentionné dans ce comptage parce qu’il ne produit jamais de commandes erronées, est la sortie verbale excessive. La CLI retournait des listes en JSON avec environ 50 tokens par ticket. Ces commandes réussissaient — code de sortie zéro —, elles ne sont donc pas considérées comme des erreurs ; mais multipliées par des listes volumineuses et 800 invocations par mois, elles constituent l’autre moitié des 700 000 tokens. Un coût qui passe inaperçu précisément parce que tout semble fonctionner correctement.

L’erreur d’interprétation

Il serait facile d’interpréter ces 500 erreurs de manière simple et erronée : l’agent utilise mal l’outil. Cette lecture est incorrecte, et voici pourquoi.

Un flag inventé indique en réalité que le nom correct n’était pas intuitif. Un flag obligatoire oublié montre qu’il ne devrait peut-être pas être requis : si l’outil peut attribuer une valeur par défaut logique, exiger une saisie explicite impose une tâche inutiles à celui qui l’appelle. Une sortie trop verbeuse indique que le format choisi s’adressait au mauvais utilisateur final.

En résumé, le journal des erreurs d’un agent n’est pas une liste de ses fautes : c’est une spécification. Chaque erreur met en lumière, en négatif, une partie manquante ou inadaptée de l’interface que vous auriez dû concevoir. Et c’est la spécification la plus honnête que vous recevrez : elle est gratuite, volumineuse — bien au-delà de ce qu’un retour utilisateur classique pourrait fournir — et dépourvue de filtres. Lorsqu’une personne rencontre des difficultés avec une mauvaise CLI, elle s’adapte ou reste silencieuse. L’agent, lui, ne s’adapte pas ; il reproduira mécaniquement la même erreur, encore et encore, en laissant une trace claire.

Cela rejoint un principe que j’ai évoqué dans un autre article : la voie incorrecte doit être impossible, pas interdite. Interdire une action incorrecte, c’est écrire de la documentation — « N’utilisez pas --status ». Mais la documentation suppose que quelqu’un la lise attentivement. Rendre l’erreur impossible, c’est faire du design.

Par conséquent, la solution ne résidait pas dans une meilleure documentation, mais dans un meilleur outil.

La refonte

J’ai réécrit la CLI — baptisée lql — autour de ce principe. Quatre décisions de conception ont concentré l’essentiel des améliorations.

Tolérance au lieu de rejeter. Si l’agent écrit --status, l’outil l’accepte comme alias de --state et continue. S’il écrit --priority urgent, c’est automatiquement interprété comme --priority 1, avec un message pour indiquer l’assomption. Le chemin “erroné” le plus probable devient simplement un chemin valide. L’outil ne pénalise pas des hypothèses raisonnables, il les prend en charge.

Des erreurs pédagogiques. Lorsque quelque chose n’existe pas, le message n’est pas simplement « flag inconnu». Il devient une leçon : --filter n’existe pas. Pour filtrer par état : --state <état>. Pour chercher : lql search "texte". Le message d’erreur agit ainsi comme de la documentation, fournie au moment précis où l’agent est prêt à la consulter en profondeur : juste après un échec.

Zéro flag obligatoire. lql list fonctionne sans aucun argument : il trie par priorité, filtre les statuts actifs et détecte l’équipe en fonction du répertoire de travail. Aucun --sort n’est oublié, car aucun --sort n’est nécessaire. Un flag que l’agent ne peut pas oublier est simplement un flag qui n’a pas lieu d’être requis.

Une sortie adaptée au véritable consommateur. Celui qui lit la sortie est un LLM qui paye pour chaque token. L’outil utilise TOON (Token-Oriented Object Notation), un format compact qui encode le schéma une seule fois dans un en-tête, puis diffuse les valeurs au format positionnel.

FormatTokens par ticket50 tickets
XML~70~3 500
JSON~50~2 500
TOON~25~1 250

TOON n’est pas une invention personnelle ; il s’agit d’un format ouvert (toonformat.dev) que l’outil se contente d’adopter. L’option --json reste disponible pour les scripts et pipelines, où le consommateur final est une machine conventionnelle.

La mise à l’épreuve

La métrique qui me convainc le plus n’est pas un benchmark de performance. C’est celle-ci.

L’agent a besoin d’un fichier d’instructions pour interagir avec Linear — dans Claude Code, on appelle cela un « skill ». Avec l’ancienne version de la CLI, ce fichier comptait 246 lignes. 150 d’entre elles étaient des workarounds : « si cela arrive, fais cela », « souviens-toi d’ajouter ce flag », « ne fais pas ça comme ça ». Une documentation compensatoire, écrite pour pallier les lacunes de l’outil.

Avec la CLI remaniée, ce fichier ne fait plus que 205 lignes avec zéro workaround. Un outil tolérant n’a pas besoin d’être excusé. Ces 150 lignes n’ont pas disparu parce qu’elles ont été effacées ; elles ont disparu simplement car elles ne servaient plus à rien.

Les limites de cette analyse

Par souci d’honnêteté, il est important de souligner les limites de cette investigation. L’analyse porte sur un agent — Claude Code — et une API, Linear. La répartition exacte des trois principaux types d’erreur pourrait être différente avec un autre agent ou une autre API. Cependant, la nature même du problème — l’agent devine l’interface la plus plausible et échoue lorsque cette probabilité ne correspond pas au design — me semble universelle. Mais cela reste une hypothèse à vérifier, et non un fait.

Le décompte des plus de 500 erreurs et 370 reessais provient de l’analyse des fichiers JSON des 165 sessions de Claude Code. La définition d’une erreur — un code de sortie différent de zéro — et celle d’un réessai — la répétition d’une commande après un échec initial — reposent sur des critères mécaniques et reproductibles ; bien que les données proviennent d’un usage réel et non d’une expérimentation contrôlée.

Essayez-le

lql est un logiciel libre sous licence MIT. Le code source est disponible sur github.com/frr149/lql.

brew install frr149/tools/lql
lql list --team PROD --state Todo --priority urgent

Que faire si vous connectez un agent à une CLI

Si vous faites appel à un agent IA pour utiliser une CLI — qu’elle soit la vôtre ou celle d’un tiers —, vous disposez déjà des données nécessaires pour améliorer votre outil : les erreurs commises par cet agent durant son usage.

Ne les considérez pas comme des anomalies dans les journaux ni comme des faiblesses de l’agent. Analysez-les, classez-les par type et lisez-les pour ce qu’elles sont : le plan de votre interface, dessiné en négatif. Chaque flag que l’agent invente correspond à une suggestion de ce que devrait être le flag réel ; chaque action qu’il tente mais n’existe pas représente une demande de fonctionnalité.

Cet article a été publié en espagnol et traduit avec l’aide de l’IA.