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
- Configure OpenClaw with a DeepSeek V4 model in thinking mode as primary model (via Ollama or DeepSeek API)
- Enable thinking/reasoning mode
- Have a conversation that triggers at least one tool call
- Continue the conversation (session replay sends the history back to the API)
- Observe HTTP 400 error: "The reasoning_content in the thinking mode must be passed back to the API"
- 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:
- Detects DeepSeek thinking mode via provider name, model name substring, or base URL
- Injects
reasoning_content: "" on tool-call assistant messages at creation time (prevents future poisoning)
- Injects
reasoning_content: "" on replay for already-poisoned persisted sessions (handles existing history)
- 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.
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_contenton every assistant message that includestool_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 injectreasoning_contenton 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
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 emptyreasoning_content: ""string on that message (or preserve the originalreasoning_contentif it was stored). This matches the DeepSeek API contract and prevents session poisoning.Actual behavior
The pi-ai OpenAI completions provider builds
assistantMsg.tool_callsfrom stored tool-call blocks but only addsreasoning_detailsifthoughtSignatureexists on the block. It does NOT addreasoning_contentfor DeepSeek thinking-mode messages. On replay, the DeepSeek API rejects the request.The relevant code is in
openai-completions.jsaround line 633-656 where tool calls are serialized:Reference implementation
Hermes Agent (Python) fixed this in commit 93a2d6b (PR #15527). The fix:
reasoning_content: ""on tool-call assistant messages at creation time (prevents future poisoning)reasoning_content: ""on replay for already-poisoned persisted sessions (handles existing history)Detection covers:
provider == 'deepseek'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:
ollama/deepseek-v4-flash-cn-think)reasoning: trueAND model ID containing "deepseek"Or alternatively: when a model has
reasoning: truein its config, ALWAYS includereasoning_contenton 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:
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.