← Blog

Comment réduire les coûts en tokens des agents dans les workflows CLI

Un guide pratique pour réduire les coûts en tokens des agents dans les workflows CLI grâce à la compression des sorties, l'hygiène des commandes et la discipline du contexte.

By Dora 12 min read
Comment réduire les coûts en tokens des agents dans les workflows CLI

Je m’appelle Dora. J’ai lancé un seul npm test via Claude Code le mois dernier et j’ai regardé la session consommer environ 12 000 tokens d’entrée avant que l’agent me réponde. La sortie du test faisait 400 lignes. Peut-être 30 d’entre elles comptaient. Le reste — avertissements de dépréciation, bruit des dépendances, points de progression de Jest — tout ça est allé directement dans le contexte du modèle. J’ai payé pour chaque octet.

C’est là que j’ai arrêté de traiter les tokens comme « quelque chose que le modèle gère » et que j’ai commencé à les traiter comme un budget que je laissais fuir activement. Si vous exécutez des workflows CLI agentiques sur Claude Code, Gemini CLI, ou quelque chose de similaire, c’est probablement votre plus gros poste de coût — et la solution n’est pas un meilleur modèle, c’est une meilleure hygiène. La propre documentation de gestion des coûts d’Anthropic l’énonce clairement : les coûts en tokens évoluent avec la taille du contexte, et la plupart des optimisations se font avant que le modèle ne voie les données. Cet article explique comment réduire les coûts en tokens des agents dans les workflows CLI sans perdre le signal de débogage dont vous avez besoin.

Où les workflows CLI gaspillent des tokens

Avant de corriger quoi que ce soit, j’ai dû identifier les fuites. Deux modèles se sont démarqués, et ils apparaissent dans presque tous les workflows CLI que j’ai audités depuis.

Commandes verbeuses et sorties non pertinentes

Les commandes terminal ont été conçues pour des humains qui parcourent un écran, pas pour des LLM qui lisent octet par octet. git status imprime des codes ANSI dont le modèle n’a pas besoin. npm install déverse mille lignes d’arbre de dépendances que le modèle connaît déjà. next build répercute sa propre progression pendant quinze secondes. Rien de tout ça ne mérite sa place dans la fenêtre de contexte.

Les chiffres sont pires qu’ils n’y paraissent sur le papier. Un seul cargo test dans un projet Rust de taille moyenne peut produire 8 000 à 15 000 tokens de sortie. La plupart, c’est du bruit de compilation. Quand l’agent lit tout ça pour trouver une seule assertion qui échoue, vous avez payé des tarifs Opus pour le privilège de streamer un log de build.

C’est aussi pourquoi des projets communautaires comme rtk et tokf existent — ils s’intercalent entre le shell et l’agent, filtrent le texte générique avant qu’il n’atteigne le contexte, et rapportent des économies de 70 à 90 % sur les commandes courantes. Que vous utilisiez un wrapper ou non, le principe tient : la sortie brute du terminal n’est pas une donnée prête pour les LLM.

Accumulation de contexte et lectures répétées

La deuxième fuite est plus subtile. Chaque appel d’outil que l’agent effectue — lecture de fichier, grep, commande bash — reste dans l’historique de conversation. Au dixième tour, le modèle retraite neuf tours de sorties obsolètes à chaque requête. Le propre post-mortem d’avril d’Anthropic sur les problèmes de qualité de Claude Code décrit exactement cette dynamique : un bug de cache faisait s’accumuler l’historique de réflexion entre les tours, et l’utilisation des tokens a gonflé de 10 à 20 fois avant que quiconque ne le remarque. Même sans bugs, c’est le comportement par défaut. Les longues sessions sont des sessions coûteuses.

J’ai vérifié une de mes sessions vieille d’une semaine. L’agent avait lu le même package.json quatre fois. Aucune de ces relectures n’avait ajouté d’information — le fichier n’avait pas changé. C’était juste un artefact de l’agent qui ne savait pas ce qu’il savait déjà.

Étape 1 : Compresser les sorties bruyantes

La correction la moins chère, et de loin, est d’empêcher les données inutiles d’entrer dans le contexte dès le départ. Trois règles, dans cet ordre :

Filtrer à la source, pas après. Au lieu de npm test, l’agent exécute npm test --silent 2>&1 | grep -E "(FAIL|PASS|Error)". Au lieu de git status, il exécute git status --short. Au lieu de cargo build, il exécute cargo build --quiet 2>&1 | tail -20. Rien de tout ça n’est ingénieux. C’est juste de la discipline. L’agent obtient le test qui échoue, les fichiers modifiés, l’erreur réelle — rien d’autre.

Limiter la sortie des outils au niveau du harnais. Claude Code vous permet de définir une taille maximale de sortie d’outil. J’ai réduit la mienne à 8 000 caractères par appel. Quand une commande la dépasse, l’agent reçoit un avis de troncature et décide s’il doit affiner la requête. Ce seul paramètre m’a fait économiser plus de tokens que tous les autres changements combinés.

Utiliser un proxy CLI quand l’outil en amont ne peut pas se taire. Certaines commandes n’ont pas d’indicateur silencieux vraiment utile — next build, webpack, tout ce qui est basé sur Java. Pour celles-là, un wrapper qui supprime le texte générique connu vaut le temps de configuration. Les outils de la famille rtk/tokf gèrent ça de manière générique ; vous pouvez aussi écrire une fonction bash de 30 lignes pour les trois commandes qui vous dérangent le plus.

Il y a un vrai compromis ici. Une compression agressive peut masquer le signal de débogage. Quand un build échoue pour une raison que le filtre supprime — un avertissement de dépréciation devenu une erreur, un problème de configuration obscur enterré à la ligne 847 — l’agent obtient une image plus courte et moins utile. Ça m’est arrivé deux fois. Les deux fois, la solution était d’assouplir une règle de filtre, pas d’abandonner la stratégie.

Étape 2 : Limiter le contexte avant qu’il n’atteigne le modèle

Le filtrage des sorties gère les tokens nouveaux entrant à chaque tour. La discipline de contexte gère les tokens accumulés déjà à l’intérieur de la session. Des problèmes différents.

Les deux commandes qui comptent, toutes deux directement tirées des meilleures pratiques de Claude Code d’Anthropic, sont /clear et /compact. /clear réinitialise complètement la session — utile lors du passage à une tâche sans rapport. /compact résume l’historique antérieur tout en préservant les décisions clés et l’état actuel — utile quand la tâche continue mais que l’exploration initiale ne porte plus de charge. Claude Code se compacte automatiquement lorsqu’il approche des limites de contexte, mais attendre ce déclenchement est généralement trop tard. À ce stade, vous avez déjà payé le tarif gonflé pour plusieurs tours.

Mon habitude actuelle : j’exécute /compact à chaque frontière naturelle de tâche, avec une instruction comme /compact Focus on the failing test and the recent file edits. L’instruction compte. Sans elle, la compaction résume tout de manière approximative. Avec elle, l’agent conserve les parties qui comptent pour la prochaine phase.

Pour les agents basés sur API (pas l’abonnement CLI), la documentation d’édition de contexte d’Anthropic décrit un mécanisme plus strict : clear_tool_uses_20250919 efface automatiquement les anciens résultats d’outils une fois que le contexte dépasse un seuil. L’agent conserve la conversation mais perd les sorties brutes qu’il a déjà traitées. Pour les tâches agentiques à long horizon, c’est la valeur par défaut appropriée.

Un point à signaler : un CLAUDE.md gonflé est une taxe permanente. Il se charge à chaque tour, chaque session, pour toujours. J’ai réduit le mien de ~280 lignes à ~90. Le nombre de tokens par tour a diminué de manière notable et le comportement de l’agent n’a pas changé d’une façon que j’aurais pu mesurer.

Étape 3 : Repenser l’outillage des agents pour moins de gaspillage

Les deux premières étapes sont tactiques. Celle-ci est structurelle, et c’est là que vivent les économies durables.

Concevoir des outils qui émettent des sorties adaptées aux LLM. La CLI Spec portée par la communauté formule cet argument mieux que je ne pourrais le faire : les commandes destinées aux agents devraient prendre en charge un flag --output, séparer les données (stdout) des diagnostics (stderr), et fournir une pagination plutôt que de déverser du JSON non borné. Si vous construisez des CLIs internes que vos agents appelleront, suivez cette spec. Si vous utilisez des CLIs externes qui ne la respectent pas, enveloppez-les.

Préférer des outils étroits aux outils larges. Une fonction git_status_summary qui retourne trois champs structurés vaut mieux que laisser l’agent exécuter git status brut et analyser la sortie. Chaque couche d’analyse que le modèle doit faire est une couche où les tokens brûlent en traduction plutôt qu’en raisonnement. J’ai converti quatre de mes commandes les plus utilisées en fins wrappers Python qui retournent du JSON. L’utilisation de tokens sur aller-retour pour ces opérations a chuté d’environ 60 %.

Utiliser les sous-agents pour le travail intensif en lecture. La fonctionnalité de sous-agent de Claude Code exécute un contexte séparé pour des tâches comme « scanner le dépôt et résumer le flux d’authentification ». Les résultats reviennent sous forme de résumé compact — pas les 40 fichiers que le sous-agent a réellement lus. La conversation principale ne voit jamais les données brutes. Pour les tâches à forte exploration, c’est le plus grand gain structurel disponible.

Adapter le modèle au travail. Opus 4.7 est impressionnant et coûteux. La plupart du travail CLI — éditions de fichiers, corrections de tests, refactorisations de routine — fonctionne bien sur Sonnet, à environ 40 % du coût par token d’Opus. À noter : le nouveau tokenizer d’Opus 4.7 peut produire jusqu’à 35 % de tokens supplémentaires pour un texte identique comparé aux modèles précédents, ce qui amplifie l’écart de coût.

La mise en garde honnête : mesurez avant d’optimiser, puis mesurez après. J’ai établi une base de référence avec /cost (API) ou /usage (abonnement) pendant une semaine avant de changer quoi que ce soit, puis j’ai remessuré après chaque changement. Deux de mes « optimisations » se sont avérées ne rien changer de mesurable. Sans base de référence, vous devinez.

FAQ

Pourquoi les workflows terminal consomment-ils autant de tokens ?

Parce que la sortie terminal a été conçue pour les humains, et les agents paient octet par octet. Une commande de build typique émet des milliers de lignes de progression, d’avertissements et de texte générique dont le modèle n’a pas besoin. Combinez ça avec un historique de conversation qui ne se réinitialise jamais et des résultats d’outils qui s’accumulent entre les tours, et vous obtenez des sessions qui épuisent les budgets de contexte avant que le vrai travail ne commence.

Dans quelle mesure la compression des sorties peut-elle aider ?

D’après mes mesures, le filtrage au niveau des commandes combiné aux plafonds de sortie a réduit les tokens d’entrée par tour de 40 à 60 % sur les exécutions de tests, les builds et les opérations git. Les wrappers communautaires comme rtk rapportent des réductions de 80 à 90 % sur des commandes spécifiques, bien que ces chiffres supposent une sortie verbale dans le pire cas. Les gains réalistes dépendent des commandes que votre agent exécute le plus. Auditez les cinq premières, corrigez celles-là, et la plupart des économies apparaissent immédiatement.

Que devraient optimiser les équipes en premier ?

Dans cet ordre : plafonds de sortie des outils, discipline /clear et /compact, sélection du modèle. Les plafonds de sortie sont un changement de configuration unique sans coût continu. L’hygiène de session est une habitude, mais elle est gratuite une fois acquise. La sélection du modèle est le gain le plus facile à ignorer — faire tourner tout sur Opus quand la plupart des tâches fonctionnent bien sur Sonnet est une fuite silencieuse et importante.

Quand l’optimisation des tokens nuit-elle à la qualité du débogage ?

Quand vous compressez au-delà du point où l’agent peut voir ce qui a cassé. Une trace de pile tronquée, un avertissement de dépréciation filtré, un flag --quiet qui cache la vraie erreur — tout ça m’a coûté du temps réel. Le modèle que je suis : comprimer agressivement sur les commandes de routine (git status, npm install, les exécutions de tests réussies), conserver la sortie verbale pour les opérations qui échouent ou qui sont inconnues. Si vous vous retrouvez à relancer une commande sans filtres pour déboguer, c’est le filtre qui était mauvais, pas la stratégie.

Conclusion

Les coûts en tokens dans les workflows CLI ne sont pas un problème de modèle. C’est un problème de plomberie. La plupart des dépenses s’évaporent dans l’écart entre ce que les commandes terminal émettent et ce dont le modèle a réellement besoin pour raisonner — et cet écart est réparable avec le filtrage des sorties, la discipline de contexte, et un outillage qui respecte l’agent de l’autre côté.

J’utilise la configuration ci-dessus depuis environ six semaines. La consommation quotidienne de tokens sur Claude Code a baissé d’environ 55 %, la latence de l’agent s’est améliorée comme effet secondaire de contextes plus petits, et le workflow semble moins bruyant à déboguer. Aucun de ces chiffres n’est universel — votre base de référence et vos cinq premières commandes seront différentes. Mais le modèle tient : contrôlez ce qui entre dans le contexte, contrôlez ce qui reste dans le contexte, et laissez le modèle dépenser son budget pour raisonner plutôt que pour lire des logs de build.

C’est là que mes données s’arrêtent. La couche de compression continue d’évoluer, et les changements de tokenizer d’Anthropic signifient que ces chiffres ont une durée de vie. Ça vaut la peine de rétablir une base de référence tous les trimestres.

Articles précédents :