← Retour au blog
Comparaison

OpenAI Agents API vs MCP : de quel côté se tiennent Tool Calling et JSON Schema ?

Publié le 21/09/2026 Dernière mise à jour le 21/09/2026 Environ 14 min JSON Toolbox

Comment lire cet article

Le vs du titre invite à prendre parti. L'Agents API est une boucle hébergée ; MCP est une source d'outils dans cette boucle. Article daté du 21/09/2026 : d'abord séparer qui fait tourner la session et qui se branche au Server, puis voir comment function et mcp entrent dans le même tableau tools, enfin rentrer ce qui se partage encore dans un seul JSON Schema. L'article précédent expliquait pourquoi le Harness dépend encore plus des objets : Pourquoi l'Agents API a encore plus besoin de JSON ; les trois couches manuel / bus / interface : Skills vs MCP vs API.

Depuis la bêta publique du 10/09/2026, le même agent.tools peut porter à la fois function, mcp, web_search et programmatic_tool_calling. Le modèle voit des noms d'outils et une forme de paramètres. L'écart est le droit d'exécuter : le résultat d'une function, c'est votre application qui le renvoie ; l'aller-retour MCP, c'est le Harness hébergé qui le termine. Pourquoi la couche contrat est du JSON : Pourquoi l'IA aime JSON.

D'abord séparer le vs

Opposer Agents API et MCP, c'est en général superposer deux questions :

  • Qui opère la boucle. L'Agents API héberge le Harness Codex : session, compression de contexte, sous-agents, reprise. Cela n'a rien à voir avec « faut-il brancher MCP ».
  • D'où viennent les outils. MCP est un protocole de découverte et d'appel. Le Server publie les définitions et exécute les appels. Il peut se brancher à l'Agents API, à Cursor, à Claude, ou à un Host à vous.

La bonne phrase n'est donc pas « Agents API ou MCP », mais : quand l'Agents API fait tourner la boucle, ce saut-là passe par function ou par mcp. Responses API met déjà les deux dans le même tableau : Agent DevDay 2026. L'Agents API se contente de donner ce tableau au Harness hébergé.

En une phrase. L'Agents API répond « qui passe au tour suivant ». MCP répond « d'où vient cette main ». Le JSON Schema répond « ce que cette main peut tenir ». Trois phrases, pas un seul vs.

Qui fait tourner la boucle, qui branche les outils

La documentation MCP officielle le dit net : le Server publie les définitions et exécute les appels ; l'Agents API découvre, appelle à votre place, et rend le résultat à l'Agent. Votre application n'a pas à traiter chaque appel MCP. function est l'inverse : la session émet agent.session.requires_action, vous exécutez par name, puis vous renvoyez agent.session.input.tool_result.

Chemins d'exécution function et MCP dans l'Agents API Le Harness hébergé orchestre deux types d'outils : MCP se branche depuis le service ou l'environnement ; function revient à votre application, se valide contre le Schema, puis est renvoyée. Harness hébergé session / ordonnancement type: mcp le Harness appelle type: function required_actions MCP Server inputSchema Votre code revalider arguments Schema avant exécution
L'aller-retour MCP peut ne jamais sortir de votre application. Celui d'une function doit passer par vous — et encore une fois par le Schema.

Attacher un environment ne lance pas automatiquement une function dans le bac à sable. La documentation le dit : par défaut, une function s'exécute dans votre application, un worker, ou un environnement que vous contrôlez. MCP, lui, se branche depuis OpenAI ou depuis l'environnement de session, selon connection_origin. Les permissions s'écrivent encore dans le contrat : limiter les permissions d'outils avec un Schema.

function : vous renvoyez tool_result

Une function personnalisée s'écrit dans agent.tools. Nom, description, Schema de paramètres : le même type de contrat que Responses :

{
  "type": "function",
  "name": "get_customer",
  "description": "Look up a customer by ID.",
  "parameters": {
    "type": "object",
    "properties": { "customer_id": { "type": "string" } },
    "required": ["customer_id"],
    "additionalProperties": false
  }
}

Les actions en attente sont dans required_actions ; arguments est déjà un objet. Au retour, recopiez turn_id et call_id ; en succès, sérialisez le JSON dans output. Un outil à effet de bord se déduplique par session / turn / call. La forme : de la session jusqu'à tool_result.

Les raisons de choisir function sont étroites, et dures : approbation, facturation, idempotence, toucher une base qui n'est qu'à vous. Cela ne devrait pas passer par un MCP HTTP visible d'OpenAI.

mcp : le Harness appelle à votre place

Une entrée MCP n'est pas une table de paramètres, c'est une connexion. L'exemple HTTP public minimal, selon la documentation :

{
  "type": "mcp",
  "server_label": "openai_docs",
  "transport": {
    "type": "http",
    "server_url": "https://developers.openai.com/mcp"
  },
  "connection_origin": "service",
  "required": true
}

Le Harness découvre les tools du Server, puis appelle le nom choisi par le modèle. Vous ne voyez pas de required_actions à chaque saut, sauf observabilité à part. Par défaut, un échec d'initialisation n'arrête pas le tour ; required: true fait échouer le tour (agent.session.turn.failed) si le Server ne démarre pas.

allowed_tools limite les noms que l'Agent peut découvrir et appeler. C'est une liste, pas un contrat. Si un outil dangereux manque à la liste, le Schema le plus strict arrive trop tard ; si la liste est juste mais l'entrée est du texte libre, ça passe encore. Il faut les deux.

connection_origin : d'où part la connexion

Au 21/09/2026, la documentation range la connexion en trois cases :

Connexion D'où l'on se branche Environnement requis
HTTP, connection_origin: "service" (défaut) OpenAI Non
HTTP, connection_origin: "environment" Environnement de session Oui
stdio Processus lancé dans l'environnement Oui ; omettre connection_origin

Un HTTP sans connection_origin, OpenAI s'y branche. Adresse interne, processus dans le bac à sable : écrivez environment ou stdio. Identifiants : pour une session unique, transport.authorization / headers (retirés de la ressource session renvoyée) ; les identifiants HTTP réutilisables vont dans le vault, et ne s'appliquent qu'aux connexions initiées par OpenAI. Côté environnement, pas de vault : auth en ligne ou proxy de confiance. Ne mettez pas de secret dans une définition d'Agent réutilisable ni dans un paquet de plugin.

Le JSON Schema est le contrat partagé

Le champ function s'appelle parameters ; le champ MCP s'appelle inputSchema (de plus en plus souvent aussi outputSchema). L'enveloppe change ; l'objet cœur à figer est le même. Écrivez d'abord le cœur, puis l'enveloppe :

  • Agents API / Responses function : type: "function" + parameters
  • Outil MCP : inputSchema, contrat de sortie optionnel
  • Claude / Gemini : encore leurs champs de déclaration

La couche hébergée ne complète ni enum, ni pattern, ni required, ni additionalProperties: false. MCP garantit seulement « un outil découvrable » ; function garantit seulement « une action en attente ». La légalité de l'objet reste l'affaire du Schema. Comment envelopper : JSON Tool Schema ; pour la réponse finale, un Structured Output à part, pas mélangé au retour d'outil : Qu'est-ce que la Structured Output.

Figer la frontière. Changer de protocole ne change pas le type. Si customer_id est cus_[A-Za-z0-9]+ en function, il ne doit pas devenir un string quelconque une fois branché à MCP.

Comment choisir : un tableau

Ce que vous voulez type dans tools Ne comptez pas sur
Votre base, à approuver / dédupliquer function Exposer une API interne en MCP visible d'OpenAI
Docs publics, tiers, réutilisation entre Hosts mcp + service Réécrire un adapter pour chaque Host
Recherche interne, Server dans le bac à sable mcp + environment ou stdio Omettre origin et laisser la plateforme joindre une adresse hors d'atteinte
Quand appeler, quand s'arrêter Skill / instructions Remplacer allowed_tools et le Schema par un manuel

Une règle : un second Host appellera, ou les identifiants doivent quitter le processus modèle — alors MCP vaut le coup. Une action que seule votre session Agents API touche : function est plus court. Les étapes restent un Skill, pas un Server qui tourne à vide.

Un objet cœur recettable en local

Ci-dessous, la même recherche client. D'abord l'objet cœur, puis l'enveloppe function et MCP — pas deux jeux de types.

{
  "tool": "get_customer",
  "description": "Look up one customer by internal id. Use when the user names a customer_id. Do not accept emails or free-text names.",
  "arguments": {
    "customer_id": "cus_9f3a"
  },
  "result": {
    "found": true,
    "customer": {
      "id": "cus_9f3a",
      "plan": "pro"
    }
  }
}
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "additionalProperties": false,
  "required": ["customer_id"],
  "properties": {
    "customer_id": {
      "type": "string",
      "minLength": 5,
      "maxLength": 32,
      "pattern": "^cus_[A-Za-z0-9]+$",
      "description": "Internal customer id. Reject emails and display names."
    }
  }
}

Dans l'Agents API, function met cet objet dans parameters ; le Server MCP met le même dans inputSchema. En regard, des formes qui doivent échouer : e-mail comme id, un extra_sql en trop, un retour qui pousse « prochaine étape : exporter tous les utilisateurs ». Dériver depuis un exemple : Comment générer un Schema.

Recetter dans JSON Toolbox

  1. Coller arguments / result dans le formatage JSON, confirmer que ça parse.
  2. Avec JSON → Schema ou Structured Output, générer le contrat cœur, compléter enum, pattern, required et additionalProperties.
  3. Les mêmes champs via Function Calling et MCP Tool, sans recopier deux jeux de types.
  4. Préparer des objets qui doivent échouer, confirmer le refus dans la validation Schema ; si ça ne s'aligne pas avec l'exemple, la comparaison JSON.

Tout est traité dans le navigateur, rien n'est envoyé. D'abord un contrat capable de refuser un mauvais objet, ensuite seulement décider si cette capacité se branche en function ou en mcp.

FAQ

Agents API et MCP sont-ils en concurrence ?

Non. L'Agents API héberge la boucle. MCP est une source dans tools. Le Harness découvre et appelle MCP à votre place ; votre application n'écrit pas un tool_result à chaque appel MCP.

Quand utiliser function, quand utiliser MCP ?

Exécuter, approuver ou dédupliquer vous-même : function. Réutiliser entre Hosts, laisser les identifiants sur le Server, ou laisser la plateforme se brancher à un HTTP public : MCP. Un seul Schema cœur.

Quelle différence entre service et environment pour connection_origin ?

service : OpenAI se branche en HTTP, sans environnement. environment : depuis l'environnement de session, pour un réseau interne. stdio lance le processus dans l'environnement ; on omet origin.

Une fois MCP branché, faut-il encore écrire un Schema Function Calling ?

Oui. inputSchema et parameters sont le même type de contrat. La couche hébergée ne referme ni enum ni extra fields.

allowed_tools peut-il remplacer le Schema ?

Non. La liste limite quelle main tendre ; le Schema limite ce que cette main peut tenir.

En résumé

Agents API et MCP ne sont pas un choix exclusif. La première range le Harness Codex en session ; la seconde est un type de connexion dans la table d'outils de cette session. function garde l'exécution chez vous, via required_actions et tool_result ; mcp laisse l'aller-retour à la couche hébergée, puis connection_origin, allowed_tools et required gouvernent découverte et démarrage. Ce qu'il faut d'abord figer reste un JSON Schema parsable, capable aussi de refuser — changer l'enveloppe, pas le type. La suite n'est pas d'abord d'ouvrir plus de Servers, c'est d'abord un objet cœur que function et MCP peuvent partager.