On this page

Calling the official DeepSeek API in thinking mode with tool calling enabled, a bare 400 often points to missing history rather than a bad tool schema. DeepSeek’s Thinking Mode guide is clear: when tools is on the request, reasoning_content from previous turns must be fully returned on every subsequent request. Drop it—intentionally or through a store, proxy, or serializer that only keeps content—and the API rejects the call. Everything below follows that guide as of October 26, 2026 (Beijing time). For reference only; this failure has not been reproduced on this site, and a fix has not been tested here. Feedback from production hits can go through the site-owner contact link in the footer.

The symptom: 400 with tools in thinking mode

Thinking mode is on by default for DeepSeek’s Chat Completions path. The model first emits a chain of thought, then the final answer. Those two pieces arrive as sibling fields on the assistant message: reasoning_content and content.

When you also pass a tools array, DeepSeek expects the conversation history to keep that chain of thought. The docs say that if your code does not correctly pass reasoning_content back, the API returns a 400 error. That is the failure this note is about—not auth failures, not rate limits, and not every other 400 you might see.

The rule: pass back all historical reasoning_content

For any request that carries tools:

  • Pass back the reasoning_content of all previous turns.
  • Those values are concatenated into the model context.
  • You must keep doing this on every subsequent request, including turns where the model did not issue a tool call.

DeepSeek’s sample pattern is the safest default: append the whole assistant message object the SDK returned.

python
messages.append(response.choices[0].message)

That object already holds content, reasoning_content, and tool_calls. The explicit equivalent is:

python
messages.append({
    "role": "assistant",
    "content": response.choices[0].message.content,
    "reasoning_content": response.choices[0].message.reasoning_content,
    "tool_calls": response.choices[0].message.tool_calls,
})

If your own history builder rebuilds assistant messages from only role + content, you will silently drop reasoning_content—and the next tools request can come back 400.

When the request does not carry tools

Without tools, the rule flips:

  • You do not need to pass reasoning_content back.
  • Even if you do send it, the API ignores it and does not concatenate it into context.

So a multi-turn chat that never attaches tools can keep only content and still behave as the Multi-turn Conversation section describes. The hard requirement starts the moment tools is present on the request.

Where reasoning_content usually gets dropped

Visitor-facing places that commonly strip the field:

  • Client message stores that persist only role and content, then rebuild history for the next call.
  • Proxies and gateways that whitelist OpenAI-shaped fields and discard unknown keys such as reasoning_content.
  • History databases or ORMs whose schema has a content column but no column for chain-of-thought text.
  • Manual JSON serializers that copy tool_calls but forget the sibling reasoning_content on the same assistant turn.

If your stack sits between the SDK response and the next request, check that the field survives the round trip—especially after a tool result is appended and you fire the follow-up completion.

What this is not

A few boundaries so this note stays useful:

  • Not every HTTP 400 from DeepSeek is a missing reasoning_content. Invalid payloads, auth problems, and other validation errors also return 400. Treat this guide as one documented cause when thinking mode and tools are both in play.
  • Not the DeepSeek Harness install path. Installing or wiring a coding harness is a separate topic—see DeepSeek Harness Install Guide: Windows, Linux, CLI, Plugins. This page is only about the API history rule for thinking mode plus tools.
  • Official DeepSeek API scope. The wording above follows DeepSeek’s own Thinking Mode docs for the official API. Third-party relays may behave differently; check their docs separately.

Nearby DeepSeek and harness context on this site: