Générer des outils d’agent à partir d’OpenAPI, sans dérive de schéma
La plupart des agents reposent sur un fichier pénible à maintenir : des dizaines de définitions d’outils JSON écrites à la main, qui dupliquent des endpoints déjà décrits ailleurs. Quand l’API évolue, la spécification et la documentation sont mises à jour, mais l’agent continue d’envoyer une ancienne charge utile jusqu’aux premiers 400.
Essayez Apidog dès aujourd’hui
Votre document OpenAPI est déjà une description lisible par machine de chaque endpoint. Utilisez-le comme source unique de vérité pour générer les outils appelables par le modèle, puis synchronisez-les automatiquement. Pour le contexte plus large, consultez faut-il encore un outil API quand les agents écrivent le code ?.
Apidog est utile ici : si la spécification est incomplète ou ambiguë, les outils générés le seront aussi.
Pourquoi arrêter les définitions écrites à la main ?
Les outils manuels deviennent fragiles dès que l’API dépasse quelques endpoints :
- Dérive de schéma : l’équipe API maintient la spécification ; l’équipe agent maintient un autre fichier. Rien ne garantit leur cohérence.
- Descriptions insuffisantes : les modèles sélectionnent les outils à partir de leurs descriptions. Des descriptions réduites à une ligne dégradent directement la sélection. Voir la conception de schémas d’outils API pour les agents.
-
Erreurs détectées trop tard : déclarer une chaîne là où l’API attend un entier produit un
422au premier appel réel.
La génération depuis OpenAPI résout ces problèmes : une seule source de vérité, des descriptions issues de la documentation, et des types alignés sur la validation serveur.
Mapper une opération OpenAPI vers un outil
Prenons cette opération :
paths:
/orders/{orderId}/refund:
post:
operationId: refundOrder
summary: Rembourser une commande
description: >
Émet un remboursement complet ou partiel pour une commande complétée.
Les remboursements sont irréversibles. Les remboursements partiels nécessitent un montant
pas supérieur au solde remboursable restant.
parameters:
- name: orderId
in: path
required: true
schema: { type: string }
description: La commande à rembourser.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [reason]
properties:
amount:
type: integer
description: Montant en centimes. Omettre pour un remboursement complet.
reason:
type: string
enum: [duplicate, fraudulent, requested_by_customer]
Elle devient l’outil suivant :
{
"name": "refundOrder",
"description": "Émet un remboursement complet ou partiel pour une commande complétée. Les remboursements sont irréversibles. Les remboursements partiels nécessitent un montant pas supérieur au solde remboursable restant.",
"input_schema": {
"type": "object",
"required": ["orderId", "reason"],
"properties": {
"orderId": {
"type": "string",
"description": "La commande à rembourser."
},
"amount": {
"type": "integer",
"description": "Montant en centimes. Omettre pour un remboursement complet."
},
"reason": {
"type": "string",
"enum": ["duplicate", "fraudulent", "requested_by_customer"]
}
}
}
}
Appliquez ces quatre règles :
- Transformez
operationIden nom d’outil. S’il manque, générez un identifiant stable depuis la méthode HTTP et le chemin, puis ajoutez-le à la spécification. - Aplatissez les paramètres de chemin, de requête et de corps dans un seul objet
properties. Conservez toutefois une table annexe indiquant leur emplacement réel. - Concaténez
summaryetdescriptionpour former la description de l’outil. - Fusionnez tous les tableaux
required.
L’exécuteur reste minimal :
def execute(tool_name, args, spec_index, http):
op = spec_index[tool_name] # method, path template, param locations
path = op.path
query, body = {}, {}
for name, value in args.items():
location = op.locations[name] # "path" | "query" | "header" | "body"
if location == "path":
path = path.replace("{" + name + "}", str(value))
elif location == "query":
query[name] = value
elif location == "body":
body[name] = value
return http.request(op.method, path, params=query, json=body or None)
Normaliser les schémas avant génération
Un transfert brut d’OpenAPI vers un schéma d’outil ne suffit pas. Le générateur doit effectuer cinq transformations.
1. Résoudre les $ref
Les API d’outils ne suivent pas toujours les références vers components. Intégrez les schémas référencés directement.
Attention aux schémas récursifs : limitez leur profondeur et décrivez le niveau suivant en prose plutôt que de développer la structure indéfiniment.
2. Réduire les mots-clés mal pris en charge
Les mots-clés oneOf, allOf, discriminator et nullable sont fréquents dans OpenAPI mais souvent mal supportés par les outils.
- Fusionnez les propriétés pour réduire
allOf. - Pour
oneOf, choisissez la variante dominante ou créez un outil par variante. - Préférez plusieurs outils explicites lorsqu’ils améliorent la sélection.
3. Éviter les entrées trop imbriquées
Un modèle remplit moins fiablement un objet profond comme customer.address.postal_code. Exposez plutôt une interface d’outil plus plate, puis reconstruisez la charge utile attendue dans l’exécuteur.
4. Exclure les schémas de réponse
Une définition d’outil décrit ses entrées. N’y ajoutez pas le schéma de réponse complet : cela consomme du contexte inutilement. La gestion des résultats mérite une stratégie séparée, détaillée dans cet article sur le maintien des réponses API dans la fenêtre de contexte de l’agent.
5. Conserver les contraintes de sécurité
Marquez les opérations d’écriture pour les envoyer vers une étape d’approbation. Si votre spécification utilise une extension comme x-agent-requires-approval, votre générateur et votre exécuteur doivent la respecter.
Associez cette approche à des garde-fous pour agents IA.
Ne fournissez pas 200 outils au modèle
Le problème principal n’est généralement pas la conversion : c’est le volume. Une liste exhaustive remplit la fenêtre de contexte et pousse le modèle à choisir entre des opérations presque identiques.
Réduisez l’ensemble d’outils, dans cet ordre :
Filtrez par tags OpenAPI.
Un agent de remboursement a besoin deordersetpayments, pas deadminouanalytics.Maintenez une liste blanche d’
operationId.
Générez uniquement les opérations que l’agent est autorisé à appeler. C’est aussi une barrière de sécurité : un endpoint sans outil ne peut pas être appelé par erreur. Voir comment empêcher les agents IA de détruire vos API.Récupérez les outils à la demande.
Pour les très grandes API, indexez les opérations et injectez seulement les plus pertinentes à chaque tour. Cette approche ajoute toutefois une couche de récupération à tester.
Le Model Context Protocol propose aussi une voie standardisée pour exposer les outils d’un serveur aux clients. Consultez ce qu’est le MCP et comment construire un serveur MCP avec Apidog.
Corriger la spécification avant de générer
La génération déplace la qualité en amont. Une description vague dans OpenAPI devient une description vague pour le modèle ; un champ incorrectement optionnel devient un appel qui échoue à l’exécution.
Auditez votre spécification avec cette checklist :
- Chaque opération possède un
operationIdlisible, idéalement sous la forme verbe + nom. - Chaque description explique ce que l’opération fait, ce qu’elle modifie et quand ne pas l’utiliser.
- Chaque paramètre précise ses unités et son format.
- Les valeurs possibles sont déclarées avec des
enum, pas seulement décrites en prose. - Les champs
requiredreflètent exactement les contraintes du serveur.
Par exemple, préférez :
Supprime définitivement un utilisateur et toutes ses sessions. Ne peut pas être annulé. Utilisez
desactivateUserpour désactiver temporairement l’accès.
à :
Supprime un utilisateur.
Dans Apidog, la spécification, la documentation, les maquettes et les tests proviennent d’un même projet. Améliorer une description améliore donc tous ces éléments. Pour maintenir cette cohérence dans le temps, consultez la gestion du versionnement d’API dans Apidog.
Partagez la configuration d’outils
Un ensemble d’outils généré est une configuration : filtres, liste blanche et version de spécification épinglée doivent être versionnés et partagés avec la spécification.
Certaines plateformes en font une unité de travail réutilisable. Dans Sharkly, un Agent regroupe ses instructions, son Runtime, ses Skills, ses dépôts et ses paramètres d’exécution. Une configuration d’outils validée peut ainsi être partagée dans un espace au lieu d’être recréée localement par chaque personne. Le runtime reste Claude Code, Codex ou celui que vous utilisez déjà ; seule la configuration cesse d’être individuelle.
Tester les outils générés
Testez à la fois la génération et le comportement des appels.
Vérifier l’aller-retour du schéma
Pour chaque outil généré :
- Construisez un exemple valide à partir de son schéma.
- Envoyez-le à l’endpoint correspondant.
- Traitez chaque
400ou422comme un désaccord entre l’outil, la spécification et le serveur.
La correction doit normalement être apportée à la spécification.
Tester la sélection d’outil
Créez un petit corpus d’invites pour lesquelles vous connaissez l’outil attendu. Exécutez l’agent et enregistrez l’outil choisi.
Cette suite de régression détecte les renommages et les descriptions raccourcies. Comme la sortie est non déterministe, vérifiez surtout le nom de l’outil, pas les arguments exacts. Voir le test des agents IA non déterministes.
Tester contre des maquettes
Avant la production, exécutez l’agent contre un serveur de maquette généré à partir de la même spécification. Vous obtenez des réponses réalistes sans effet de bord et pouvez injecter des 500 ou des délais d’attente pour valider les reprises.
Conclusion
La spécification OpenAPI est le contrat ; la liste d’outils doit en être une projection, jamais une copie maintenue à la main.
Générez les outils, filtrez-les strictement, rendez leurs descriptions précises et testez autant la forme des appels que la sélection du bon outil.
Commencez par exporter votre document OpenAPI et comptez les opérations sans description. Ce nombre représente le travail restant avant d’obtenir des outils d’agent fiables. Vous pouvez télécharger Apidog pour centraliser spécification, maquettes et tests.
Foire aux questions
Puis-je générer des outils depuis Swagger 2.0 ?
Oui, mais convertissez d’abord le document vers OpenAPI 3.x. Le modèle de corps de Swagger 2.0 diffère suffisamment pour produire des générateurs incohérents. Les outils actuels ciblent OpenAPI 3.x. Consultez le dépôt de la spécification OpenAPI.
Combien d’outils un modèle peut-il gérer à la fois ?
La précision diminue bien avant la limite technique. En pratique, quelques dizaines d’outils constituent déjà un signal pour filtrer par tags ou organiser une liste blanche.
Les noms d’outils doivent-ils correspondre exactement aux operationId ?
Oui, si l’operationId est lisible. Cela permet de relier directement un appel d’outil à son opération OpenAPI et simplifie le traçage comme le débogage. Corrigez les mauvais noms dans la spécification, pas dans le générateur.
Et pour GraphQL ?
Le principe reste le même : introspectez le schéma et générez un outil par requête ou mutation. La surface exposée par GraphQL est souvent plus large, donc le filtrage est encore plus important.
Dois-je encore écrire des outils à la main ?
Oui, pour les outils composites qui enchaînent plusieurs appels, ou pour les outils qui n’encapsulent pas HTTP. Les wrappers routiniers d’un endpoint unique, eux, ne devraient plus être manuels.
Comment empêcher les appels d’écriture pendant les tests ?
Générez un ensemble d’outils en lecture seule en filtrant par méthode HTTP, et redirigez les opérations d’écriture vers une maquette. Consultez pourquoi les agents devraient utiliser des maquettes, pas la production.


Top comments (0)