Engineering the Agentic Stack · Partie 3

Utilisation d’outils par les AI agents : MCP, CLI, Skills et exécution de code

Traduction automatique Cet article a été traduit automatiquement depuis la version originale en anglais.

Mise à jour de l’article

Publié initialement le 24 mars 2026. Relu et mis à jour le 6 septembre 2026. Cette mise à jour couvre la spécification MCP révisée, les tool calls programmatiques, ainsi que les nouveaux éléments sur les coûts et les limites de l’utilisation d’outils.

Un agent a besoin d’un moyen d’agir : un tool call JSON, un service MCP, une commande CLI ou du code dans un sandbox. Il peut également avoir besoin d’instructions pour choisir et utiliser ce mécanisme. Les Skills fournissent ces instructions. Le harness est le programme ordinaire qui entoure le modèle : il construit les prompts, vérifie un appel proposé, exécute un appel approuvé et détermine quand la tâche est terminée.

Ce troisième article de la série ajoute la couche d’action aux reasoning loops de la partie 1 et à la mémoire de la partie 2. La partie 4 examine le contrôle de policy avant l’exécution, et la partie 6 examine le harness qui exécute à la fois l’appel et ce contrôle.

L’écosystème des outils a évolué en 2025–2026. MCP, le Model Context Protocol, a fourni aux fournisseurs un moyen commun d’exposer des services externes. Les agents capables d’exécuter du code ont montré qu’un modèle pouvait parfois composer un petit programme plus efficacement qu’émettre une longue séquence d’appels JSON. Anthropic a fait état d’une réduction de 98,7 % du nombre de tokens pour un workflow Google Drive vers Salesforce, tandis que l’article CodeAct a rapporté des gains de réussite des tâches allant jusqu’à 20 points de pourcentage dans son protocole de benchmark. Ces résultats décrivent leurs tâches et leurs harnesses, et ne démontrent pas un avantage universel de l’exécution de code.

Je compare les tool calls JSON, les outils MCP, les outils CLI et l’exécution de code, puis je montre où les Skills s’intègrent dans cet ensemble. Une section ultérieure applique les principes de conception de l’Agent-Computer Interface (ACI) au Market Analyst Agent, un petit agent de recherche LangGraph que j’ai construit pour la partie 1 et qui récupère des données de marché avant de rédiger un rapport d’analyste.

Pour une décision rapide concernant l’interface, consultez Interfaces d’outils pour AI agents.

En bref : utilisez les tool calls JSON pour les petites actions typées, MCP pour les intégrations partagées, les commandes CLI pour les opérations locales établies et le code dans un sandbox pour les tâches multi-étapes. Les Skills fournissent des instructions réutilisables pour les utiliser. Avant l’exécution d’un appel, le harness doit vérifier ses arguments et approuver son effet ; un schéma ou un transport ne le fait pas de lui-même. Quelle que soit la surface, l’Agent-Computer Interface (ACI) doit rendre les actions claires, les retours compacts et les erreurs récupérables.


Surfaces d’exécution et guidance procédurale

La reasoning loop propose un appel. Le harness vérifie ses arguments et détermine si l’appel est autorisé, puis l’envoie à un outil ou à un sandbox et renvoie le résultat. Les schémas JSON, le transport MCP, les wrappers CLI et les code runners peuvent contraindre les entrées, mais aucun ne décide si l’action demandée est autorisée. Les Skills fournissent les instructions nécessaires à cette étape. Ces surfaces d’exécution présentent des compromis différents entre coût en tokens, flexibilité et enforcement.

Cinq modalités d’outils pour AI agents et leurs compromisCinq modalités d’outils pour AI agents et leurs compromis

1. Tool calling JSON : la base

Le pattern d’origine : vous définissez les tool schemas en JSON, le LLM émet des function calls structurés et votre code les exécute. Cette approche est bien comprise et fonctionne correctement pour les petits ensembles d’outils.

# Schema cost depends on its text, structure, and the model tokenizer
tools = [
    {
        "name": "get_stock_price",
        "description": "Get the current stock price for a ticker symbol",
        "input_schema": {
            "type": "object",
            "properties": {
                "ticker": {"type": "string", "description": "Stock ticker (e.g., NVDA)"}
            },
            "required": ["ticker"]
        }
    }
]

Comptez les tokens de vos schémas réels. Le coût dépend de leur longueur et du nombre de schémas chargés par le host ; une recherche de prix compacte et un contrat d’API profondément imbriqué ne constituent pas des unités équivalentes. La découverte différée peut éviter de charger tout le registre.

2. MCP pour les intégrations partagées

MCP est le standard vers lequel la plupart des fournisseurs ont convergé. Un serveur MCP est un processus qui publie une liste d’outils via un protocole wire défini — stdio pour un processus local, HTTP pour un processus distant. Votre agent exécute un client MCP qui se connecte au serveur, lui demande quels outils sont disponibles et lui transmet les appels du modèle. Le même serveur fonctionne ainsi avec tout client parlant le protocole. En décembre 2025, Anthropic a donné le protocole à la Linux Foundation, dans le cadre de l’Agentic AI Foundation qu’il a cofondée avec OpenAI et Block. Google, Microsoft et AWS soutiennent la fondation en tant que membres platinum. OpenAI a ajouté la prise en charge de MCP à son Responses API. Selon l’annonce du don d’Anthropic en décembre 2025, l’écosystème comptait plus de 10 000 serveurs MCP publics actifs et plus de 97 millions de téléchargements mensuels des SDK Python et TypeScript.

MCP convient aux intégrations SaaS multi-fournisseurs (Figma, Notion, Salesforce), aux services sans équivalent CLI et aux environnements nécessitant une orchestration OAuth. Sa valeur réside dans une couche partagée de découverte et de transport. La gouvernance dépend toujours de l’authentification, de l’autorisation, de la journalisation et des contrôles de déploiement du serveur.

La version du protocole est désormais une décision de migration concrète. La révision du 28/07/2026 modifie des comportements supposés par les anciens tutoriels :

ModificationVérifications à effectuer dans une intégration
Les requêtes stateless remplacent le handshake d’initialisation et les sessions de transportEnvoyez les métadonnées de protocole pour chaque requête ; utilisez server/discover pour vérifier la prise en charge. Vérifiez les versions du client et du serveur.
Les requêtes multi-aller-retour renvoient InputRequiredResultGérez les demandes d’entrées supplémentaires, puis réessayez l’opération initiale avec les réponses et l’état de continuation.
Les Tasks passent dans l’extension officielle TasksVérifiez la prise en charge de l’extension au lieu de supposer l’existence de l’ancienne API Tasks expérimentale du cœur.
La reprise des flux SSE est suppriméeUn flux de réponse interrompu nécessite une nouvelle requête. Prévenez séparément les effets métier en double.

La même révision déprécie Roots, Sampling, Logging et OAuth Dynamic Client Registration ; une dépréciation n’implique pas une suppression immédiate. L’enregistrement actuel des clients privilégie les Client ID Metadata Documents. Certaines intégrations existantes peuvent encore utiliser une ancienne révision ; inspectez donc le SDK installé et le contrat du serveur avant d’adopter une nouvelle fonctionnalité.

La réalité de la production est plus complexe que ne le suggèrent les chiffres mis en avant.

Le Vulnerable MCP Project regroupe des rapports portant notamment sur la prompt injection, la validation des entrées, l’authentification et les contrôles réseau. Une telle collection aide à identifier des cas de test ; sans dénominateur d’exposition, elle ne permet pas de comparer MCP au shell ou aux appels directs d’API.

Le tool poisoning est la classe d’attaque qui m’inquiète le plus. Invariant Labs a démontré que des outils MCP empoisonnés pouvaient exfiltrer des données même lorsqu’ils n’étaient jamais invoqués. La simple lecture de leurs métadonnées par le modèle suffit à déclencher l’attaque. Les benchmarks MCPTox, qui ont testé 20 agents LLM contre 45 serveurs MCP réels, ont rapporté un taux moyen de réussite des attaques de 72,8 % pour o1-mini dans leur configuration de tool poisoning. Il s’agit du résultat de benchmark d’un modèle, et non d’une moyenne sur les 20 agents ni d’un taux d’incidents en conditions réelles.

L’overhead en tokens est le problème opérationnel. Une équipe exécutant des serveurs MCP pour GitHub, Slack et Sentry (environ 40 outils au total) a constaté que 55 000 tokens de définitions de schémas étaient injectés avant même qu’un utilisateur ne demande quoi que ce soit. Une autre a indiqué que 143 000 tokens sur 200 000 disponibles (72 %) étaient consommés par les seules définitions d’outils.

Comparaison de l’overhead en tokensComparaison de l’overhead en tokens

Le rapport d’Anthropic sur le Tool Search Tool a indiqué des contextes approximatifs de 77 000 tokens avant le début du travail et de 8 700 après une découverte différée, avec environ 72 000 tokens de définitions d’outils dans la configuration traditionnelle. Seuls les trois à cinq outils nécessaires à la requête sont chargés, mais une étape de découverte est ajoutée avant l’invocation ; cette approche est moins utile pour les petits ensembles d’outils compacts, utilisés fréquemment à chaque session.

3. Les Skills encapsulent l’expertise, pas l’exécution

Les agent skills sont un format ouvert permettant de regrouper des instructions et des fichiers auxiliaires. Les outils fournissent des capacités (ce que les agents peuvent faire), tandis que les Skills fournissent une expertise (ce que les agents savent de la manière d’accomplir des tâches complexes).

Le format SKILL.md définit une skill comme un fichier Markdown doté d’un frontmatter YAML. Le standard ouvert n’exige que name et description ; l’exemple ci-dessous utilise également deux extensions de Claude Code, argument-hint et user-invocable, ainsi que son placeholder d’argument positionnel $0 :

---
name: deploy
description: Deploy the application to production
argument-hint: "[environment]"
user-invocable: true
---
Deploy the application to the $0 environment (default: staging).
Steps:
1. Run the test suite
2. Build the production bundle
3. Deploy using the deploy script
4. Verify the deployment health check

Les Skills utilisent la divulgation progressive. Au démarrage, l’agent reçoit environ 100 tokens de name et description. Il ne charge le SKILL.md complet que lorsqu’il a besoin de la skill, puis charge les scripts, documents ou assets référencés au fur et à mesure. Ce coût initial est bien inférieur aux quelque 55 000 tokens que peuvent consommer environ 40 outils MCP avant le début du raisonnement. Une skill active ajoute tout de même ses instructions et ses ressources au contexte.

Utilisez les Skills pour les connaissances métier, les procédures multi-étapes et les tâches récurrentes telles que les migrations de bases de données ou les intégrations de paiement. Elles conviennent aux tâches dans lesquelles l’agent a besoin d’instructions sur la manière d’utiliser une capacité existante.

4. Outils CLI et shell

Les interfaces CLI peuvent être beaucoup moins coûteuses en contexte lorsque le modèle connaît déjà la commande. Scalekit a rapporté une différence de 4 à 32× en tokens entre ses chemins CLI et MCP sur 75 exécutions. Cette étude de cas mesure ses propres outils et tâches ; elle ne remplace pas une comparaison fondée sur vos définitions d’outils et sorties de commandes.

Les commandes largement documentées telles que git, docker, kubectl, gh, curl et jq nécessitent souvent peu de texte de schéma introductif. Les CLI moins courantes ou internes ont toutefois besoin d’une aide découvrable, d’exemples et d’une sortie machine-readable stable.

Le guide d’Ugo Enyioha, “Writing CLI Tools That AI Agents Actually Want to Use”, formalise huit règles de conception :

  1. La sortie structurée est obligatoire — prenez en charge --json
  2. Les codes de sortie constituent le contrôle de flux — utilisez des codes distincts pour les différents types d’erreurs
  3. Les commandes doivent être idempotentes
  4. Auto-documentées --help avec des exemples réalistes
  5. Concevez pour la composabilité--quiet pour les valeurs brutes, prise en charge de stdin
  6. Fournissez les flags --dry-run et --yes
  7. Prenez en charge l’introspection de version
  8. Gérez l’authentification via des variables d’environnement

La CLI ne possède pas de découverte au niveau du protocole. Le tool calling JSON peut transporter des schémas typés, tandis que MCP standardise la découverte des outils et, pour les transports HTTP, un modèle d’autorisation. Aucun des deux ne fournit à lui seul une gouvernance : le host, le serveur ou le harness doit appliquer la policy et enregistrer les appels nécessaires à l’audit. Une valeur par défaut pratique consiste à utiliser la CLI pour le développement et les opérations locales, et MCP pour l’intégration de services externes partagés lorsque la découverte entre clients ou l’orchestration OAuth justifie l’overhead du serveur.

5. Exécution de code pour les tâches multi-étapes

C’est le changement dans le tooling des agents que je trouve le plus important. Au lieu d’émettre du JSON structuré pour invoquer des fonctions prédéfinies une par une, l’agent écrit un script Python ou bash. Le script appelle plusieurs outils, traite les résultats avec des boucles et des conditions, puis ne renvoie au contexte du modèle que le résumé final.

Anthropic a introduit le Programmatic Tool Calling (PTC) en beta. Le guide API actuel utilise le Messages API standard avec code_execution_20260120 ou une version ultérieure ; le lancement initial en beta relève du contexte historique. Le fondement académique est l’article CodeAct (Wang et al., ICML 2024), qui a testé 17 LLMs et constaté que les actions sous forme de code obtenaient jusqu’à 20 points de pourcentage de réussite supplémentaires et nécessitaient 30 % d’actions en moins que les alternatives JSON.

Flux d’exécution de codeFlux d’exécution de code

Trois études de cas de première main montrent où ce pattern peut être utile : Vercel et Cloudflare ci-dessous, puis l’exemple d’analyse de dépenses d’Anthropic. Considérez-les comme des éléments fournis par les vendors et reproduisez la comparaison sur vos propres tâches.

  • Vercel a reconstruit d0, son agent de données de langage naturel vers SQL. Son ancien exemple de code nomme 17 outils ; le nouvel exemple expose ExecuteCommand et ExecuteSQL. Vercel présente cette refonte comme une suppression de 80 % de ses outils, mais cette affirmation est le titre de Vercel, et non un pourcentage déductible des outils nommés dans les exemples. Sur cinq requêtes représentatives, Vercel indique que la réussite des tâches est passée de 4/5 à 5/5, que le temps d’exécution moyen a été réduit d’un facteur 3,5 (274,8 s à 77,4 s) et que l’utilisation moyenne de tokens a diminué de 37 % (environ 102 k à environ 61 k). Leur formulation : « Les meilleurs agents sont peut-être ceux qui disposent du moins d’outils. »

  • Cloudflare a développé « Code Mode », qui permet aux agents d’écrire du TypeScript pour appeler son API au lieu de définir des tool schemas, réduisant ainsi l’overhead du contexte. Leur raisonnement : « Les LLMs disposent d’une quantité énorme de TypeScript réel dans leurs données d’entraînement, mais seulement d’un petit ensemble d’exemples artificiels de tool calls. »

Voici le pattern présenté dans la documentation PTC d’Anthropic. Dans l’illustration séquentielle d’analyse de dépenses d’Anthropic, le tool calling traditionnel nécessite plus de 20 passes d’inférence distinctes, les données intermédiaires transitant par le contexte. Après la recherche de l’équipe, un host prenant en charge les appels d’outils parallèles peut regrouper les demandes de dépenses indépendantes ; le chiffre de plus de 20 ne rend pas cela impossible. Anthropic indique que le code généré pour répondre à la même question réduit les données arrivant dans le contexte de 200 Ko de lignes de dépenses brutes — plus de 2 000 lignes — à 1 Ko de résultats. Le script ci-dessous illustre ce contrôle de flux avec des adaptateurs Python async personnalisés : ils acceptent des arguments positionnels et renvoient des listes et dictionnaires décodés. Il ne s’agit pas du contrat natif des wrappers PTC.

# Custom decoded Python adapters, not native Claude PTC wrappers.
import asyncio
import json

async def main() -> None:
    team = await get_team_members("engineering")
    levels = list(set(member["level"] for member in team))
    budgets = dict(zip(
        levels,
        await asyncio.gather(*(get_budget_by_level(level) for level in levels)),
    ))
    expenses = await asyncio.gather(
        *(get_expenses(member["id"], "Q3") for member in team)
    )
    over_budget = []
    for member, employee_expenses in zip(team, expenses):
        total = sum(expense["amount"] for expense in employee_expenses)
        limit = budgets[member["level"]]["travel_limit"]
        if total > limit:
            over_budget.append(
                {"name": member["name"], "spent": total, "limit": limit}
            )
    # Only this final summary returns to the LLM context
    print(json.dumps(over_budget))

asyncio.run(main())

Pour utiliser les wrappers PTC natifs de Claude, transmettez à chaque outil un dictionnaire d’arguments, décodez la chaîne JSON renvoyée et utilisez await au niveau supérieur dans l’environnement d’exécution géré, plutôt que de démarrer une event loop avec asyncio.run. L’exemple d’adaptateurs personnalisés ci-dessus suppose un runtime de script Python ordinaire ; il ne constitue pas non plus un exemple de connecteur MCP natif prêt à l’emploi. Les contraintes actuelles de l’API PTC excluent les outils strict: true et les outils de connecteur MCP natifs du calling programmatique, et restreignent les schémas récursifs. Un bridge code-to-MCP personnalisé constitue une intégration distincte. allowed_callers explique comment Claude appelle un outil ; ce n’est pas une frontière d’autorisation. Le host doit valider chaque invocation renvoyée, y compris un appel direct inattendu.

Le LLM ne voit que le résumé JSON final, et non les milliers de lignes de dépenses traitées dans le sandbox. L’économie réalisée n’est pas spécifique aux rapports de dépenses : le billet distinct d’Anthropic sur l’exécution de code donne le chiffre le plus marquant de ce pattern, avec un workflow Google Drive vers Salesforce passant d’environ 150 000 tokens à environ 2 000, soit une réduction de 98,7 %.

Le guide PTC actuel rapporte également un contre-exemple : sur les tâches airline, retail et telecom de tau2-bench, le PTC n’a pas modifié les scores et a coûté environ 8 % de plus. Sur un benchmark distinct de gestion de projet avec 75 outils, il a réduit les tokens d’entrée facturés d’environ 38 % sans modifier la précision. Ces évaluations internes ne citent qu’un modèle Claude de production, sans fournir son identifiant exact. Les petits workflows séquentiels peuvent ne pas économiser suffisamment pour compenser le cold start du conteneur et le coût de génération du code.

L’efficacité en tokens constitue un gain potentiel. Les boucles et les conditions ne coûtent rien, et l’exécution de code peut gérer les erreurs avec des handlers explicites au lieu de demander au modèle de raisonner sur les échecs en langage naturel. Une voie d’exécution de code peut maintenir des données intermédiaires sensibles hors du contexte du modèle, mais cela ne garantit pas la confidentialité : l’isolation, les contrôles d’egress, les credentials limités et la journalisation doivent être appliqués séparément.

Quand le tool calling JSON reste pertinent : pour les opérations atomiques uniques, les environnements sans infrastructure de sandbox, les modèles plus petits dont la génération de code est faible ou les exigences d’audit nécessitant la journalisation de chaque invocation d’outil.


Comparaison de l’exécution d’outils pour AI agents

DimensionTool Calling JSONMCPSkills (SKILL.md)CLI/BashExécution de code (PTC)
Idéal pourActions simples et unitairesSaaS multi-fournisseursProcédures réutilisables sélectionnant une surfaceWorkflows de dev, opérations localesOrchestration multi-étapes
Overhead en tokensTokens des schémas chargésSchémas chargés ou différésMétadonnées de découverte d’environ 100 tokens ; les instructions/ressources actives ajoutent du contexteTokens de l’aide, des commandes et des sortiesSchémas d’entrée, code et sortie
Éléments sur les tâchesRéférence de base dans les études citéesDépend du serveur et de la tâcheN/A (couche d’expertise)À mesurer sur des tâches natives CLICodeAct : jusqu’à +20 points
ComposabilitéDirigée par le harness ; les appels dépendants ajoutent des toursDirigée par le harness ; les appels dépendants ajoutent des toursGuide une surface sous-jacenteÉlevée (pipes, chaînage)Très élevée (flux/filtrage côté code)
Surface de sécuritéAutorité sur les arguments et les effetsIdentité du serveur et autorité des outilsDépend du host et des ressourcesShell, chemins, credentialsCode, accès aux données et egress
Complexité de mise en placeFaibleMoyenne (déploiement du serveur)Faible pour les instructions ; dépend de la surfaceTrès faible (CLI existantes)Moyenne (infrastructure de sandbox)
Latence des appels dépendantsGénéralement 1 tour/appel du modèleGénéralement 1 tour du modèle + transport/appelHéritée de la surfaceGénéralement 1 tour/appel du modèle1 tour de génération du script ; le host exécute le flux
DébogageBon (I/O structurées)Modéré (couche de transport)Bon (Markdown lisible)Excellent (visible)Bon (code lisible)

Le tool calling JSON, MCP, la CLI et l’exécution de code sont des surfaces d’exécution. Les Skills sont des instructions qui guident l’une de ces surfaces ; leur latence, leur contexte et leur mise en place dépendent donc du mécanisme sélectionné. Les « meta-tools » désignent les quelques points d’entrée génériques dont un agent exécutant du code a besoin — ExecuteCommand et ExecuteSQL chez Vercel, par exemple — plutôt qu’un schéma pour chaque opération. Les lignes consacrées à la composabilité et à la latence décrivent les appels dont les arguments ultérieurs dépendent des résultats précédents. Le tool calling JSON et MCP peuvent émettre simultanément des appels indépendants, mais les appels dépendants nécessitent généralement un nouveau tour du modèle. Le PTC déplace ce contrôle de flux dépendant et ce filtrage dans un script, puis renvoie un résumé au modèle. Les cellules relatives aux tokens et à la réussite des tâches synthétisent les exemples cités ; elles ne proviennent pas d’un benchmark contrôlé unique couvrant les cinq colonnes.


L’Agent-Computer Interface (ACI) pour les outils des AI agents

Le terme « Agent-Computer Interface » (ACI) a été forgé par John Yang, Carlos E. Jimenez et leurs collègues de Princeton dans leur article sur SWE-agent (NeurIPS 2024). La qualité des interfaces humaines dispose de toute une discipline — l’interaction humain-machine, ou HCI. L’article soutient que les agents fondés sur des modèles de langage méritent le même traitement : ils constituent « une nouvelle catégorie d’utilisateurs finaux, avec leurs propres besoins et capacités, qui bénéficieraient d’interfaces spécialement conçues ».

Leurs résultats d’ablation quantifient cette idée. Avec le même modèle de base GPT-4 Turbo, l’ablation SWE-bench Lite de l’article a atteint 18,0 % avec l’ACI complète de SWE-agent sur 300 tâches, contre 7,3 % pour la condition shell-only sans démonstration et 11,0 % avec une démonstration. La comparaison montre que l’interface et les conditions de démonstration ont modifié sensiblement les performances dans cette configuration ; elle n’isole pas la conception de l’interface de toutes les autres différences et ne montre pas que le modèle n’a effectué aucun travail. Dans la même ablation d’interface, l’activation du linting a fait passer la condition d’édition de 15,0 % à 18,0 % ; sur l’ensemble de test SWE-bench, 51,7 % des exécutions de SWE-agent ont rencontré au moins une modification rejetée par le linter avant sa propagation.

Principes de conception de l’ACIPrincipes de conception de l’ACI

Anthropic a adopté l’ACI comme concept fondamental dans son guide “Building Effective Agents”, en le présentant comme l’un des trois principes centraux : « Concevez soigneusement votre agent-computer interface au moyen d’une documentation et de tests approfondis des outils. » Leur recommandation pratique : « Une règle générale consiste à réfléchir à l’effort consacré aux interfaces humain-machine et à prévoir d’investir autant d’efforts dans la création de bonnes agent-computer interfaces. »

Quatre principes ACI en pratique

1. Les actions doivent être simples et faciles à comprendre. L’erreur la plus courante consiste à envelopper les endpoints d’API un par un. Au lieu de list_users, list_events et create_event, implémentez schedule_event, qui recherche les disponibilités et planifie le rendez-vous en un seul appel. Au lieu de read_logs, implémentez search_logs, qui ne renvoie que les lignes pertinentes avec leur contexte.

2. Les actions doivent être compactes et efficaces. Regroupez les opérations importantes dans le moins d’actions possible. Dans le Market Analyst Agent, je combine la récupération des prix et les métriques de base dans un seul outil get_stock_snapshot, au lieu d’exiger des appels distincts pour le prix, le volume, la capitalisation et le ratio PE.

3. Les retours de l’environnement doivent être informatifs, mais concis. Évitez de renvoyer du HTML brut ou des payloads API complets. Résolvez les identifiants cryptiques en noms sémantiques. Les tests d’Anthropic ont ajouté un enum response_format afin que l’agent puisse demander une réponse concise (environ 72 tokens) ou détaillée (environ 206 tokens), soit une différence de coût en tokens d’environ 3×.

4. La validation doit limiter la propagation des erreurs. La détection automatique des erreurs aide les agents à identifier et corriger rapidement leurs erreurs. Dans SWE-agent, un éditeur de fichiers personnalisé intégrant le linting rejette automatiquement les erreurs de syntaxe — c’est l’étape de validation à l’origine du chiffre de 51,7 % ci-dessus. Il s’agit de la validation des entrées et sorties d’un outil, et non du filtrage de contenu autour d’un appel de modèle assuré par les produits de guardrails de la partie 4 ; le même terme est utilisé dans les deux cas. J’applique le même principe au Market Analyst Agent en validant les arguments des outils avec des schémas Pydantic avant l’exécution :

from pydantic import BaseModel, Field, field_validator

from market_analyst.utils import normalize_ticker

class StockQuery(BaseModel):
    """Validated input for stock queries.

    Pydantic catches malformed tickers before the API call,
    preventing error propagation through the reasoning loop.
    """
    ticker: str = Field(description="Stock ticker symbol (e.g., NVDA)")

    @field_validator("ticker")
    @classmethod
    def validate_ticker(cls, v: str) -> str:
        return normalize_ticker(v)

class StockHistoryQuery(StockQuery):
    """Validated input for price history queries."""

    period: str = Field(default="1mo", description="Time period: 1d, 5d, 1mo, 3mo, 6mo, 1y")

    @field_validator("period")
    @classmethod
    def validate_period(cls, v: str) -> str:
        valid = {"1d", "5d", "1mo", "3mo", "6mo", "1y"}
        if v not in valid:
            raise ValueError(f"Invalid period: {v}. Must be one of {valid}")
        return v

Le normalizer partagé supprime les espaces et convertit la valeur en majuscules, puis accepte les chiffres de ticker et les suffixes contenant des points ou des tirets tels que BRK.B et BF-B ; StockHistoryQuery, et non StockQuery, est propriétaire de period.


Patterns de conception d’outils pour AI agents qui fonctionnent

Le guide d’Anthropic “Writing effective tools for agents” décrit les outils comme « un nouveau type de logiciel qui reflète un contrat entre des systèmes déterministes et des agents non déterministes ».

Considérez les descriptions d’outils comme du prompt engineering

Les descriptions doivent comporter au moins trois ou quatre phrases, couvrant les cas d’utilisation de l’outil, les paramètres obligatoires et facultatifs, le format de sortie ainsi que les cas limites. Anthropic indique que le choix entre un namespacing par préfixe ou par suffixe (asana_search contre search_asana) a eu des « effets non négligeables » dans ses propres évaluations de tool use. L’étude ne dit pas quel schéma est le meilleur ; testez donc les deux sur votre ensemble d’outils au lieu de supposer que les préfixes sont préférables. Anthropic a également réinjecté les transcripts de ses agents d’évaluation dans Claude Code et lui a demandé de réécrire les outils. Sur des jeux de test tenus à l’écart, cette boucle a trouvé de nouvelles améliorations « allant même au-delà de celles obtenues avec des implémentations d’outils “expertes” » — que ces outils aient été écrits manuellement par ses chercheurs ou générés par Claude.

# Bad: vague, no context for when to use
tools = [{
    "name": "search",
    "description": "Search for items",
}]

# Good: specific, with input examples and edge cases
tools = [{
    "name": "search_news",
    "description": (
        "Search for recent news articles about a specific stock or company. "
        "Use this tool when the user asks about recent events, earnings, "
        "announcements, or market-moving news for a specific ticker. "
        "Returns up to 10 articles sorted by relevance. "
        "For company competitors rather than news, use search_competitors instead."
    ),
    "input_schema": {
        "type": "object",
        "properties": {
            "query": {
                "type": "string",
                "description": "Search query. Examples: 'NVDA earnings Q3 2025', 'Tesla delivery numbers'"
            },
            "max_results": {
                "type": "integer",
                "description": "Max articles to return (1-10, default 5)",
                "default": 5
            }
        },
        "required": ["query"]
    }
}]

Les tests internes d’Anthropic ont montré que l’ajout d’un champ input_examples faisait passer la précision sur la gestion complexe des paramètres de 72 % à 90 %.

Renvoyez une sortie à fort signal, machine-readable

Utilisez des libellés sémantiques plutôt que des identifiants de bas niveau (uuid, mime_type) dans la réponse par défaut. Conservez un ID lorsqu’un outil ultérieur en a besoin, ou proposez une réponse détaillée qui l’inclut. Par exemple, un résultat de recherche pour Jane peut être concis à lire, tandis qu’un résultat détaillé inclut l’ID requis par send_message. Structurez la réponse afin que l’agent puisse raisonner dessus sans devoir analyser du boilerplate :

# Bad: raw API response dumped to agent
def get_stock_snapshot(ticker: str) -> dict:
    response = api.get(f"/v1/quotes/{ticker}")
    return response.json()  # 500+ tokens of nested JSON

# Good: high-signal summary the agent can immediately reason about
def get_stock_snapshot(ticker: str) -> dict:
    data = api.get(f"/v1/quotes/{ticker}").json()
    return {
        "ticker": ticker,
        "price": data["regularMarketPrice"],
        "change_pct": round(data["regularMarketChangePercent"], 2),
        "volume": data["regularMarketVolume"],
        "market_cap_b": round(data["marketCap"] / 1e9, 1),
        "pe_ratio": data.get("trailingPE"),
        "summary": f"{ticker} at ${data['regularMarketPrice']:.2f} "
                   f"({'up' if data['regularMarketChangePercent'] > 0 else 'down'} "
                   f"{abs(data['regularMarketChangePercent']):.1f}%)"
    }

Renvoyez des erreurs que la loop peut exploiter

La gestion des erreurs nécessite quatre mécanismes distincts, car ils traitent des classes d’échec différentes :

  1. Retry avec exponential backoff pour les erreurs transitoires
  2. Chaînes de fallback de modèles en cas d’indisponibilité d’un fournisseur
  3. Routage par classification d’erreur — les erreurs transitoires sont réessayées, les erreurs récupérables par le LLM sont renvoyées à l’agent avec leur contexte et les erreurs nécessitant un humain sont escaladées
  4. Récupération depuis un checkpoint pour survivre aux crashs

Le guide d’Anthropic “Writing effective tools for agents” recommande des erreurs d’outils claires et une conception guidée par les évaluations, mais ne fournit aucun chiffre universel sur ce que ces quatre mécanismes permettent de récupérer. Mesurez le taux de récupération, les retries et les escalades sur votre propre suite de tâches.

import httpx
from tenacity import retry, retry_if_exception, stop_after_attempt, wait_exponential

def is_transient_error(error: BaseException) -> bool:
    if isinstance(error, (httpx.TimeoutException, httpx.NetworkError)):
        return True
    if isinstance(error, httpx.HTTPStatusError):
        return error.response.status_code == 429 or 500 <= error.response.status_code < 600
    return False

@retry(
    retry=retry_if_exception(is_transient_error),
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=2, max=10),
    reraise=True,
)
def call_stock_api(ticker: str) -> dict:
    """Fetch stock data with automatic retry on transient failures.

    Mechanism 1 of the four above: exponential backoff for rate limits
    and network blips.
    This only retries transient transport failures. If attempts are exhausted,
    Tenacity re-raises the original httpx exception.
    """
    response = httpx.get(
        f"https://api.example.com/v1/quotes/{ticker}",
        timeout=10.0,
    )
    response.raise_for_status()
    return response.json()

L’appelant ou le harness doit encore effectuer l’étape suivante : transformer cette exception en un résultat stable indiquant quelle opération a échoué, s’il faut réessayer et quelle action entreprendre ensuite. Un 4xx non réessayable contourne ce decorator et nécessite le même traitement. Réessayer une requête ne suffit ni à classifier son erreur ni à récupérer un checkpoint.


Application des patterns au Market Analyst Agent

Le Market Analyst Agent de la partie 1 rend l’effet de l’interface visible.

Consolidation des outils

Les modules d’outils d’origine définissaient get_stock_price, get_company_metrics, get_price_history, deux outils de recherche et execute_trade. Pour une analyse de base, l’agent devait choisir à la fois l’appel de prix et celui des métriques ; la capitalisation et le P/E étaient des champs de get_company_metrics, et non des outils autonomes. Le code source avant consolidation montre cette surface antérieure.

J’ai remodelé la surface de données de marché en 5 outils de haut niveau, conformément au principe ACI d’actions compactes et efficaces. La liste d’outils ReAct du dépôt en inclut quatre autres — un chargeur de skill, deux wrappers CLI et un évaluateur Python restreint en processus (une allowlist AST, pas un sandbox ; la partie 4 traite ce point) — couvrant trois des cinq modalités ci-dessus. MCP apparaît comme sidecar plutôt que comme un outil de cette liste :

Avant (outils d’origine)Après (outils de données de marché)Pourquoi
get_stock_price + get_company_metricsget_stock_snapshotUn appel renvoie le prix de base et la snapshot de valorisation
get_price_historyget_price_historyConservé avec des périodes validées et un résumé du volume moyen
search_newssearch_newsRenvoie des éléments structurés avec les points clés extraits
search_competitorssearch_competitorsConserve l’action de recherche centrée sur les concurrents
Aucun outil d’états financiersget_financialsSélectionne les données de compte de résultat, de bilan ou de flux de trésorerie via un paramètre

Cette modification regroupe le prix et la valorisation dans une définition adaptée à la tâche et ajoute les états financiers comme action explicite. L’amélioration de la sélection des outils doit être vérifiée sur des requêtes et des traces représentatives.

Sorties structurées pour les résultats d’outils

Les outils d’actions et d’actualités renvoient des réponses validées par Pydantic. Les wrappers CLI et d’exécution de code renvoient str ; les modèles ci-dessous décrivent donc les résultats structurés des outils, et non chaque wrapper du dépôt :

from pydantic import BaseModel

class StockSnapshot(BaseModel):
    """Structured tool response — the agent never sees raw API noise."""
    ticker: str
    price: float
    change_pct: float
    volume: int
    market_cap_b: float
    pe_ratio: float | None
    summary: str  # Human-readable one-liner for direct use in reports

class NewsItem(BaseModel):
    """One news item pre-processed for agent consumption."""
    headline: str
    source: str
    date: str
    relevance_score: float  # Pre-ranked so the agent doesn't waste tokens sorting
    key_points: list[str]  # Extracted by the tool, not the agent

class NewsSearchResult(BaseModel):
    query: str
    results: list[NewsItem]
    summary: str

Le champ summary fournit à l’agent une chaîne directement utilisable dans un rapport. NewsItem.key_points évitent au modèle d’avoir à analyser le corps des articles. Si une action ultérieure a besoin d’un ID, conservez-le dans la réponse détaillée ou proposez des modes concis et détaillé ; ne le supprimez pas partout.


Compromis et considérations

Au-delà des réserves propres à chaque pattern ci-dessus, quelques considérations transversales influencent le choix :

  • Le coût opérationnel varie selon la dimension considérée. L’exécution de code économise des tokens, mais ajoute la latence de cold start du sandbox. MCP réduit le temps de développement des intégrations SaaS, mais ajoute l’overhead de déploiement du serveur. La CLI est gratuite à démarrer, mais plus difficile à gouverner à grande échelle. Optimisez en fonction de votre véritable goulot d’étranglement : coût en tokens, latence ou complexité opérationnelle.

  • Les compétences de l’équipe comptent. L’exécution de code suppose que vos agents — et les modèles qui les sous-tendent — puissent générer du Python ou du TypeScript fiable. La CLI suppose une familiarité avec les conventions Unix. MCP nécessite de comprendre les protocoles de transport et les flux OAuth. Adaptez la modalité aux points forts de votre équipe.

  • La consolidation des outils peut aller trop loin. Si un outil accumule des modes et des arguments sans rapport, l’agent se retrouve face à un autre problème de sélection, cette fois à l’intérieur du schéma. Utilisez des évaluations de tool selection et de réussite des tâches pour trouver la surface adaptée à votre charge.

  • Les Skills sont fondées sur des prompts, et non enforceées. Une skill contient des instructions que l’agent devrait suivre, et non des guardrails qu’il doit suivre. Un bundle de skills peut inclure des fichiers arbitraires et des scripts exécutables : faites donc confiance à sa source, examinez le bundle et laissez le host appliquer les permissions pour chaque ressource qu’il peut lire, modifier ou exécuter. Pour les workflows critiques, combinez les Skills avec une validation déterministe.

  • Les exigences d’audit influencent le choix. Les appels MCP et JSON structurés sont des événements pratiques à journaliser, mais aucun des deux protocoles ne crée par défaut une piste d’audit complète. Le host, le serveur ou le harness doit enregistrer les invocations et les résultats, puis appliquer l’autorisation, la policy, la rétention et la revue. L’exécution de code nécessite la même instrumentation autour du sandbox ; son script et sa sortie ne constituent pas à eux seuls un enregistrement de conformité.


Trois directions pour le tooling des AI agents à grande échelle

La première est le tool RAG pour le passage à l’échelle. Avant que le modèle ne choisisse un outil, récupérez les quelques descriptions d’outils correspondant à la requête et laissez-le choisir dans ce sous-ensemble plutôt que dans le registre complet. Dans les tâches de benchmark et le stress test MCP de RAG-MCP, la précision de sélection des outils de référence était de 13,62 % ; la retrieval l’a portée à 43,13 %, soit une amélioration de 3,2×, tout en réduisant les tokens de prompt de 2 133,84 à 1 084 (environ 49,2 %). Le résumé de l’article parle de « plus de 50 % », et les descriptions du générateur et de l’évaluateur diffèrent selon les sections ; ces incohérences limitent l’interprétation. Le résultat constitue un élément en faveur de cette configuration d’évaluation, et non un taux universel de sélection naïve lorsque les toolsets grandissent.

La deuxième direction concerne les agents qui créent leurs propres outils. Le framework LATM (« LLMs As Tool Makers ») a établi un paradigme en deux phases dans lequel un LLM puissant crée des fonctions Python réutilisables et un LLM léger les utilise. Sur le benchmark de ToolMaker, composé de 15 tâches portant sur des articles disposant de dépôts de code publics, fournis sous forme d’URL GitHub et de courtes descriptions de tâches, il a correctement implémenté 12 tâches sur 15 ; le benchmark contient au total plus de 100 tests. Ce petit benchmark de tâches sur des dépôts ne démontre pas une fiabilité de production. Les deux approches dépassent le simple tool use pour aller vers la création d’outils, puis vers la gestion d’une bibliothèque d’outils générés.

La troisième est une stack à double protocole A2A + MCP. Google a transféré A2A à la Linux Foundation en juin 2025. La documentation du protocole A2A distingue leurs responsabilités : MCP connecte un agent à des outils et à des ressources, tandis que A2A permet à des agents indépendants de se découvrir, de négocier des interactions, de gérer des tâches partagées et de déléguer du travail.


Comparez les interfaces sur des tâches et des opérations autorisées identiques. Enregistrez les tokens de découverte, les entrées avec et sans cache, la sortie d’exécution, les retries, la latence et la réussite de l’état final. Testez aussi les échecs de découverte, et pas seulement les économies de tokens ; pour les programmes générés, comptez les erreurs de syntaxe, les erreurs d’exécution et les exécutions partielles.

Points clés à retenir

  1. Choisissez la surface d’exécution en fonction de l’action : appels JSON pour les petites opérations typées, MCP pour les services partagés, CLI pour les commandes établies et code dans un sandbox pour la composition locale. Utilisez les Skills pour documenter le choix et l’utilisation de cette surface.
  2. Conservez les conditions du benchmark avec le résultat. CodeAct, Anthropic, Vercel, Cloudflare, Apideck et Scalekit ont mesuré des modèles, tâches, outils et harnesses différents.
  3. La qualité de l’ACI reste importante malgré les changements de protocole. Des actions claires, des retours compacts, une validation et des erreurs utiles bénéficient à toutes les modalités.
  4. Ne consolidez les outils qui se recouvrent que lorsque les évaluations montrent que la surface réduite améliore la sélection ou la réussite des tâches.
  5. La sécurité évolue avec la puissance d’exécution. Les interfaces shell et code nécessitent un sandbox ; MCP nécessite une identité limitée et une policy serveur ; les Skills restent des instructions et non un mécanisme d’enforcement.

La couche suivante est la policy

La partie 4, AI Agent Security, couvre le contrôle du harness entre un tool call proposé et son exécution. La partie 5 place l’outil et son sandbox dans un runtime récupérable. La partie 6 ajoute un contrat que le modèle ne voit pas : une catégorie d’effet, une règle de retry et un résultat structuré qu’un contrôle d’acceptation peut lire sans analyser de prose.


Références

Articles

Ingénierie Anthropic

Spécifications de protocoles

Études de cas industrielles

Sécurité

Conception de CLI

Projet de démonstration


Le code complet du Market Analyst Agent, y compris les conceptions d’outils décrites dans cet article, est disponible sur GitHub.