DeepSeek a sorti V4 Pro de la préversion le 12 août 2026, et la couverture de son lancement met l'accent sur les workflows d'agents : codage, utilisation d'outils et tâches à long terme qui enchaînent des dizaines d'étapes sans perdre le fil. Ce positionnement fait qu'une fonctionnalité de l'API est plus importante que toute autre, l'appel de fonction, et c'est la seule fonctionnalité que les guides de la semaine de lancement n'ont pas abordée. Chaque tutoriel s'arrête jusqu'à présent aux complétions de chat.
Celui-ci va plus loin : définissez un schéma d'outil, effectuez votre premier appel d'outil avec le SDK Python openai standard, construisez la boucle complète de l'agent, puis testez l'ensemble dans Apidog avant le déploiement de votre agent. Si vous n'avez pas encore de clé API DeepSeek, configurez-en une avec notre guide sur comment utiliser l'API DeepSeek V4, puis revenez.
button
TL;DR
deepseek-v4-pro(version GA DeepSeek-V4-Pro-0813) prend en charge l'appel de fonction de style OpenAI : envoyez un tableau `tools`, recevez des `tool_calls`, et renvoyez les résultats en tant que messages `tool`. Le SDK `openai` standard fonctionne avec `https://api.deepseek.com`.- La boucle complète de l'agent est d'environ 30 lignes de Python : appeler, exécuter, ajouter, répéter jusqu'à ce que le modèle cesse de demander des outils. Les appels parallèles et les sorties structurées sont pris en charge ; le mode de réflexion ajoute `reasoning_content`.
- Le cache préfixe automatique facture l'entrée en cas de succès du cache à 0,003625 $ par million de tokens, soit 120 fois moins cher qu'en cas d'échec. C'est ce qui rend les boucles d'agent profondes abordables.
- La qualité de l'appel d'outils varie en fonction de votre harnais et de vos schémas. Testez vos outils réels avec le modèle en direct, pas avec des benchmarks.
Pourquoi l'appel d'outils est le cas d'utilisation phare de V4 Pro
DeepSeek a conçu V4 Pro pour les agents, et la fiche technique ressemble à une liste de contrôle d'exécution d'agent :
| Spécification | DeepSeek V4 Pro |
|---|---|
| Architecture | MoE Sparsifié : 1,6 T paramètres totaux, 49 B actifs par token |
| Fenêtre contextuelle | 1 million de tokens |
| Sortie maximale | 384 mille tokens |
| Prix d'entrée | 0,435 $/M tokens (échec cache), 0,003625 $/M (succès cache) |
| Prix de sortie | 0,87 $/M tokens |
| Appel de fonction | Tableau `tools` compatible OpenAI et réponses `tool_calls` |
| Autres surfaces | Format Anthropic Messages, API DeepSeek Responses |
Chaque ligne correspond à un problème d'agent : la fenêtre de 1 million de tokens contient l'historique complet des résultats d'outils d'un agent long, le plafond de sortie de 384 000 laisse de la place pour de grandes charges utiles structurées, et la mise en cache de préfixes rend l'économie des boucles viable. Le modèle est listé sur OpenRouter sous le nom deepseek-v4-pro-0813 pour les comparaisons de fournisseurs.
Une mise en garde avant le code. Dans la discussion de lancement sur Hacker News, des développeurs ont signalé que la performance de l'appel d'outils est très sensible au harnais : le même modèle obtenait de meilleurs ou de moins bons résultats selon le framework, l'échafaudage des prompts et le style des schémas. Les benchmarks ne vous diront pas comment il gère vos schémas d'outils. Testez avec vos définitions réelles.
Comment fonctionne l'appel de fonction de DeepSeek
L'appel de fonction ne signifie pas que le modèle exécute quoi que ce soit. Il répond avec une requête structurée, "appelez get_order avec {"order_id": "ORD-10442"}", au lieu d'un texte. Votre code exécute la fonction, renvoie le résultat, et le modèle continue avec des données réelles. Le cycle :
- Vous envoyez des `messages` plus un tableau `tools` décrivant chaque fonction en JSON Schema.
- Le modèle décide qu'un outil est nécessaire et répond avec des `tool_calls` et `finish_reason: "tool_calls"`.
- Votre code analyse les arguments et exécute la fonction réelle.
- Vous ajoutez le résultat en tant que message `role: "tool"` lié à l'ID de l'appel.
- Le modèle demande soit un autre outil, soit produit sa réponse finale.
Si vous avez travaillé avec l'appel de fonction OpenAI, c'est le même format de communication ; la plupart des codes d'agents sont portables en changeant l'URL de base et le nom du modèle. La documentation officielle de DeepSeek couvre également un point de terminaison Messages compatible Anthropic et une API Responses, mais ce guide se limite à la surface compatible OpenAI.
Étape 1 : Configurer le client
Installez le SDK et configurez-le pour DeepSeek :
pip install openai
export DEEPSEEK_API_KEY="sk-..."
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
C'est toute la configuration. Chaque exemple utilise `model="deepseek-v4-pro"`, qui correspond à la version GA DeepSeek-V4-Pro-0813.
Étape 2 : Définir un schéma d'outil
Nous allons construire un agent de support pour une boutique en ligne. Son premier outil recherche les commandes. Une définition d'outil comporte trois parties : un nom, une description et un JSON Schema pour les paramètres.
tools = [
{
"type": "function",
"function": {
"name": "get_order",
"description": (
"Recherche une commande client par son ID. Renvoie le statut de la commande, "
"le transporteur, le numéro de suivi et la date de livraison estimée. Utilisez ceci "
"chaque fois que l'utilisateur demande où se trouve une commande ou quel est son état."
),
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "L'ID de la commande, formaté comme 'ORD-10442'."
}
},
"required": ["order_id"],
},
},
}
]
La description n'est pas une décoration : le modèle décide quand appeler un outil en la lisant. Les descriptions vagues sont la principale raison pour laquelle un modèle ignore un outil ou en choisit un mauvais.
La fonction locale que le schéma décrit, simulée pour un service de commande réel :
def get_order(order_id: str) -> dict:
"""Simulation de votre service de commande réel."""
fake_db = {
"ORD-10442": {
"status": "shipped",
"carrier": "DHL",
"tracking_number": "4281337005",
"estimated_delivery": "2026-08-15",
},
"ORD-10587": {
"status": "processing",
"estimated_ship_date": "2026-08-14",
},
}
return fake_db.get(order_id, {"error": f"ID de commande inconnu : {order_id}"})
Étape 3 : Effectuer votre premier appel d'outil
Envoyez une question à laquelle le modèle ne peut pas répondre sans l'outil :
messages = [
{"role": "system", "content": "Vous êtes un agent de support pour une boutique en ligne."},
{"role": "user", "content": "Où est ma commande ORD-10442?"},
]
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=messages,
tools=tools,
)
message = response.choices[0].message
print(message.tool_calls[0].function.name) # get_order
print(message.tool_calls[0].function.arguments) # {"order_id": "ORD-10442"}
Au lieu de répondre, le modèle vous demande d'exécuter `get_order`. La charge utile de la réponse brute ressemble à ceci :
{
"id": "chatcmpl-8f3a1c",
"object": "chat.completion",
"model": "deepseek-v4-pro",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "call_0_f1c29a44",
"type": "function",
"function": {
"name": "get_order",
"arguments": "{\"order_id\": \"ORD-10442\"}"
}
}
]
},
"finish_reason": "tool_calls"
}
],
"usage": {
"prompt_tokens": 312,
"completion_tokens": 24,
"total_tokens": 336,
"prompt_cache_hit_tokens": 0,
"prompt_cache_miss_tokens": 312
}
}
Trois détails importants. `finish_reason` est `"tool_calls"`, ce qui indique à votre boucle que le modèle souhaite l'exécution. Chaque appel porte un `id` que vous devez renvoyer avec le résultat. Et `arguments` est une *chaîne* JSON que vous analysez vous-même, attendez-vous donc à ce qu'elle soit occasionnellement mal formée.
Étape 4 : Exécuter la fonction et renvoyer le résultat
Exécutez la fonction, puis ajoutez deux messages : le tour de l'assistant contenant les `tool_calls`, et un message `tool` portant votre résultat.
import json
tool_call = message.tool_calls[0]
args = json.loads(tool_call.function.arguments)
result = get_order(args)
messages.append(message) # le tour de l'assistant contenant les tool_calls
messages.append({
"role": "tool",
"tool_call_id": tool_call.id, # doit correspondre à l'id de la réponse
"content": json.dumps(result),
})
final = client.chat.completions.create(
model="deepseek-v4-pro",
messages=messages,
tools=tools,
)
print(final.choices[0].message.content)
# Votre commande ORD-10442 a été expédiée avec DHL et devrait arriver
# d'ici le 15 août 2026. Numéro de suivi : 4281337005.
Le lien `tool_call_id` est strict : chaque entrée `tool_calls` nécessite un message `tool` correspondant avant le prochain tour du modèle, sinon la requête échoue.
Étape 5 : La boucle complète de l'agent
Les agents réels enchaînent les appels : rechercher une commande, vérifier une politique de remboursement, rédiger un e-mail, chaque étape dépendant de la précédente. Le modèle : continuer à appeler le modèle et à exécuter ce qu'il demande jusqu'à ce qu'il renvoie une réponse normale.
TOOLS_BY_NAME = {"get_order": get_order}
def run_agent(client, messages, tools, max_rounds=10):
"""Exécute le modèle jusqu'à ce qu'il produise une réponse finale ou atteigne la limite."""
for _ in range(max_rounds):
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=messages,
tools=tools,
)
message = response.choices[0].message
messages.append(message)
if not message.tool_calls: # pas de requêtes d'outils : nous avons terminé
return message.content
for tool_call in message.tool_calls:
fn = TOOLS_BY_NAME.get(tool_call.function.name)
try:
if fn is None:
raise ValueError(f"Outil inconnu : {tool_call.function.name}")
args = json.loads(tool_call.function.arguments)
result = fn(args)
except Exception as exc:
result = {"error": str(exc)} # renvoyer les échecs au modèle
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result),
})
raise RuntimeError(f"L'agent n'a pas terminé dans les {max_rounds} tours")
Les frameworks et les SDK d'agents sont des élaborations de cette boucle. La limite `max_rounds` transforme un modèle bloqué à rappeler un outil défaillant en un échec propre au lieu d'une facture ouverte.
Appels d'outils parallèles
Demandez deux recherches, "comparez le statut de ORD-10442 et ORD-10587", et V4 Pro les regroupera souvent en un seul tour :
"tool_calls": [
{
"id": "call_0_a7d1",
"type": "function",
"function": { "name": "get_order", "arguments": "{\"order_id\": \"ORD-10442\"}" }
},
{
"id": "call_1_b3e9",
"type": "function",
"function": { "name": "get_order", "arguments": "{\"order_id\": \"ORD-10587\"}" }
}
]
La boucle `run_agent` gère déjà cela : la boucle interne `for` répond à chaque appel avec son propre `tool_call_id` (chaque appel nécessite un résultat correspondant avant le tour suivant), et vous êtes libre d'exécuter le lot de manière concurrente. C'est une philosophie différente de l'appel d'outil programmatique de GPT-5.6, où le modèle écrit le code d'orchestration dans un bac à sable ; DeepSeek maintient l'exécution, et la limite de confiance, dans votre environnement d'exécution.
Mode de réflexion et outils
V4 Pro est livré avec trois modes de réflexion, vous permettant d'augmenter l'effort de raisonnement pour les tours de planification difficiles et de le sauter pour les recherches de routine (voir la documentation officielle pour les noms de modes et les valeurs par défaut). Avec la réflexion activée, l'API renvoie la trace du modèle sous forme de `reasoning_content` en plus des appels d'outils :
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=messages,
tools=tools,
extra_body={"thinking": {"type": "enabled"}},
)
message = response.choices[0].message
print(message.reasoning_content) # la trace de planification
print(message.tool_calls) # les appels qu'il a choisis
La trace montre pourquoi le modèle a choisi un outil, ce qui est généralement le cas lorsqu'un mauvais schéma se révèle. Supprimez `reasoning_content` avant d'ajouter le tour de l'assistant à l'historique, et réservez la réflexion pour les tours à forte planification, la facturation du raisonnement est de 0,87 $/M en sortie.
Gestion des erreurs : quand le modèle se trompe dans un appel
Les appels d'outils mal formés sont rares, mais une boucle d'agent amplifie chaque mode de défaillance. Le modèle essentiel : ne jamais planter sur un mauvais appel, renvoyer le problème comme résultat de l'outil, et laisser le modèle réessayer. Cela couvre les arguments qui échouent `json.loads` ainsi que les valeurs qui enfreignent vos règles métier :
from jsonschema import ValidationError, validate
schema = tools[0]["function"]["parameters"]
try:
args = json.loads(tool_call.function.arguments)
validate(instance=args, schema=schema)
result = get_order(**args)
except (json.JSONDecodeError, ValidationError) as exc:
result = {
"error": f"Arguments invalides : {exc}",
"hint": "Appelez get_order à nouveau avec une chaîne order_id comme 'ORD-10442'.",
}
Le champ `hint` est important : une correction d'une ligne produit généralement un nouvel essai corrigé au tour suivant. Traitez également les erreurs d'agent comme des événements de sécurité. Un modèle incité à appeler `delete_order` avec des arguments fournis par un attaquant n'est dangereux que dans la mesure de la clé qui le sous-tend, ce qui justifie les clés API à privilèges minimaux pour les agents IA. Limitez la portée des identifiants afin qu'un mauvais appel ne puisse pas devenir un incident.
Testez et déboguez les appels d'outils avec Apidog avant le déploiement
Chaque outil est un mince enveloppement autour d'une API, et le modèle est maintenant un consommateur de cette API. Si le point de terminaison de support est ambigu ou instable, le modèle hérite de tous ses défauts. C'est là que Apidog gagne sa place dans la boucle :
- Concevez d'abord l'API de support. Définissez `GET /orders/{order_id}` comme une spécification dans le concepteur visuel d'Apidog ; le JSON Schema de votre outil découle directement de la spécification, de sorte que les deux ne peuvent pas s'écarter silencieusement.
- Simulez-le avant l'existence du backend. La simulation intelligente d'Apidog fournit des réponses réalistes à partir du schéma, de sorte que la boucle de l'agent s'exécute contre `get_order` pendant que le service réel est encore en construction.
- Inspectez les charges utiles brutes. Envoyez le même corps `messages` + `tools` à `https://api.deepseek.com` depuis Apidog et lisez le JSON brut `tool_calls` directement, une propriété `properties` mal imbriquée ou des arguments doublement encodés apparaissent en une seule inspection.
- Transformez les conversations en scénarios de test. Affirmez sur `finish_reason` et les formes d'arguments, et exécutez la suite à chaque changement de schéma ; étant donné la sensibilité du harnais signalée sur Hacker News, une suite de régression sur vos schémas réels est le benchmark qui prédit la production. Voir le branchement d'un agent IA dans un harnais de test Apidog pour un modèle plus approfondi.
Téléchargez Apidog gratuitement pour suivre ; le serveur de simulation et les scénarios de test sont inclus dans le niveau gratuit.
Ce que coûtent les boucles d'agents (et pourquoi la mise en cache est décisive)
Les boucles d'agents relisent l'intégralité de la conversation à chaque tour : au dixième tour, votre prompt système, les schémas d'outils et neuf tours de résultats sont facturés pour la dixième fois. Le cache préfixe automatique de V4 Pro brise cette courbe, l'entrée de chaque tour étant celle du tour précédent plus un petit extra, de sorte que la quasi-totalité du préfixe est facturée à 0,003625 $/M au lieu de 0,435 $/M. Relire une conversation de 100 000 tokens coûte environ 0,0435 $ sans cache mais environ 0,0004 $ avec cache ; `prompt_cache_hit_tokens` dans le bloc d'utilisation indique votre taux de réussite réel.
Pour maintenir ce taux élevé, ne modifiez jamais les messages précédents et maintenez le tableau `tools` stable en termes d'octets d'un tour à l'autre. Notre introduction sur ce qu'est le cache de prompts couvre les mécanismes. Et si `deepseek-v4-flash` à 0,14 $/0,28 $ semble tentant : il est bien pour le routage d'outils en un seul coup, mais il régresse sur les boucles enchaînant plus de 10 appels, donc les réessais absorbent les économies, Pro est le choix par défaut plus sûr pour les agents.
FAQ
Les définitions d'outils coûtent-elles des tokens ?
Oui, le tableau `tools` est une entrée à chaque requête. Maintenez-le stable et il rejoindra le préfixe mis en cache après le premier tour, facturé au taux de succès du cache à partir de ce moment-là.
Puis-je combiner l'appel de fonction avec des sorties structurées ?
Oui. Un modèle courant : les outils récupèrent les données intermédiaires, un schéma de sortie structuré formate la réponse finale, de sorte que le code en aval ne parse jamais de texte libre.
En résumé
L'appel de fonction sur DeepSeek V4 Pro est délibérément simple à implémenter : des schémas compatibles OpenAI, un tableau `tool_calls`, un message `tool` avec un ID. La boucle de l'Étape 5 est toute l'architecture, et la tarification basée sur le cache la rend moins chère que la plupart des équipes ne s'y attendent. Ce que les benchmarks ne peuvent pas vous dire, c'est comment le modèle se comporte avec vos schémas. Concevez délibérément les API de support, simulez-les tôt, et maintenez une suite de régression des scénarios d'appel d'outils dans Apidog afin que les modifications de schéma ne puissent pas casser silencieusement votre agent.
button
