Aller au contenu
Blog

Technique

Un seul outil qui écrit du code : pourquoi notre agent n’a que ça

Un outil visible se paie à chaque étape. Une fonction que le code importe ne coûte rien tant qu’elle ne sert pas, et l’écart grandit à chaque intégration.

Parce qu’un outil que le modèle peut voir se paie à chaque étape de chaque conversation, alors qu’une fonction que le code importe ne coûte rien tant qu’elle ne sert pas. Balt n’a donc qu’un outil, qui exécute du code, et tout ce qu’il sait faire est une fonction qu’il importe. Le jour où une entreprise branche sa cinquantième intégration, la partie fixe de ce que relit le modèle n’a pris qu’une ligne de plus.

Ce choix n’est pas une coquetterie d’ingénieur. Il découle d’une arithmétique simple, et nous l’avons appris en faisant d’abord l’inverse, comme presque tout le monde : un outil par action, ajouté le jour où l’action devenait utile, jusqu’à ce que la liste coûte plus cher que le travail.

Combien coûte un outil que l’agent ne sert pas ?

Il coûte sa description entière, à chaque étape, multipliée par le nombre d’étapes, et c’est le poste que presque personne ne regarde. Nous avons décrit ailleurs comment les définitions d’outils pèsent 14 % de la facture d’un agent, devant le raisonnement qu’il produit réellement. Ce chiffre est une moyenne, et il cache une pente.

La pente, Anthropic l’a mesurée en novembre 2025 : cinq serveurs MCP courants, 58 outils au total, consomment environ 55 000 jetons avant que l’utilisateur ait écrit quoi que ce soit. Dans leurs propres systèmes, les définitions d’outils sont montées à 134 000 jetons avant optimisation. Un agent branché sur la messagerie, l’agenda, le CRM, l’ATS et le drive d’une entreprise relit donc, à chaque étape d’une tâche qui n’en touche qu’un, le mode d’emploi complet des quatre autres.

Le problème n’est pas seulement de volume. Plus la liste est longue, plus le modèle se trompe d’outil ou de paramètre, et c’est pourquoi la même publication rapporte que donner au modèle un moyen de chercher ses outils, au lieu de les lui présenter tous, a fait passer la justesse d’un modèle de 49 % à 74 % sur leurs évaluations MCP. Une liste d’outils trop longue rend l’agent plus cher et moins bon en même temps, ce qui est rare et mérite d’être pris au sérieux.

Pourquoi un seul outil plutôt qu’un outil par action ?

Parce qu’un modèle écrit mieux du code qu’il n’enchaîne des appels d’outils, et que le code garde hors du contexte tout ce qui n’a pas besoin d’y entrer. Trois publications indépendantes sont arrivées à la même forme en un an, et c’est ce qui nous a convaincus qu’il ne s’agissait pas d’une préférence.

La première est académique. Les auteurs de CodeAct, présenté à ICML en 2024, ont comparé dix-sept modèles exprimant leurs actions soit en appels structurés, soit en code Python exécutable, et le code obtient jusqu’à 20 % de réussite en plus. L’explication tient au fait qu’une boucle, une condition ou une variable intermédiaire s’écrivent naturellement en code et très mal en une suite d’appels séparés.

La deuxième vient de Cloudflare, en septembre 2025, sous un titre qui ne prend pas de gants : « nous avons tous mal utilisé MCP ». Leur argument porte sur l’apprentissage des modèles, qui ont vu des quantités immenses de code réel et très peu d’appels d’outils. Ils transforment donc chaque serveur MCP en bibliothèque typée, et ne donnent à l’agent qu’un outil, celui qui exécute le code dans un environnement isolé.

La troisième est celle d’Anthropic, deux mois plus tard. En laissant l’agent appeler les mêmes outils depuis du code, une tâche est passée de 150 000 à 2 000 jetons, soit 98,7 % de moins. Le gain vient de deux endroits : les descriptions ne sont lues que quand l’agent en a besoin, et les résultats intermédiaires restent dans l’environnement d’exécution au lieu de traverser le modèle. Une transcription de réunion de deux heures copiée d’un outil à l’autre ajoute environ 50 000 jetons au contexte ; manipulée par du code, elle n’y entre jamais.

Comment l’agent sait-il ce qu’il peut faire, s’il ne voit pas d’outils ?

Il lit, comme un collègue qui arrive ouvre la documentation de l’outil qu’il doit utiliser plutôt que d’apprendre tous les logiciels de l’entreprise le premier jour. Chaque capacité tient en une ligne dans ce que le modèle voit : ce qu’elle fait et où lire le détail. Le reste vit dans un fichier que l’agent ouvre quand la tâche l’y mène.

Cette ligne a une exigence que nous avons découverte en la ratant. Elle doit dire où lire, faute de quoi l’agent refuse, à juste titre, d’utiliser une capacité dont il ne trouve pas le mode d’emploi. Une capacité découverte par la lecture n’est utile que si le chemin vers la lecture est écrit.

L’autre conséquence est celle qui nous a fait choisir cette forme plutôt que de simplement trier les outils. L’agent peut écrire ses propres fonctions et les garder, au même endroit et sous la même forme que celles que nous livrons. Un agent qui ne peut utiliser que ce que nous avons écrit s’arrête à ce que nous avions imaginé, et c’est précisément là qu’un collègue commence à être utile. C’est aussi la raison pour laquelle un savoir-faire écrit et relu vaut mieux qu’un découpage en sous-agents : les deux reposent sur la même idée, un contexte qu’on charge quand il sert.

Et le cache de prompt, dans tout ça ?

C’est le second multiplicateur, et il est plus gros que le premier. Un modèle ne se souvient de rien entre deux appels, si bien que chaque étape renvoie tout ce qui précède ; le fournisseur facture alors la partie déjà vue à un dixième du prix, à une condition stricte : que le début de la requête soit identique octet pour octet.

Une liste d’outils qui change le jour où quelqu’un branche un logiciel ne coûte donc pas seulement ses propres jetons. Elle modifie le tout début de la requête et fait perdre la remise sur tout ce qui vient derrière, c’est-à-dire sur l’essentiel de la facture. C’est le mécanisme qui permet d’économiser 88 % sur cinquante étapes, et il ne fonctionne que si la partie fixe reste fixe.

Nous avons fini par comprendre que la règle de l’outil unique et la règle du préfixe stable sont la même règle vue des deux bouts. Une capacité qui s’ajoute ne doit rien changer à ce que le modèle relit à chaque étape, ni en taille ni en contenu, sinon elle se paie deux fois.

Que se passe-t-il quand la règle gêne ?

Elle gêne souvent, et c’est à ça qu’on reconnaît une règle plutôt qu’une préférence. Ajouter un outil visible est toujours plus rapide que d’écrire une fonction et sa ligne d’index, et chaque fois l’argument de la commodité est bon pris isolément.

Nous avons donc écrit la règle dans le code plutôt que dans un document. La liste des outils que le modèle peut voir est figée dans un test, et le build échoue si un outil y apparaît sans y être inscrit. Ce plafond peut baisser et ne peut pas monter : ni parce qu’un outil est petit, ni parce qu’une capacité serait plus facile à atteindre, ni parce qu’un fournisseur le demande.

Et il a baissé. Les lectures de la messagerie, qui doublaient des fonctions déjà disponibles, sont passées derrière le code. Les déclencheurs, qui n’étaient qu’une routine lancée par une condition plutôt que par une horloge, ont rejoint les routines. Le registre de l’entreprise est devenu une intégration comme une autre. À chaque fois, quelqu’un avait une bonne raison de laisser l’outil en place, et à chaque fois la raison valait pour cet outil et pour tous ceux qui viendraient après.

Un outil est resté alors qu’il aurait pu partir, parce qu’il était déjà livré et que le déplacer n’apportait rien. Nous l’avons écrit comme une exception datée plutôt que comme un précédent, parce qu’une liste ne grossit jamais par décision : elle grossit d’un paragraphe raisonnable à la fois.

Écrire du code rend-il l’agent plus dangereux ?

Non, et l’inverse serait un mauvais argument de vente. La forme de l’appel ne change rien à ce que l’agent peut atteindre, et c’est seulement ça qui compte en sécurité : une limite qui tient est un droit non accordé, qu’elle soit franchie par un outil ou par une ligne de Python.

Le code s’exécute dans un environnement isolé, et les identifiants restent du côté de la plateforme qui relaie les appels, ce qui est aussi le choix de Cloudflare. Une action sortante passe par la même validation humaine qu’avant. Et un serveur MCP rangé derrière une bibliothèque reste un fournisseur qui détient des accès sur vos systèmes : sa description est lue par le modèle quand celui-ci ouvre le fichier, ce qui ne la rend ni plus ni moins fiable qu’avant.

Ce que MCP règle bien, c’est la manière de brancher un logiciel et de décrire ce qu’il expose, et nous en consommons volontiers. Le débat sur ce que MCP change par rapport aux intégrations par API porte sur le branchement ; le nôtre porte uniquement sur l’endroit où les outils arrivent. MCP est un transport, pas une interface que le modèle doit porter.

Ce choix vaudra-t-il encore avec le prochain modèle ?

C’est le second test que nous appliquons, et il départage les cas où le calcul ne suffit pas : cette chose sera-t-elle encore utile à un modèle meilleur de deux générations ? Une liste d’outils ne devient pas moins chère quand le modèle progresse, alors qu’un modèle meilleur écrit du code meilleur et tire davantage des mêmes fonctions.

La concession est réelle et nous la payons. Un petit modèle écrit du code médiocre, un aller-retour dans un environnement d’exécution prend du temps, et un agent qui doit lire avant d’agir met une étape de plus à commencer. Pour un assistant qui fait trois choses, une liste de trois outils est plus simple et le restera.

Pour un collègue qui travaille dans tous les logiciels d’une entreprise, le calcul ne se discute plus au-delà de quelques intégrations, et il empire avec chacune. Reste la question que pose tout choix d’architecture fait pour un modèle donné : ce qui se passe le jour où ce modèle est retiré, et ce qu’il faut avoir rangé à part pour que la migration ne casse rien.

Questions fréquentes

Un agent qui écrit du code est-il plus risqué qu’un agent qui appelle des outils ?

Le risque ne vient pas de la forme de l’appel mais de ce que l’agent peut atteindre. Le code s’exécute dans un environnement isolé, les identifiants restent hors de sa portée, et une action sortante passe par la même validation que si elle venait d’un outil. Écrire du code ne donne aucun droit supplémentaire.

Faut-il renoncer aux serveurs MCP pour adopter cette forme ?

Non. Un serveur MCP reste la manière la plus simple de brancher un logiciel, et nous en consommons. La seule différence est l’endroit où ses outils arrivent : dans une bibliothèque que le code importe, et non dans la liste que le modèle relit à chaque étape.

Cette architecture marche-t-elle avec n’importe quel modèle ?

Elle suppose un modèle qui écrit du code correct, ce qui est le cas des modèles de pointe depuis 2024 et l’est beaucoup moins des petits modèles. C’est un pari assumé : chaque génération écrit mieux que la précédente, alors qu’une liste d’outils ne devient pas moins chère quand le modèle progresse.

Combien d’outils un agent peut-il voir avant que cela coûte cher ?

Il n’y a pas de seuil universel, parce que tout dépend de la taille de chaque description et du nombre d’étapes. L’ordre de grandeur publié est d’environ 1 000 jetons par outil, payés à chaque étape, ce qui devient le premier poste fixe d’un agent dès qu’il est branché sur quelques logiciels.

Sources

  1. Anthropic, Code execution with MCP: building more efficient agents (novembre 2025)anthropic.com
  2. Anthropic, Introducing advanced tool use on the Claude Developer Platform (novembre 2025)anthropic.com
  3. Cloudflare, Code Mode: the better way to use MCP (septembre 2025)blog.cloudflare.com
  4. Wang et al., Executable Code Actions Elicit Better LLM Agents (CodeAct), ICML 2024arxiv.org
  5. Anthropic, documentation du cache de promptdocs.anthropic.com
  6. Cobalt, MCP vs API : pourquoi vos intégrations ATS vont disparaîtrecobalt-ia.com

À lire ensuite