openclaw - ✅(Solved) Fix [Bug]: DeepSeek V4 thinking mode causes HTTP 400 "reasoning_content must be passed back" on tool calls — sessions freeze unrecoverably [1 pull requests, 3 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#71455Fetched 2026-04-26 05:12:33
View on GitHub
Comments
3
Participants
2
Timeline
5
Reactions
0
Author
Participants
Timeline (top)
commented ×3closed ×1cross-referenced ×1

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.

Error Message

  1. Observe HTTP 400 error: "The reasoning_content in the thinking mode must be passed back to the API"
  2. Session becomes stuck/frozen — compaction and /resume both fail with the same 400 error

Root Cause

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.

Fix Action

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.

PR fix notes

PR #71473: fix(openai): replay DeepSeek tool reasoning_content

Description (problem / solution / changelog)

Fixes #71455.

Summary

  • detect DeepSeek-family OpenAI-compatible models by model id, so Ollama/custom hosted deepseek-* models get DeepSeek thinking compat
  • inject blank reasoning_content: "" on assistant messages with replayed tool_calls when DeepSeek thinking mode is active
  • preserve the disabled-thinking path without adding reasoning_content

Test plan

  • pnpm test src/agents/openai-transport-stream.test.ts extensions/deepseek/index.test.ts

Changed files

  • src/agents/openai-completions-compat.ts (modified, +5/-1)
  • src/agents/openai-transport-stream.test.ts (modified, +171/-0)
  • src/agents/openai-transport-stream.ts (modified, +32/-8)
  • src/agents/provider-attribution.ts (modified, +9/-2)

Code Example

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

---

[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
RAW_BUFFERClick to expand / collapse

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 93a2d6b3 (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.

extent analysis

TL;DR

Injecting an empty reasoning_content string on tool-call assistant messages for DeepSeek V4 thinking-mode models can prevent session poisoning.

Guidance

  • Modify the openai-completions.js file to include reasoning_content: "" on tool-call assistant messages when the model is in thinking mode.
  • Detect DeepSeek thinking mode via provider name, model name substring, or base URL, and apply the fix accordingly.
  • Consider adding a check for reasoning: true in the model config to ensure reasoning_content is included on tool-call messages for all thinking-mode models.
  • Verify the fix by testing a conversation that triggers a tool call with a DeepSeek V4 thinking-mode model and checking for the absence of HTTP 400 errors.

Example

assistantMsg.tool_calls = toolCalls.map((tc) => ({
    id: tc.id,
    type: "function",
    function: {
        name: tc.name,
        arguments: JSON.stringify(tc.arguments),
    },
    reasoning_content: "", // Add this line
}));

Notes

The provided fix is based on the reference implementation from the Hermes Agent (Python) and may require adjustments for the OpenClaw/Ollama environment.

Recommendation

Apply the workaround by injecting reasoning_content: "" on tool-call assistant messages for DeepSeek V4 thinking-mode models, as this is a targeted fix for the identified issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

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.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: DeepSeek V4 thinking mode causes HTTP 400 "reasoning_content must be passed back" on tool calls — sessions freeze unrecoverably [1 pull requests, 3 comments, 2 participants]