Le Function Calling (appel d’outils) est le protocole Agent par défaut en 2026 : les modèles ne font plus semblant d’appeler des API en prose. Ils émettent du JSON sous un schéma convenu, et votre code interroge la météo, une base, édite des fichiers ou lance des tests. La différence n’est pas qui discute mieux, mais si le schéma est validé, l’exécution auditée et les effets de bord isolés.
Mis à jour le 18 août 2026. Les noms de champs des SDK bougent ; la boucle non : requête → exécution → réinjection. Un outil qui mute le disque va avec un sandbox de système de fichiers agent. Les préférences inter-sessions vont dans la couche Memory, pas dans le prochain blob arguments.
Pourquoi le prompt en texte libre ne suffit pas (Why)
L’ancienne recette : « appelle get_weather(city=Beijing) » plus une regex. Les démos passent ; la prod casse en trois points :
- Parsing instable — politesse, arguments réordonnés, quotes manquantes ;
JSON.parseexplose. - Pas de types — les enums deviennent du libre ; les champs requis disparaissent ; les appels parallèles ne se corrélent pas.
- Effets de bord mêlés au chat — le modèle affirme une suppression jamais exécutée, ou vous avez exécuté sans lui renvoyer le résultat.
Le Function Calling laisse le choix au modèle et l’exécution au runtime. HTTP, SQL et shell n’arrivent jamais dans le processus du modèle. Comme la CI : un job, un workspace — frontière avant intelligence.
Trois couches (What)
Brancher « OpenAI tools » n’est pas une architecture. Coupez au moins trois couches :
| Couche | Rôle | Support | Propriétaire |
|---|---|---|---|
| L1 Schema | Noms, JSON Schema, descriptions, requis | OpenAI tools[].function, Gemini functionDeclarations, Claude input_schema | Produit |
| L2 Runtime | Valider, secrets, timeout, retry, audit | Boucle maison, LangGraph, Claude Code | Backend / agent local |
| L3 Transport | Découverte et connexion des processus outils | HTTP, MCP stdio/SSE, RPC interne | Infra |
Conclusion asymétrique : les API vendeurs standardisent l’enveloppe JSON L1. Elles ne finissent ni l’autorisation L2 ni l’isolation processus L3. MCP, c’est découverte et session — pas la sécurité automatique.
La boucle : le modèle ne détient pas vos clés ; les secrets restent dans le runtime.
┌──────────────┐ JSON tool request ┌──────────────────┐
│ LLM API │ ────────────────────────► │ Your runtime │
│ (OpenAI / │ name + arguments │ (Agent loop) │
│ Gemini / │ │ │
│ Claude) │ ◄──────────────────────── │ execute tool │
└──────────────┘ tool result JSON │ • HTTP APIs │
│ • DB / search │
│ • shell / MCP │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Policy + secrets │
│ allowlist, audit │
│ Cloud Mac / VPC │
└──────────────────┘Comparaison : OpenAI vs Gemini vs Claude
| Surface | Entrée | Exécution | Contexte | Pour qui |
|---|---|---|---|---|
| OpenAI tools | Chat Completions / Responses | Vous exécutez ; arguments souvent une chaîne JSON | tool_calls[] parallèles ; strict optionnel | SDK OpenAI ou passerelles compatibles |
| Gemini functionDeclarations | Gemini API / Vertex | Vous exécutez ; toolConfig.mode force ou interdit | Types souvent OBJECT/STRING en majuscules | GCP ; produits qui ont besoin d’un mode |
| Claude tool_use | Messages API / Claude Code | Vous exécutez ; input est déjà un objet | Blocs : tool_use / tool_result | Anthropic, agents IDE, MCP |
| Outils MCP | Client ↔ serveur MCP | Dans le processus serveur ; le modèle n’émet que du JSON | Catalogue découvert à l’exécution | Hot-plug de catalogues |
En 2026, la ligne n’est pas « est-ce supporté » (les trois le font) mais chaîne vs objet, alignement parallèle, réécriture des erreurs. Les passerelles normalisent vers ToolCall{name, id, args} et un seul runtime L2.
À quoi ressemble le JSON (How)
Le même get_weather. En prod, les descriptions posent des bornes (« météo publique seulement, jamais la position personnelle »).
OpenAI : tools + tool_calls
Attachez les outils à la requête. En cas d’appel, le message assistant contient tool_calls. arguments est du JSON stringifié — parser, puis valider.
{
"model": "gpt-4.1",
"messages": [{"role": "user", "content": "What's the weather in Beijing?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
}]
}{
"role": "assistant",
"tool_calls": [{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Beijing\",\"unit\":\"celsius\"}"
}
}]
}Ensuite un message role: tool (ou équivalent Responses) avec tool_call_id et content chaîne.
Gemini : functionDeclarations + toolConfig
Déclarations sous tools[].functionDeclarations. mode : AUTO, ANY, NONE — interrupteur produit, pas un sandbox.
{
"contents": [{"role": "user", "parts": [{"text": "What's the weather in Beijing?"}]}],
"tools": [{
"functionDeclarations": [{
"name": "get_weather",
"description": "Current weather for a city",
"parameters": {
"type": "OBJECT",
"properties": {
"city": {"type": "STRING"},
"unit": {"type": "STRING", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}]
}],
"toolConfig": {"functionCallingConfig": {"mode": "AUTO"}}
}Le modèle renvoie un part functionCall ; vous répondez functionResponse. Ne supposez pas les mêmes noms de champs qu’OpenAI.
Claude : tools + tool_use / tool_result
input_schema. La réponse est un tableau de blocs. input est un objet ; validez quand même.
{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"tools": [{
"name": "get_weather",
"description": "Current weather for a city",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}],
"messages": [{"role": "user", "content": "What's the weather in Beijing?"}]
}{
"role": "assistant",
"content": [{
"type": "tool_use",
"id": "toolu_01XYZ",
"name": "get_weather",
"input": {"city": "Beijing", "unit": "celsius"}
}]
}{
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": "toolu_01XYZ",
"content": "{\"temp_c\": 28, \"condition\": \"clear\"}"
}]
}Claude Code et Cursor ajoutent MCP. Le modèle voit toujours un catalogue JSON Schema. Le transport change, pas la boucle.
Matrice de choix
| Si vous… | Choisissez | Pourquoi |
|---|---|---|
| avez déjà une passerelle compatible OpenAI | dialecte OpenAI tools | plus grand écosystème ; adapters une fois |
| êtes surtout GCP / Vertex | Gemini + mode | moins de traduction ; « ce tour doit rechercher » |
| partez de Claude Code | Claude tools + MCP | aligné sur le catalogue IDE |
| routez trois vendeurs de modèles | ToolCall interne + adapters | pas d’if-else vendeur dans le métier |
| éditez des fichiers ou lancez des commandes | Mac distant + allowlist de chemins | un JSON joli n’arrête pas un rm faux |
| n’avez que des API SaaS en lecture | serverless + gestionnaire de secrets | pas de machine entière ; allowlist des paramètres quand même |
Stacks recommandés
A — solo, une demi-journée : un modèle, 1–3 outils lecture, JSON Schema sans additionalProperties, secrets en env, logs en hash.
B — petite équipe : ToolCall interne, timeouts et plafonds par outil, écritures sur sessions Cloud Mac, Memory à part. Même discipline de destruction que l’automatisation Mac distante.
C — entreprise : revue du catalogue, schéma en PR, MCP en VPC, pas de bash sans politique de chemins.
Pièges
- Croire que le modèle authentifie — les clés sont dans le runtime.
- Traiter
argumentsOpenAI comme un objet — parser d’abord. - Descriptions « fais tout » — sur-appels.
- Ignorer les tool_calls parallèles — sérialiser les écritures.
- Avaler les échecs — renvoyer des erreurs structurées.
- MCP = sécurité — un root home, c’est tout le disque.
Déploiement en 7 étapes
- Inventaire (effet de bord, timeout, résidence).
- JSON Schema (requis, enum, pas d’additionalProperties).
- Boucle minimale, un outil.
- Validation, isolation des secrets, audit.
- Deuxième adapter vendeur pour prouver le modèle interne.
- Sandbox des outils d’écriture.
- Observer 7 jours, resserrer les schémas qui se trompent.
FAQ
Différence avec le JSON mode ?
Le JSON mode contraint la forme de la réponse finale. Le Function Calling contraint les requêtes d’outils intermédiaires et s’étend souvent sur plusieurs tours après exécution.
Le modèle interroge-t-il ma base directement ?
Non, sauf si le runtime expose du SQL arbitraire sans autorisation. Par défaut il ne propose que des paramètres valides.
Un schéma pour trois vendeurs ?
Oui pour le JSON Schema cœur, puis enveloppes. Testez enums et champs requis ; le strict n’est pas identique.
Les outils Claude Code sont-ils du Function Calling ?
Même boucle ; le catalogue vient dynamiquement de l’IDE/MCP plutôt d’un tableau tools écrit à la main.
Mettre les résultats d’outils en mémoire long terme ?
Les payloads bruts sont gros et éphémères. Résumez vers Memory. Voir le centre d’aide.
Conclusion
Le Function Calling 2026 est un RPC typé par schéma. Trois dialectes JSON, une grammaire. La sécurité est dans L2 et les hôtes isolés. Si vous ne savez pas où atterrit un write_file maintenant, n’attachez pas d’outils d’écriture. Les API lecture peuvent partir aujourd’hui ; code et tests sur un nœud Cloud Mac jetable — consultez les tarifs.