DEV Community

Cover image for OpenAPI pour Outils d'Agents IA : Plus de Wrappers Manuels
Antoine Laurent
Antoine Laurent

Posted on Originally published at apidog.com

OpenAPI pour Outils d'Agents IA : Plus de Wrappers Manuels

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.

Génération d’outils d’agent depuis OpenAPI

Workflow OpenAPI et agents

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 422 au 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]
Enter fullscreen mode Exit fullscreen mode

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"]
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Appliquez ces quatre règles :

  1. Transformez operationId en 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.
  2. 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.
  3. Concaténez summary et description pour former la description de l’outil.
  4. 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)
Enter fullscreen mode Exit fullscreen mode

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 :

  1. Filtrez par tags OpenAPI.

    Un agent de remboursement a besoin de orders et payments, pas de admin ou analytics.

  2. 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.

  3. 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 operationId lisible, 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 required reflè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 desactivateUser pour 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é :

  1. Construisez un exemple valide à partir de son schéma.
  2. Envoyez-le à l’endpoint correspondant.
  3. Traitez chaque 400 ou 422 comme 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)