Featured image of post DeepSeek + Claude Code: Thinking Block 兼容性问题分析

DeepSeek + Claude Code: Thinking Block 兼容性问题分析

分析 Claude Code 使用 DeepSeek 模型时 extended thinking 模式下多轮对话触发 400 错误的根因,对比 OpenCode 的处理方式,以及社区解决方案。

语速

问题描述

在 Claude Code 中直接使用 DeepSeek 模型(如 deepseek-v4-flash)时,开启 extended thinking 后,多轮对话会触发 400 错误:

1
Bad Request: {"error":{"message":"The content[].thinking in the thinking mode must be passed back to the API.","type":"invalid_request_error","param":null,"code":"invalid_request_error"}}

根因分析

调用链

1
Claude Code → DeepSeek Anthropic 兼容端点 (https://api.deepseek.com/anthropic)

协议不兼容

根据 DeepSeek Anthropic API 兼容文档,兼容情况如下:

Message 字段支持状态
content[].thinking✅ Supported
content[].redacted_thinking❌ Not Supported

Claude Code 在 extended thinking 模式下的多轮对话中,会忠实地将上一轮返回的所有 thinking blocks(包括 redacted_thinking 类型)原样回传给 API。DeepSeek 不识别 redacted_thinking,因此报 400。

此外,DeepSeek 的 thinking block 格式与 Anthropic 原生协议存在差异,在 tool_use 场景下的回传逻辑也不完全兼容。

核心矛盾

  • Anthropic API 要求:extended thinking 模式下,content[].thinkingcontent[].redacted_thinking 必须原封不动回传
  • DeepSeek 兼容层:只支持 thinking,不支持 redacted_thinking
  • Claude Code 行为:按 Anthropic 协议硬编码,不区分目标端点类型

社区反馈

这是一个广泛存在的社区问题,几乎所有 CC 代理/路由项目都遇到了:

Issue项目标题
#1cc-useDeepSeek Thinking Mode Error: content[].thinking Must Be Passed Back
#878openclaudeDeepSeek V4: reasoning_content must be passed back (400) on tool_calls
#1355claude-code-routerCCR 代理 deepseek V4 思考时返回 400
#4543new-apiClaudeCode 接入 DeepSeek V4 遇到 400 reasoning_content 报错
#3559routerDeepSeek API Error 400 – Missing reasoning_content
#16748hermes-agentDeepSeek /anthropic: stripped thinking blocks cause HTTP 400 on replay
#2414cc-switchClaude 使用 cc-switch 配置 deepseek-v4-pro,无法识别字段
#174cc-haha/compact 命令在使用 DeepSeek API 时无法工作

DeepSeek 官方回应

零回应。 也没必要回应。

  • 首先,DeepSeek 没有公开的 API issue 仓库,所有反馈均发生在第三方项目中,无 DeepSeek 官方人员参与任何讨论。
  • 其次,是否将 Anthropic 作为标准来兼容,我想 DeepSeek 应该是犹豫的。

临时解决方案

  1. 关闭 extended thinking — 用 DeepSeek 时在 CC 中关闭 thinking 模式
  2. 使用代理过滤 — 在 CC 和 DeepSeek 之间加一层代理,过滤掉 redacted_thinking blocks
  3. 换模型 — 非 thinking 场景使用 DeepSeek,thinking 场景使用 Anthropic 原生模型

OpenCode 为什么没有这个问题?

OpenCode (opencode-ai/opencode) 在架构上天然规避了这个问题,并非专门"修复"。

关键在 internal/llm/provider/anthropic.goconvertMessages 方法(第 60-119 行):

  • 构建 assistant 消息时,只回传 TextContent(文本)和 ToolCall(工具调用)
  • 完全忽略 ReasoningContent(thinking 内容),不放入 messages
  • thinking 内容仅通过 stream 的 thinking_delta 事件在 UI 展示,不会回传给 API

对比 Claude Code 的行为:

Claude CodeOpenCode
thinking 回传✅ 忠实回传所有 thinking blocks(含 redacted_thinking)❌ 不回传 thinking blocks
架构原因遵循 Anthropic API 规范,要求原样回传自行管理对话状态,thinking 仅用于 UI 展示
DeepSeek 兼容性❌ 触发 400(redacted_thinking 不被识别)✅ 不受影响(根本不传 thinking)

结论:OpenCode 避开问题的方式是以不遵循 Anthropic extended thinking 规范为代价的。 这种做法对 DeepSeek 等第三方兼容端点友好,但如果未来需要 Anthropic 原生的 thinking 上下文保持能力,可能需要重新实现。

不回传 thinking blocks 是否会影响 DeepSeek 性能?

基本不会,原因:

  1. thinking blocks 是模型的内部 scratchpad,不是最终输出。对话历史里的文本回复和工具调用已经保留了关键决策和结论
  2. DeepSeek 的 reasoning 更接近 OpenAI 的模式——每轮独立生成,不像 Anthropic 那样强依赖跨轮回传来保持推理连贯性
  3. OpenCode 的大量实际使用也印证了这一点——社区用户在 OpenCode 中用 DeepSeek thinking 模式跑多轮对话,没有反馈过推理质量下降的问题

真正可能受影响的极端场景:超长多轮任务中,模型可能重复之前已经推理过的结论。但在大多数实际使用中影响可忽略。

相关的 Claude Code 原生 issue

CC 自身在 Anthropic 模型上也有类似的 thinking block 回传 bug(非 DeepSeek 特有):

Issue标题状态
#10199API Error 400 - Thinking Block Modification ErrorOpen (oncall)
#51985thinking block missing in multi-turn conversationsOpen
#20692thinking blocks order error on first tool useOpen (oncall)
#54482Thinking blocks stripped from context every turn (Opus 4.7)Open