Tool Calling
Laissez le modèle demander des appels d’outils que l’application exécute en toute sécurité avant de retourner les résultats.
Tool Calling permet au modèle de choisir un ou plusieurs outils selon la conversation et de produire leurs paramètres structurés. Le modèle n’accède pas lui-même aux bases de données, aux services internes ni aux opérations d’écriture : l’exécution reste toujours à la charge de votre programme.
Il convient à la consultation de commandes, à la météo, à la recherche dans une base de connaissances, aux calculs et aux opérations métier précises exécutées après autorisation.
N’exécutez pas directement les paramètres générés
Les noms et paramètres d’outils sont des sorties du modèle. Avant l’exécution, analysez le JSON, validez le Schema, vérifiez les autorisations et la liste d’actions métier autorisées. Pour les paiements, suppressions ou envois de messages, demandez aussi une confirmation et utilisez des contrôles d’idempotence.
Cycle d’appel complet
1. Définir les outils
Utilisez des noms clairs, des descriptions et un JSON Schema pour indiquer au modèle quand appeler chaque outil et comment structurer les paramètres.
2. Interroger le modèle
Envoyez l’entrée utilisateur avec les définitions d’outils. Le modèle peut répondre directement ou retourner zéro, un ou plusieurs appels.
3. Valider et exécuter
Retrouvez l’implémentation locale par nom, validez tous les paramètres et les autorisations, puis exécutez avec un délai maximal. Ne laissez pas le modèle choisir librement une fonction, une URL, du SQL ou une commande Shell.
4. Retourner les résultats
Associez le résultat à l’appel d’origine avec l’identifiant retourné par le protocole, puis interrogez de nouveau le modèle.
5. Lire la réponse finale
Le modèle peut répondre à partir des résultats ou demander d’autres appels. Définissez un nombre maximal d’itérations et identifiez les conditions d’arrêt.
Définir un outil en lecture seule
L’outil suivant consulte uniquement la météo, sans écriture externe :
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Consulter la météo actuelle de la ville indiquée",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Nom de la ville, par exemple Shanghai"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["city", "unit"],
"additionalProperties": false
}
}
}La description doit préciser ce que fait l’outil et quand l’utiliser. Gardez des noms de paramètres stables, limitez les valeurs d’énumération et utilisez required et additionalProperties pour restreindre les entrées superflues.
Effectuer un cycle d’outils avec Chat
Voici le parcours complet : déclarer l’outil, lire l’appel, exécuter la fonction locale, retourner le résultat et lire la réponse finale :
import json
from openai import OpenAI
client = OpenAI(
api_key="your-api-key",
base_url="https://api.agtcloud.cn/v1",
)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Consulter la météo actuelle de la ville indiquée",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
},
},
"required": ["city", "unit"],
"additionalProperties": False,
},
},
}
]
def get_weather(city: str, unit: str) -> dict[str, str | int]:
if city != "Shanghai" or unit != "celsius":
raise ValueError("Cet exemple accepte uniquement la température de Shanghai en degrés Celsius")
return {"city": city, "unit": unit, "temperature": 25}
messages = [{"role": "user", "content": "Quelle est la température actuelle à Shanghai ?"}]
response = client.chat.completions.create(
model="MODEL_ID",
messages=messages,
tools=tools,
tool_choice="auto",
)
assistant_message = response.choices[0].message
messages.append(assistant_message)
for tool_call in assistant_message.tool_calls or []:
if tool_call.function.name != "get_weather":
raise ValueError("Le modèle a demandé un outil non enregistré")
arguments = json.loads(tool_call.function.arguments)
result = get_weather(**arguments)
messages.append(
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False),
}
)
if assistant_message.tool_calls:
final_response = client.chat.completions.create(
model="MODEL_ID",
messages=messages,
tools=tools,
)
print(final_response.choices[0].message.content)
else:
print(assistant_message.content)En production, validez arguments avec une bibliothèque JSON Schema et définissez des autorisations, des délais, des types d’erreur et des journaux d’audit propres à chaque outil.
Représentation des appels d’outils selon le protocole
| Protocole | Définition | Appel par le modèle | Retour du résultat |
|---|---|---|---|
| Chat Completions | tools[].function | tool_calls dans l’Assistant Message | role: tool et tool_call_id |
| Responses | Function Tool dans tools | Output Item function_call | function_call_output et call_id |
| Anthropic Messages | tools et input_schema | Content Block tool_use | Content Block tool_result |
| Gemini | functionDeclarations | functionCall dans une Part | functionResponse dans une Part |
Ne mélangez pas les noms de champs ni les structures imbriquées. Consultez les références Chat Completions, Responses, Anthropic Messages et Gemini Generate Content.
Appels multiples et streaming
- Ne supposez pas qu’un seul outil est appelé ; validez, exécutez et retournez chaque résultat par identifiant d’appel.
- Seuls les appels indépendants en lecture seule et autorisés par les règles métier se prêtent à une exécution parallèle.
- Les paramètres en streaming peuvent être fragmentés ; assemblez-les complètement avant d’analyser le JSON.
- Après le retour des résultats, le modèle peut demander une autre série d’appels ; imposez un nombre maximal d’itérations et un délai total.
- Utilisez une clé d’idempotence métier pour réessayer une écriture sans répéter un débit, un envoi ou une création de ressource.
Gestion des échecs
Si un outil échoue, ne simulez pas une réussite. Retournez une catégorie d’erreur expurgée, comme des paramètres invalides, des droits insuffisants ou un service amont indisponible, afin que le modèle explique le problème ou choisisse une solution autorisée.
Ne transmettez pas directement au modèle ni à l’utilisateur les traces internes, structures de bases de données, jetons d’accès, adresses privées ou réponses tierces non expurgées.
Vérifications avant la mise en production
- Les outils sont sélectionnés uniquement dans un registre ou une liste autorisée.
- Les paramètres sont validés selon le Schema et les règles métier avant exécution.
- Chaque outil dispose d’autorisations, d’un délai, d’une taille maximale de résultat et d’une gestion des erreurs.
- Les écritures à haut risque nécessitent une confirmation et prennent en charge l’idempotence et l’audit.
- Le cycle d’appels possède une limite d’itérations et ne peut pas continuer indéfiniment.
- Les appels d’outils en streaming ne sont exécutés qu’une fois leurs paramètres complets.
Pour assembler les paramètres d’outils à mesure qu’ils arrivent, consultez Streaming. Pour imposer un JSON Schema à la réponse finale, consultez Structured Output.