DeepSeek V4 Pro (0813) is available on AIHubMix through three protocol surfaces:
- OpenAI-compatible Chat Completions
- OpenAI Responses
- Claude-compatible Messages
They reach the same model, but the request and response shapes are not interchangeable. The largest production trap is thinking history: on tool-using multi-turn conversations, dropping the previous turn's thinking content causes a hard HTTP 400.
The findings below come from calls made on August 13, 2026 against the AIHubMix production APIs. The full hands-on guide includes complete examples, observed responses, and the full capability matrix.
The short version
| Capability | Chat Completions | Responses | Messages |
|---|---|---|---|
| Endpoint | /v1/chat/completions |
/v1/responses |
/v1/messages |
| Thinking off | thinking.type="disabled" |
reasoning.effort="none" |
thinking.type="disabled" |
| Thinking passback | reasoning_content |
type="reasoning" item |
thinking block |
| Tool schema | nested function
|
flat definition | input_schema |
| Structured output | response_format |
text.format |
no native field |
| Web search | no | web_search |
web_search_20250305 |
The model has a 1M-token context window, accepts text input, and thinks by default. Sending an excessive max_tokens value is rejected instead of silently truncated; a request with max_tokens=9999999 returned 400 and identified the ceiling as 393,216.
One subtle input warning: Responses does not reject image parts. Unsupported image and file inputs are replaced with placeholder text. "No error" does not mean the model saw the image.
1. Preserve thinking history verbatim
In thinking mode, the previous turn's thinking is part of the conversation state. This matters most in agent loops where the model emits a tool call and the client sends the tool result back.
Chat Completions
Preserve reasoning_content on the historical assistant message:
messages = [
{"role": "user", "content": "What is 1 + 1? Remember the result."},
{
"role": "assistant",
"content": "2",
"reasoning_content": "<reasoning_content from the previous response>",
},
{"role": "user", "content": "Add 1 to the result."},
]
Dropping reasoning_content returned HTTP 400. Restoring it made the same request continue normally.
Responses
Append the prior response.output without filtering its items:
input = previous_input + response.output + [
{"role": "user", "content": "Add 1 to the result."}
]
A common framework pattern is to retain only items where type == "message". That silently removes the reasoning item and triggers the next-turn 400.
Messages
Pass the previous response.content back as the assistant message:
messages = [
{"role": "user", "content": "What's the weather in Paris?"},
{"role": "assistant", "content": response.content},
{"role": "user", "content": [tool_result_block]},
]
Keep both the thinking and tool_use blocks. Removing the thinking block returned an invalid_request_error.
2. Turning thinking off requires different fields
Thinking is enabled by default. The off switch depends on the protocol:
# Chat Completions
extra_body={"thinking": {"type": "disabled"}}
# Responses
reasoning={"effort": "none"}
# Messages
extra_body={"thinking": {"type": "disabled"}}
The result is observable. Chat and Messages stop returning their thinking fields. Responses reports zero reasoning tokens and omits the reasoning output item.
low, high, and max were accepted, but token counts for the same prompts did not vary monotonically and the selected level was not echoed. The only level whose effect was unambiguous from the caller side was Responses none.
3. Tool schemas are protocol-specific
Chat Completions wraps a function definition inside function:
tools=[{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
Responses uses a flat definition:
tools=[{
"type": "function",
"name": "get_weather",
"description": "Get weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}]
Messages uses input_schema.
There are two more gotchas:
-
tool_choice: "required"returns 400 on Chat and Responses while thinking is enabled. Use a named-function choice, or disable thinking before usingrequired. - Parallel tool calling cannot be disabled. DeepSeek documents the relevant switches as ignored on Responses and Messages. Serialize calls in your client if ordering matters.
Tool definitions also consume context in full. A request containing 200 definitions succeeded in testing, but the prompt reached 6,105 tokens. Route only the tools relevant to the current task.
4. Structured output, caching, and web search
Chat Completions supports JSON mode through response_format. Responses supports strict JSON Schema through text.format:
response = client.responses.create(
model="deepseek-v4-pro-0813",
input="Return the number 1 under key a.",
text={
"format": {
"type": "json_schema",
"name": "extract",
"strict": True,
"schema": {
"type": "object",
"properties": {"a": {"type": "integer"}},
"required": ["a"],
},
}
},
)
Messages has no equivalent structured-output field. Carrying a schema in a forced tool is possible, but use Chat or Responses when hard schema guarantees are central.
Context caching is automatic. Repeated long prefixes produced cache hits under different usage fields:
- Chat:
prompt_tokens_details.cached_tokens - Responses:
input_tokens_details.cached_tokens - Messages:
cache_read_input_tokens
Put stable system instructions, knowledge snippets, and tool definitions at the front of the request.
Server-side web search worked on Responses and Messages. Chat accepted unknown search-like fields without error, but did not perform retrieval. Route search workloads to Responses or Messages.
Production checklist
- Persist thinking content as normal conversation state.
- Do not filter Responses output down to message items before passback.
- Avoid
tool_choice: "required"while thinking is enabled. - Keep the three tool-definition schemas separate.
- Do not infer image support from the absence of an error.
- Serialize parallel tool calls on the client when required.
- Branch on HTTP status, not only
error.type, for Responses errors. - Do not use the echoed
modelfield as the sole routing or attribution signal.
DeepSeek V4 Pro's multi-protocol support is useful, but compatibility is a client-side responsibility. Treat thinking as durable conversation state and isolate protocol adapters around history, tools, usage, and errors.
For the complete 3-API matrix, additional code samples, logprobs behavior, current-path deviations, and FAQs, read the full AIHubMix guide. Current pricing and status are on the model page.
Top comments (0)