Skip to content

feat(deepseek): support v4 models#71105

Merged
steipete merged 2 commits into
openclaw:mainfrom
lsdsjy:supports-ds-v4
Apr 24, 2026
Merged

feat(deepseek): support v4 models#71105
steipete merged 2 commits into
openclaw:mainfrom
lsdsjy:supports-ds-v4

Conversation

@lsdsjy

@lsdsjy lsdsjy commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Problem: DeepSeek V4 thinking-mode tool calls require prior assistant reasoning_content to be replayed with tool-call history; missing it can make the DeepSeek API reject follow-up requests with 400.
  • Why it matters: DeepSeek's official thinking-mode tool-call guide requires carrying reasoning_content through subsequent requests, including later user turns: https://api-docs.deepseek.com/guides/thinking_mode#tool-calls
  • What changed: Adds deepseek-v4-pro and deepseek-v4-flash, defaults onboarding to deepseek/deepseek-v4-flash, enables DeepSeek thinking payloads, and backfills reasoning_content into replayed OpenAI-compatible chat messages.
  • What did NOT change (scope boundary): Does not change core replay policy beyond the DeepSeek provider hook; no live API credentials or provider auth storage changes.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: The generic OpenAI-compatible conversion did not preserve DeepSeek reasoning_content in replay payloads for assistant messages that include tool_calls.
  • Missing detection / guardrail: Existing DeepSeek tests only covered catalog/auth metadata and did not exercise realistic tool-call replay across multiple user turns.
  • Contributing context (if known): DeepSeek's API contract differs from providers where reasoning can be omitted on replay; the official guide explicitly requires appending/replaying assistant messages with content, reasoning_content, and tool_calls for thinking-mode tool calls.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: extensions/deepseek/index.test.ts
  • Scenario the test should lock in: OpenAI-compatible request payload generation for DeepSeek multi-turn tool-call history preserves reasoning_content on every replayed assistant message, including tool-call turns and prior turns.
  • Why this is the smallest reliable guardrail: It exercises the provider wrapper plus the real buildOpenAICompletionsParams conversion without requiring live DeepSeek credentials.
  • Existing test that already covers this (if any): N/A
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

  • Built-in DeepSeek catalog now exposes deepseek-v4-pro and deepseek-v4-flash with 1,048,576 context and 262,144 max output.
  • DeepSeek onboarding now defaults to deepseek/deepseek-v4-flash.
  • DeepSeek thinking-mode requests send thinking: { type: "enabled" } and reasoning_effort by default for reasoning-capable models.
  • Replayed DeepSeek assistant messages preserve reasoning_content; empty reasoning strings are also replayed when present.

Diagram (if applicable)

Before:
DeepSeek tool call -> tool result -> follow-up request without reasoning_content -> possible 400

After:
DeepSeek tool call -> tool result -> follow-up request with reasoning_content + tool_calls -> accepted replay shape

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local OpenClaw checkout, Node via repo pnpm
  • Model/provider: DeepSeek deepseek-v4-pro, deepseek-v4-flash
  • Integration/channel (if any): Provider plugin / OpenAI-compatible chat completions
  • Relevant config (redacted): N/A

Steps

  1. Build a DeepSeek conversation history with user turn 1, assistant reasoning + tool call, tool result, assistant reasoning + second tool call, tool result, final assistant, user turn 2, and another assistant reasoning + tool call.
  2. Convert that internal context through buildOpenAICompletionsParams.
  3. Apply the DeepSeek provider stream wrapper.
  4. Inspect the outgoing chat completions payload.

Expected

  • Assistant messages in the outgoing payload include reasoning_content alongside content and tool_calls where applicable.
  • Earlier-turn reasoning remains present in later-turn replay payloads.
  • Empty reasoning_content is preserved as an explicit empty string when the stored thinking block exists.

Actual

  • Covered by the new DeepSeek provider tests; payload assertions match the expected DeepSeek official tool-call replay shape.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Validation runs:

pnpm check:test-types
# passed
pnpm test extensions/deepseek
Test Files  1 passed (1)
Tests  13 passed (13)

Additional local check:

pnpm exec oxfmt --check --threads=1 docs/providers/deepseek.md extensions/deepseek/index.test.ts extensions/deepseek/index.ts extensions/deepseek/models.ts extensions/deepseek/onboard.ts extensions/deepseek/replay-history.ts extensions/deepseek/stream.ts
All matched files use the correct format.

Known unrelated local gate result:

pnpm check:changed
failed in typecheck extensions due existing extensions/codex AgentMessage type mismatch between root and extension-local @mariozechner/pi-agent-core installs.

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: DeepSeek catalog models, default model documentation/onboarding, reasoning payload injection, tool-call reasoning replay, multi-turn replay, and empty reasoning replay.
  • Edge cases checked: Both deepseek-v4-pro and deepseek-v4-flash; assistant messages with tool_calls; prior-turn replay after a later user message; explicit empty reasoning string.
  • What you did not verify: Live DeepSeek API call with real credentials; codex review --base origin/main was not run in this session.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (Yes)
  • Migration needed? (No)
  • If yes, exact upgrade steps: Existing configured DeepSeek model refs remain config-owned if explicitly set. New onboarding defaults use deepseek/deepseek-v4-flash.

Risks and Mitigations

  • Risk: DeepSeek's official API behavior may evolve.
    • Mitigation: The replay behavior is provider-local and linked to the official thinking-mode tool-call contract.
  • Risk: Generic OpenAI-compatible conversion shape changes could break the assistant replay index mapping.
    • Mitigation: Added a real conversion-chain test that asserts payload role order, tool-call IDs, and reasoning_content values.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation extensions: deepseek size: L labels Apr 24, 2026
@greptile-apps

greptile-apps Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds deepseek-v4-pro and deepseek-v4-flash to the DeepSeek catalog, updates the onboarding default to deepseek-v4-flash, and introduces replay-history.ts + stream.ts to backfill reasoning_content into replayed assistant messages for DeepSeek thinking-mode tool calls, addressing 400 errors on follow-up requests.

  • P1 – reasoning_content injected even when thinking is disabled: In stream.ts, backfillDeepSeekReasoningPayload is called unconditionally after the thinkingType guard block. When thinking is explicitly disabled (thinkingType === \"disabled\"), the code removes top-level reasoning/reasoning_effort fields but still injects reasoning_content into individual assistant messages for any context that contains thinking blocks. Sending reasoning_content alongside thinking: { type: \"disabled\" } is contradictory and may trigger a 400 from DeepSeek's API.

Confidence Score: 4/5

Mostly safe to merge, but the unconditional reasoning_content backfill when thinking is disabled should be addressed to avoid potential API 400 errors in the disabled-thinking path.

One P1 logic bug: backfillDeepSeekReasoningPayload runs unconditionally, including when thinkingType is "disabled", which can send reasoning_content to DeepSeek in a context where thinking is turned off. The happy-path (thinking enabled) is well-tested and correct; remaining findings are limited to this one control-flow gap.

extensions/deepseek/stream.ts — the payload-patch closure should guard the backfill call on thinkingType not being "disabled".

Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/deepseek/stream.ts
Line: 97-111

Comment:
**`reasoning_content` backfilled even when thinking is disabled**

`backfillDeepSeekReasoningPayload` is called unconditionally regardless of `thinkingType`. When thinking is explicitly disabled (`thinkingType === "disabled"`), the code correctly removes `reasoning`, `reasoning_effort`, and `reasoningEffort` from the top-level payload — but still injects `reasoning_content` into individual assistant messages for any context messages that contain thinking blocks. Sending `reasoning_content` in messages alongside `thinking: { type: "disabled" }` conflicts with DeepSeek's API contract and could result in a 400 error on those calls.

```suggestion
      if (thinkingType !== "disabled") {
        backfillDeepSeekReasoningPayload({
          payload,
          contextMessages: (context as { messages?: unknown }).messages,
        });
      }
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "feat(deepseek): support v4 models" | Re-trigger Greptile

Comment thread extensions/deepseek/stream.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3a0592b8d3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread extensions/deepseek/replay-history.ts Outdated
@steipete
steipete merged commit 7d1891e into openclaw:main Apr 24, 2026
76 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Thanks @lsdsjy, landed this via squash as 7d1891e.

Maintainer rewrite summary:

  • kept DeepSeek support extension-owned and preserved legacy deepseek-chat / deepseek-reasoner entries
  • added DeepSeek V4 Flash/Pro catalog entries and onboarding default
  • updated Pi packages to 0.70.2 and verified Pi includes the DeepSeek V4 models
  • added provider wrapper coverage for V4 thinking payloads and disabled/None stripping of replayed reasoning_content

Validation:

  • pnpm test extensions/deepseek
  • pnpm check:test-types
  • pnpm config:schema:check
  • pnpm check:docs
  • pnpm check
  • live DeepSeek V4 Flash/Pro API smoke, including disabled/None replay and thinking/tool replay behavior
  • PR CI green on f7e45ea

@zilvercat

Copy link
Copy Markdown

I find the same issue with the same models in openclaw v2026.4.25, currently, you can't use /think with deepseek v4 models, specially on flash version after a multistep conversation it fail " run error: LLM request failed: provider rejected the request schema or tool payload."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants