问题描述
在 Claude Code 中直接使用 DeepSeek 模型(如 deepseek-v4-flash)时,开启 extended thinking 后,多轮对话会触发 400 错误:
| |
根因分析
调用链
| |
协议不兼容
根据 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[].thinking和content[].redacted_thinking必须原封不动回传 - DeepSeek 兼容层:只支持
thinking,不支持redacted_thinking - Claude Code 行为:按 Anthropic 协议硬编码,不区分目标端点类型
社区反馈
这是一个广泛存在的社区问题,几乎所有 CC 代理/路由项目都遇到了:
| Issue | 项目 | 标题 |
|---|---|---|
| #1 | cc-use | DeepSeek Thinking Mode Error: content[].thinking Must Be Passed Back |
| #878 | openclaude | DeepSeek V4: reasoning_content must be passed back (400) on tool_calls |
| #1355 | claude-code-router | CCR 代理 deepseek V4 思考时返回 400 |
| #4543 | new-api | ClaudeCode 接入 DeepSeek V4 遇到 400 reasoning_content 报错 |
| #355 | 9router | DeepSeek API Error 400 – Missing reasoning_content |
| #16748 | hermes-agent | DeepSeek /anthropic: stripped thinking blocks cause HTTP 400 on replay |
| #2414 | cc-switch | Claude 使用 cc-switch 配置 deepseek-v4-pro,无法识别字段 |
| #174 | cc-haha | /compact 命令在使用 DeepSeek API 时无法工作 |
DeepSeek 官方回应
零回应。 也没必要回应。
- 首先,DeepSeek 没有公开的 API issue 仓库,所有反馈均发生在第三方项目中,无 DeepSeek 官方人员参与任何讨论。
- 其次,是否将 Anthropic 作为标准来兼容,我想 DeepSeek 应该是犹豫的。
临时解决方案
- 关闭 extended thinking — 用 DeepSeek 时在 CC 中关闭 thinking 模式
- 使用代理过滤 — 在 CC 和 DeepSeek 之间加一层代理,过滤掉
redacted_thinkingblocks - 换模型 — 非 thinking 场景使用 DeepSeek,thinking 场景使用 Anthropic 原生模型
OpenCode 为什么没有这个问题?
OpenCode (opencode-ai/opencode) 在架构上天然规避了这个问题,并非专门"修复"。
关键在 internal/llm/provider/anthropic.go 的 convertMessages 方法(第 60-119 行):
- 构建 assistant 消息时,只回传
TextContent(文本)和ToolCall(工具调用) - 完全忽略
ReasoningContent(thinking 内容),不放入 messages - thinking 内容仅通过 stream 的
thinking_delta事件在 UI 展示,不会回传给 API
对比 Claude Code 的行为:
| Claude Code | OpenCode | |
|---|---|---|
| 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 性能?
基本不会,原因:
- thinking blocks 是模型的内部 scratchpad,不是最终输出。对话历史里的文本回复和工具调用已经保留了关键决策和结论
- DeepSeek 的 reasoning 更接近 OpenAI 的模式——每轮独立生成,不像 Anthropic 那样强依赖跨轮回传来保持推理连贯性
- OpenCode 的大量实际使用也印证了这一点——社区用户在 OpenCode 中用 DeepSeek thinking 模式跑多轮对话,没有反馈过推理质量下降的问题
真正可能受影响的极端场景:超长多轮任务中,模型可能重复之前已经推理过的结论。但在大多数实际使用中影响可忽略。
相关的 Claude Code 原生 issue
CC 自身在 Anthropic 模型上也有类似的 thinking block 回传 bug(非 DeepSeek 特有):
