Vérification factuelle : 22 juillet 2026. Ce guide explique le Function Calling avec l’API officielle DeepSeek V4. Les noms de modèles, les paramètres, les limites et les fonctions bêta peuvent évoluer : contrôlez la documentation officielle avant chaque mise en production.
Transparence : deepseek-fr.ai est un guide francophone indépendant. Il n’est ni exploité, ni approuvé, ni affilié à DeepSeek. L’assistant proposé sur ce site transmet vos messages à l’API DeepSeek dans le seul but de générer la réponse ; le site n’a accès à aucun échange mené sur les services officiels. Les exemples ci-dessous s’exécutent uniquement dans votre propre application avec une clé API officielle.
Le Function Calling DeepSeek, appelé Tool Calls dans la documentation actuelle, permet au modèle de demander l’utilisation d’une fonction externe : consulter une commande, interroger une base de données, appeler une API météo ou créer un ticket. DeepSeek ne déclenche pas lui-même cette fonction. Le modèle renvoie une demande structurée dans tool_calls ; votre backend vérifie le nom de l’outil et ses arguments, applique les autorisations, exécute la fonction puis renvoie son résultat avec le même tool_call_id.
Cette séparation est essentielle : le modèle peut proposer une action, mais votre application reste seule responsable de son exécution. La documentation officielle DeepSeek sur les Tool Calls confirme que la fonction doit être fournie et exécutée par le développeur.
Function Calling DeepSeek : la réponse rapide
| Question | Réponse actuelle |
|---|---|
| Quels modèles utiliser ? | deepseek-v4-flash ou deepseek-v4-pro. |
| Les Tool Calls fonctionnent-ils avec le mode Thinking ? | Oui, avec les deux modèles V4. Thinking est activé par défaut. |
| Le modèle exécute-t-il la fonction ? | Non. Il génère une demande ; votre application valide et exécute l’outil. |
| Quels champs sont essentiels ? | tools, tool_calls, tool_call_id et éventuellement tool_choice. |
| Le strict mode est-il stable ? | Il est encore en bêta et utilise l’URL https://api.deepseek.com/beta. |
| Combien de fonctions peut-on envoyer ? | La référence Chat Completion documente un maximum de 128 fonctions. |
Sommaire
- Comment fonctionne un appel d’outil ?
- Quels modèles DeepSeek utiliser ?
- Premier appel avec cURL
- Exemple Python complet
- Exemple Node.js et TypeScript
- Comprendre tool_choice
- Tool Calls en mode Thinking
- Strict Mode bêta
- Tool Calls ou JSON Output ?
- Erreurs fréquentes
- Sécurité et checklist de production
- FAQ
Comment fonctionne un appel d’outil avec DeepSeek ?
Un appel d’outil suit une boucle contrôlée par votre application :
- L’utilisateur formule une demande.
- Votre backend envoie les messages à DeepSeek avec une liste de fonctions dans
tools. - Le modèle répond directement ou produit un ou plusieurs éléments dans
tool_calls. - Votre code vérifie le nom de chaque fonction et parse la chaîne JSON contenue dans
function.arguments. - Votre backend valide les types, les formats, les droits d’accès et les règles métier.
- Votre code exécute l’outil réel.
- Chaque résultat est ajouté à l’historique avec
role: "tool"et letool_call_idcorrespondant. - La conversation est renvoyée à DeepSeek afin d’obtenir la réponse finale ou un nouveau tour d’outils.
Le champ function.arguments est une chaîne JSON générée par le modèle. La référence officielle Chat Completion avertit qu’elle peut être invalide ou contenir des paramètres absents du schéma. Il faut donc la traiter comme une entrée non fiable.

Quels modèles DeepSeek utiliser pour les Tool Calls ?
La page officielle Models & Pricing présente actuellement deepseek-v4-flash et deepseek-v4-pro. Les deux prennent en charge les Tool Calls, JSON Output et les modes Thinking et Non-thinking.
| Modèle | Usage conseillé | Concurrence documentée par compte |
|---|---|---|
deepseek-v4-flash | Outils simples, support, classification, appels fréquents et budget serré. | 2 500 requêtes simultanées. |
deepseek-v4-pro | Agents complexes, raisonnement multi-étapes et tâches où la qualité prime sur le coût. | 500 requêtes simultanées. |
Ces limites sont appliquées au niveau du compte, pas de la clé : créer plusieurs clés n’augmente pas la concurrence disponible. Pour les chiffres, prix et limites les plus récents, consultez aussi nos pages sur DeepSeek V4, les limites de l’API et les prix DeepSeek.
Alias hérités : DeepSeek annonce le retrait de
deepseek-chatetdeepseek-reasonerle 24 juillet 2026 à 15:59 UTC. N’utilisez pas ces noms dans une nouvelle intégration. Vérifiez l’annonce V4 officielle si vous consultez ce guide après cette date.
Prérequis et règles avant d’écrire le code
- Créez une clé depuis la plateforme DeepSeek et stockez-la dans
DEEPSEEK_API_KEY. - Ne placez jamais la clé dans du JavaScript exécuté dans le navigateur.
- Appelez l’API depuis un backend, une fonction serverless ou un service contrôlé.
- Définissez des fonctions courtes, explicites et limitées à une seule responsabilité.
- Appliquez une allowlist : ne résolvez jamais un nom de fonction arbitraire.
- Validez les arguments après
JSON.parseoujson.loads. - Gardez l’identité et les permissions de l’utilisateur côté serveur, jamais dans des arguments choisis par le modèle.
Si vous n’avez pas encore de clé, suivez le guide créer et protéger une clé API DeepSeek.
Premier appel Function Calling avec cURL
Cette première requête définit une fonction météo. Elle désactive explicitement Thinking pour montrer le protocole le plus simple. La réponse peut contenir du texte ou un tableau tool_calls.
curl https://api.deepseek.com/chat/completions \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"thinking": {"type": "disabled"},
"messages": [
{
"role": "user",
"content": "Quel temps fait-il à Paris aujourd’hui ?"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Obtenir la météo actuelle pour une ville.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "Ville et pays, par exemple Paris, France"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location", "unit"],
"additionalProperties": false
}
}
}
],
"tool_choice": "auto"
}'
Ne copiez pas directement les arguments reçus dans une requête SQL, une commande système ou une API interne. Vérifiez d’abord que l’outil est autorisé et que chaque valeur respecte vos règles.
Exemple Python complet : statut d’une commande
L’exemple suivant utilise des données simulées. Il gère plusieurs tool_calls, limite le nombre de tours, valide le JSON et conserve l’identité du client côté serveur. L’installation testée pour la structure du SDK est :
pip install openai==2.46.0
import json
import os
import re
from typing import Any
from openai import OpenAI
api_key = os.environ.get("DEEPSEEK_API_KEY")
if not api_key:
raise RuntimeError("La variable DEEPSEEK_API_KEY est manquante")
client = OpenAI(
api_key=api_key,
base_url="https://api.deepseek.com",
timeout=120.0,
max_retries=2,
)
# Dans une application réelle, cette valeur vient de la session ou du JWT.
CURRENT_CUSTOMER_ID = "client_42"
ORDERS = {
"FR-1001": {
"customer_id": "client_42",
"status": "expédiée",
"carrier": "Colissimo",
},
"FR-2001": {
"customer_id": "client_77",
"status": "livrée",
"carrier": "Chronopost",
},
}
tools = [
{
"type": "function",
"function": {
"name": "get_order_status",
"description": (
"Récupérer le statut d’une commande appartenant "
"au client actuellement authentifié."
),
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Identifiant au format FR-1001.",
"pattern": "^FR-[0-9]{4}$",
}
},
"required": ["order_id"],
"additionalProperties": False,
},
},
}
]
def parse_order_args(raw: str) -> dict[str, str]:
value = json.loads(raw)
if not isinstance(value, dict) or set(value) != {"order_id"}:
raise ValueError("Structure d’arguments invalide")
order_id = value["order_id"]
if not isinstance(order_id, str):
raise ValueError("order_id doit être une chaîne")
if not re.fullmatch(r"FR-[0-9]{4}", order_id):
raise ValueError("Format order_id invalide")
return {"order_id": order_id}
def get_order_status(order_id: str) -> dict[str, Any]:
order = ORDERS.get(order_id)
# Ne révélez pas si une commande existe pour un autre client.
if order is None or order["customer_id"] != CURRENT_CUSTOMER_ID:
return {
"ok": False,
"error": "commande_introuvable_ou_non_autorisee",
}
return {
"ok": True,
"order_id": order_id,
"status": order["status"],
"carrier": order["carrier"],
}
messages: list[dict[str, Any]] = [
{
"role": "system",
"content": (
"Tu es un assistant de support. Utilise l’outil pour "
"vérifier une commande et réponds en français."
),
},
{
"role": "user",
"content": "Où en est ma commande FR-1001 ?",
},
]
for _ in range(4):
response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=messages,
tools=tools,
tool_choice="auto",
max_tokens=800,
# thinking est une extension DeepSeek du format OpenAI.
extra_body={"thinking": {"type": "disabled"}},
)
if not response.choices:
raise RuntimeError("Réponse DeepSeek vide")
message = response.choices[0].message
messages.append(message.model_dump(exclude_none=True))
if not message.tool_calls:
print(message.content or "")
break
for tool_call in message.tool_calls:
try:
if tool_call.function.name != "get_order_status":
raise ValueError("Outil non autorisé")
arguments = parse_order_args(
tool_call.function.arguments
)
result = get_order_status(**arguments)
content = json.dumps(result, ensure_ascii=False)
except (json.JSONDecodeError, TypeError, ValueError) as exc:
content = json.dumps(
{"ok": False, "error": str(exc)},
ensure_ascii=False,
)
messages.append(
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": content,
}
)
else:
raise RuntimeError("Nombre maximal d’appels d’outils atteint")
Le client authentifié n’est jamais fourni par le modèle. Même si le modèle remplaçait order_id par une commande valide appartenant à quelqu’un d’autre, la vérification serveur empêcherait la fuite.
Exemple Node.js et TypeScript sans erreur de type
thinking et reasoning_content sont des extensions DeepSeek qui ne figurent pas encore dans les types standards du SDK OpenAI JavaScript. Il ne faut donc pas ajouter thinking directement à un objet littéral strict sans étendre le type.
Installation utilisée pour vérifier la compilation :
npm install [email protected]
npm install --save-dev [email protected] @types/[email protected]
import OpenAI from "openai";
type DeepSeekCreateParams =
OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming & {
thinking: { type: "enabled" | "disabled" };
};
type OrderArgs = {
order_id: string;
};
const client = new OpenAI({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com",
timeout: 120_000,
maxRetries: 2,
});
const tools: OpenAI.Chat.Completions.ChatCompletionTool[] = [
{
type: "function",
function: {
name: "get_order_status",
description: "Obtenir le statut d’une commande autorisée.",
parameters: {
type: "object",
properties: {
order_id: {
type: "string",
pattern: "^FR-[0-9]{4}$",
},
},
required: ["order_id"],
additionalProperties: false,
},
},
},
];
function parseOrderArgs(raw: string): OrderArgs {
const value: unknown = JSON.parse(raw);
const record = value as Record<string, unknown>;
if (
typeof value !== "object" ||
value === null ||
Object.keys(record).length !== 1 ||
typeof record.order_id !== "string" ||
!/^FR-[0-9]{4}$/.test(record.order_id)
) {
throw new Error("Arguments get_order_status invalides");
}
return { order_id: record.order_id };
}
async function getOrderStatus(args: OrderArgs) {
// Remplacez ce mock par une fonction autorisée côté serveur.
return {
ok: true,
order_id: args.order_id,
status: "expédiée",
};
}
async function main() {
if (!process.env.DEEPSEEK_API_KEY) {
throw new Error("DEEPSEEK_API_KEY est manquante");
}
const messages:
OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [
{
role: "user",
content: "Où en est ma commande FR-1001 ?",
},
];
for (let step = 0; step < 4; step += 1) {
const params: DeepSeekCreateParams = {
model: "deepseek-v4-flash",
messages,
tools,
tool_choice: "auto",
max_tokens: 800,
thinking: { type: "disabled" },
};
const response =
await client.chat.completions.create(params);
const assistant = response.choices[0]?.message;
if (!assistant) {
throw new Error("Réponse DeepSeek vide");
}
messages.push({
role: "assistant",
content: assistant.content,
tool_calls: assistant.tool_calls,
});
if (!assistant.tool_calls?.length) {
console.log(assistant.content ?? "");
return;
}
for (const toolCall of assistant.tool_calls) {
let content: string;
try {
if (
toolCall.type !== "function" ||
toolCall.function.name !== "get_order_status"
) {
throw new Error("Outil non autorisé");
}
const args = parseOrderArgs(
toolCall.function.arguments
);
content = JSON.stringify(
await getOrderStatus(args)
);
} catch (error) {
content = JSON.stringify({
ok: false,
error:
error instanceof Error
? error.message
: "Erreur inconnue",
});
}
messages.push({
role: "tool",
tool_call_id: toolCall.id,
content,
});
}
}
throw new Error(
"Nombre maximal d’appels d’outils atteint"
);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Cette structure a passé tsc --strict avec les versions indiquées. Aucun appel payant n’a été lancé pendant la vérification : la sérialisation, le parsing et les types ont été testés avec un transport simulé, puis comparés au protocole officiel.
Comprendre tool_choice
| Valeur | Comportement | Usage |
|---|---|---|
auto | Le modèle choisit entre répondre et appeler un outil. | Valeur générale recommandée en Non-thinking. |
none | Le modèle n’utilise aucun outil. | Réponse textuelle ou test comparatif. |
required | Le modèle doit demander au moins un outil. | Une donnée externe est indispensable. |
| Fonction nommée | Une fonction précise est imposée. | Étape contrôlée d’un workflow. |
Ne forcez pas un outil uniquement pour améliorer artificiellement le taux d’appel. Si une question peut recevoir une réponse sûre sans donnée externe, auto est généralement plus adapté. Si vous imposez une fonction, le backend doit toujours vérifier que l’action est autorisée.
Tool Calls en mode Thinking
Avec DeepSeek V4, Thinking est activé par défaut. Lorsqu’une réponse intermédiaire contient un appel d’outil, conservez et renvoyez le message assistant complet, notamment reasoning_content, content et tool_calls. La documentation Thinking Mode indique que l’oubli de reasoning_content après un Tool Call peut provoquer une erreur HTTP 400.
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=messages,
tools=tools,
reasoning_effort="high",
extra_body={
"thinking": {"type": "enabled"}
},
)
assistant_message = response.choices[0].message
# model_dump conserve reasoning_content et tool_calls.
messages.append(
assistant_message.model_dump(exclude_none=True)
)
Point de documentation à tester : la référence générale Chat Completion liste
tool_choice, mais une page officielle d’intégration indique que DeepSeek V4 en Thinking peut le rejeter. Tant que ces documents ne sont pas harmonisés, ometteztool_choiceen Thinking sauf si votre test réel confirme sa prise en charge. Cette prudence ne concerne pas les exemples Non-thinking ci-dessus.
La page concernée est l’intégration officielle Oh My Pi. Un wrapper tiers peut également supprimer reasoning_content ou reconstruire les messages ; vérifiez donc le payload réellement envoyé.
En Thinking, temperature et top_p n’ont pas d’effet. Les paramètres presence_penalty et frequency_penalty sont obsolètes et sans effet quel que soit le mode.
Strict Mode bêta : conformité au JSON Schema
Le strict mode demande au modèle de respecter le schéma de la fonction plus rigoureusement. Il reste en bêta et impose plusieurs conditions :
- utiliser
https://api.deepseek.com/betacomme URL de base ; - définir
strict: truepour chaque fonction envoyée ; - placer toutes les propriétés de chaque objet dans
required; - définir
additionalProperties: falsepour chaque objet ; - rester dans les types et contraintes JSON Schema acceptés par le serveur.

Les types documentés incluent notamment object, string, number, integer, boolean, array, enum et anyOf, ainsi que $def et $ref. Certaines contraintes restent non prises en charge, notamment minLength, maxLength, minItems et maxItems.
Le strict mode n’est pas une autorisation. Un argument peut respecter parfaitement le JSON Schema tout en demandant une opération interdite. Conservez la validation métier et les permissions côté serveur.
Tool Calls ou JSON Output : quelle différence ?
| Besoin | Fonction adaptée |
|---|---|
| Extraire des champs d’un texte sans action externe. | JSON Output. |
| Obtenir une réponse JSON destinée à votre interface. | JSON Output. |
| Interroger une base de données ou une API métier. | Tool Calls. |
| Créer un ticket ou lancer une action contrôlée. | Tool Calls. |
| Construire un agent alternant raisonnement et outils. | Tool Calls. |
JSON Output structure la réponse du modèle avec response_format: {"type": "json_object"}. Les Tool Calls servent à demander l’exécution d’une fonction. Consultez notre guide JSON Output DeepSeek pour l’implémentation détaillée.
Erreurs fréquentes et corrections
| Symptôme | Cause probable | Correction |
|---|---|---|
| HTTP 400 après un Tool Call | Historique incorrect, tool_call_id absent ou perte de reasoning_content en Thinking. | Renvoyer le message assistant complet et chaque résultat d’outil correctement associé. |
| HTTP 422 | Paramètre, modèle, message ou schéma non accepté. | Comparer le payload avec la référence actuelle et simplifier le schéma. |
| Arguments JSON invalides | Sortie standard non conforme ou champs inventés. | Capturer l’erreur de parsing, refuser les champs inattendus et renvoyer une erreur contrôlée. |
| Le modèle n’appelle aucun outil | Description vague, tools absent ou tool_choice: none. | Améliorer le nom et la description ; utiliser required seulement si l’outil est réellement obligatoire. |
| Boucle d’outils sans fin | Résultat insuffisant ou aucun plafond de tours. | Limiter les itérations et journaliser la cause de chaque nouvel appel. |
| HTTP 429 | Concurrence du compte dépassée. | Respecter Retry-After, mettre en file d’attente et appliquer un backoff avec jitter. |
| HTTP 500 ou 503 | Erreur ou surcharge temporaire du service. | Retry borné uniquement pour les opérations sans risque de duplication. |
La liste officielle des codes d’erreur doit rester la référence. Notre guide des erreurs API DeepSeek fournit une checklist plus large.
Sécuriser les appels d’outils avant la production
Une sortie de modèle reste une entrée non fiable, même lorsqu’elle respecte un schéma. Appliquez au minimum les contrôles suivants :
- Allowlist : associez chaque nom autorisé à une fonction connue ; n’utilisez jamais
evalou un appel dynamique arbitraire. - Validation : vérifiez le JSON, les types, les enums, les bornes et les champs supplémentaires.
- Autorisation : l’identité, le tenant et les permissions proviennent de la session serveur.
- Confirmation humaine : demandez un accord explicite avant paiement, suppression, envoi d’e-mail externe ou action irréversible.
- Moindre privilège : séparez lecture, écriture et administration dans des outils différents.
- Limite de tours : empêchez les boucles d’agents infinies.
- Timeout : arrêtez un outil externe lent et renvoyez une erreur contrôlée.
- Déduplication : rendez les actions avec effet de bord idempotentes dans votre propre couche métier. DeepSeek ne documente pas ici un en-tête d’idempotence natif.
- Logs : ne journalisez pas les clés, secrets, données sensibles ou
reasoning_contentsans nécessité. - Prompt injection : considérez le contenu renvoyé par un site, un document ou un outil comme non fiable et ne le laissez pas modifier les règles système.
La fiche OWASP sur la prévention des prompt injections constitue un bon point de départ pour les agents connectés à des données externes.
Checklist de mise en production
- Utiliser directement
deepseek-v4-flashoudeepseek-v4-pro. - Stocker la clé dans un gestionnaire de secrets.
- Tester chaque outil avec des arguments valides, invalides et inattendus.
- Traiter tous les éléments de
tool_calls, pas uniquement le premier. - Renvoyer chaque résultat avec le bon
tool_call_id. - Conserver
reasoning_contentaprès un appel d’outil en Thinking. - Tester réellement
tool_choiceavant de l’utiliser en Thinking. - Limiter les tours, la durée, les coûts et la concurrence par utilisateur.
- Mettre en place backoff, jitter et file d’attente pour les erreurs temporaires.
- Ajouter des métriques : outil choisi, durée, taux d’erreur, nombre de tours et coût.
- Prévoir un chemin sans outil lorsque la fonction externe est indisponible.
- Revoir les prix, modèles et paramètres à chaque mise à jour de l’API.
Pour construire une interface conversationnelle complète autour de cette boucle, consultez notre guide créer un chatbot avec l’API DeepSeek. Il concerne votre propre application ; deepseek-fr.ai ne fournit pas lui-même de service de chat.
FAQ sur le Function Calling DeepSeek
Quelle différence entre Function Calling et Tool Calls ?
Dans cet usage, les deux expressions décrivent le même cycle. Function Calling est le terme souvent recherché par les développeurs ; Tool Calls est le nom employé dans la documentation DeepSeek actuelle et dans les champs tools et tool_calls.
DeepSeek exécute-t-il directement la fonction ?
Non. Le modèle renvoie le nom d’une fonction et des arguments. Votre backend valide cette demande, exécute l’outil réel et transmet son résultat à DeepSeek.
Quel modèle choisir pour commencer ?
deepseek-v4-flash en Non-thinking est un point de départ simple et économique. Choisissez deepseek-v4-pro lorsque l’orchestration ou le raisonnement est plus complexe et que la qualité justifie son coût supérieur.
Peut-on recevoir plusieurs Tool Calls dans une réponse ?
Oui. Parcourez l’ensemble de message.tool_calls, validez chaque demande et associez chaque résultat à son propre tool_call_id.
Le strict mode rend-il l’appel sûr ?
Non. Il améliore la conformité au JSON Schema, mais ne contrôle ni l’identité de l’utilisateur, ni ses permissions, ni vos règles métier. Les validations serveur restent obligatoires.
Pourquoi une erreur 400 apparaît-elle en Thinking ?
Après un tour contenant un appel d’outil, la cause fréquente est la suppression de reasoning_content ou d’une partie du message assistant. Renvoyez le message assistant complet dans les requêtes suivantes.
Quand utiliser JSON Output plutôt que Tool Calls ?
Utilisez JSON Output pour structurer une réponse sans appeler de système externe. Utilisez Tool Calls lorsqu’une fonction, une base de données, une API ou une action réelle est nécessaire.
Sources et méthode de vérification
Cette page a été contrôlée le 22 juillet 2026 à partir des pages officielles DeepSeek consacrées aux Tool Calls, à Chat Completion, au Thinking Mode, aux modèles, aux limites, aux erreurs et à l’annonce V4. Les exemples Python et TypeScript ont été vérifiés localement pour la syntaxe, les types et la sérialisation avec des réponses simulées. Aucun appel payant n’a été effectué et aucun résultat de modèle n’est présenté comme un test de qualité réel.
Les capacités, contraintes bêta et noms de modèles peuvent changer. En cas de divergence, la documentation officielle la plus récente prévaut. Vous pouvez aussi signaler une information à revérifier.




