Skip to content

[Bug]: DeepSeek V4 thinking mode causes HTTP 400 "reasoning_content must be passed back" on tool calls — sessions freeze unrecoverably #71455

Description

@mikronn2

Bug type

Bug (crash/session freeze)

Beta release blocker

No

Summary

DeepSeek V4 models in thinking mode (deepseek-v4-pro, deepseek-v4-flash) require reasoning_content on every assistant message that includes tool_calls. When this field is absent from persisted session history, replaying the session causes HTTP 400: "The reasoning_content in the thinking mode must be passed back to the API."

OpenClaw's pi-ai OpenAI completions provider (openai-completions.js) does NOT inject reasoning_content on tool-call assistant messages when building the API request from stored history. This causes any DeepSeek V4 thinking-mode session that uses tools to become poisoned after the first tool call, making recovery impossible without clearing history.

Steps to reproduce

  1. Configure OpenClaw with a DeepSeek V4 model in thinking mode as primary model (via Ollama or DeepSeek API)
  2. Enable thinking/reasoning mode
  3. Have a conversation that triggers at least one tool call
  4. Continue the conversation (session replay sends the history back to the API)
  5. Observe HTTP 400 error: "The reasoning_content in the thinking mode must be passed back to the API"
  6. Session becomes stuck/frozen — compaction and /resume both fail with the same 400 error

Expected behavior

When building API messages from stored session history, if the model is in thinking mode and an assistant message contains tool_calls, OpenClaw should inject an empty reasoning_content: "" string on that message (or preserve the original reasoning_content if it was stored). This matches the DeepSeek API contract and prevents session poisoning.

Actual behavior

The pi-ai OpenAI completions provider builds assistantMsg.tool_calls from stored tool-call blocks but only adds reasoning_details if thoughtSignature exists on the block. It does NOT add reasoning_content for DeepSeek thinking-mode messages. On replay, the DeepSeek API rejects the request.

The relevant code is in openai-completions.js around line 633-656 where tool calls are serialized:

assistantMsg.tool_calls = toolCalls.map((tc) => ({
    id: tc.id,
    type: "function",
    function: {
        name: tc.name,
        arguments: JSON.stringify(tc.arguments),
    },
}));
const reasoningDetails = toolCalls
    .filter((tc) => tc.thoughtSignature)
    .map((tc) => { ... });
if (reasoningDetails.length > 0) {
    assistantMsg.reasoning_details = reasoningDetails;
}
// MISSING: reasoning_content for DeepSeek thinking mode

Reference implementation

Hermes Agent (Python) fixed this in commit 93a2d6b (PR #15527). The fix:

  1. Detects DeepSeek thinking mode via provider name, model name substring, or base URL
  2. Injects reasoning_content: "" on tool-call assistant messages at creation time (prevents future poisoning)
  3. Injects reasoning_content: "" on replay for already-poisoned persisted sessions (handles existing history)
  4. Covers the max-iterations flush path that was also missing the passthrough

Detection covers:

  • provider == 'deepseek'
  • model name containing 'deepseek' (case-insensitive)
  • base URL matching api.deepseek.com

Detection heuristic for OpenClaw/Ollama

For Ollama-hosted models, the provider is "ollama" and there's no DeepSeek base URL. The detection should also check:

  • Model ID containing "deepseek" (handles ollama/deepseek-v4-flash-cn-think)
  • Model marked with reasoning: true AND model ID containing "deepseek"

Or alternatively: when a model has reasoning: true in its config, ALWAYS include reasoning_content on tool-call messages (a broader but safer approach that prevents the issue for all thinking-mode models, not just DeepSeek).

Workaround

Switch to a non-DeepSeek model until this is patched. For Ollama-hosted DeepSeek, there's no Ollama-level shim available — the API requirement is enforced by the model's thinking mode handler.

OpenClaw version

2026.4.23

Operating system

Ubuntu 24.04

Model

deepseek-v4-flash-cn-think (via Ollama) / deepseek-v4-pro (via DeepSeek API)

Provider / routing chain

openclaw → ollama → deepseek-v4-flash-cn-think
openclaw → deepseek (API) → deepseek-v4-pro

Logs, screenshots, and evidence

Stuck session diagnostic from OpenClaw gateway:

[diagnostic] stuck session: sessionId=main sessionKey=agent:main:main state=processing age=148s queueDepth=1
[diagnostic] stuck session: sessionId=main sessionKey=agent:main:main state=processing age=328s queueDepth=1

This pattern repeats every session that uses tools with DeepSeek V4 thinking mode.

Impact and severity

High — any agent session using DeepSeek V4 thinking mode with tools becomes unrecoverable after the first tool call. Session compaction and /resume both fail. The only recovery is clearing session history, losing all conversation context.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions