DSH redacted_thinking 兼容性
DeepSeek Harness redacted_thinking:多步工具调用兼容
- 作者
- DeepSeekAgent.io 编辑部
- 发布
- 更新
在 Anthropic 兼容协议下接入 DeepSeek 模型时,多步工具调用可能在第二轮突然中断。社区复现中,第一步 Tool Call 正常完成,模型继续响应时返回了 redacted_thinking 内容块,DSH 适配器随后抛出 UNSUPPORTED_CONTENT,提示 DeepSeek Messages 不支持该响应块。
问题的关键不在工具本身,也不在是否打开可见推理。redacted_thinking 是 Anthropic 协议为不可展示的推理内容准备的块类型,客户端需要把它作为不透明数据保存并在后续消息中按协议回传。
为什么第一步成功、第二步失败
第一次请求尚未携带上一轮的完整 Assistant 内容,模型可以正常产生 tool_use。工具结果写回后,第二次请求进入多步链路,需要带上前一轮的内容块。网关或模型返回 redacted_thinking 时,适配器的块分派只认识 text、thinking 与 tool_use,默认分支便将它当作未知内容抛错。
因此,表面症状是“工具调用到第二步停了”,实际故障点位于响应内容块的协议映射。切换 reasoningEffort 为 none 或 high 都可能复现,因为这不是界面是否展示思考文本的开关问题。
redacted_thinking 应该怎样处理
这种块不能被转换成普通文本,也不应在日志或 UI 中展开。兼容层需要满足三件事:
- 接受:解析器识别该块,不因未知分支中止整个响应;
- 保留:原样保存协议要求回传的字段,避免改写签名或块顺序;
- 隔离展示:用户界面不显示受保护内容,调试日志也只记录类型和位置。
如果下游 DeepSeek Messages 数据结构无法表达该块,适配器可以将它保存在专用的 opaque 元数据中,并在 Anthropic 协议下一轮请求时恢复。简单丢弃是否安全,取决于网关对签名和上下文连续性的要求;默认做法应优先保持往返一致性。
如何复现和定位
建立一个至少需要两次工具调用的最小任务,并保存以下材料:
- 使用的 DSH、Provider 插件与网关版本;
- 模型 ID、协议类型和推理档位;
- 第一轮响应块的类型顺序;
- Tool Result 写回后的第二轮原始块类型;
- 适配器错误栈中处理块的函数与索引。
如果第一步稳定成功、第二步在相同块类型处失败,就不必继续更换工具或扩大超时。应直接审查协议适配器的联合类型与默认分支。网关经过 Bifrost 等转换层时,还要确认是上游原本返回该块,还是中间层将其他推理内容映射成了 redacted_thinking。
修复后的回归测试
兼容层更新后,至少需要覆盖:
text → tool_use → tool_result → text;thinking → tool_use;redacted_thinking → tool_use;- 多个内容块交错及多个 Tool Call;
- 响应保存、Session 重放和下一轮回传;
- 日志、导出与 UI 不泄露受保护内容。
只验证“不再抛错”还不够。第二轮必须能继续调用工具,Session 重开后也要维持相同的块顺序与上下文。
如果遇到整轮固定等待而非明确的 UNSUPPORTED_CONTENT,可转到每轮固定 30 秒的事件时间线分析。两类问题应依据事件与错误码分开处理。
参考资料
- redacted_thinking 导致多步工具调用中断的社区复现
- Anthropic Extended Thinking 文档
- DeepSeek Harness v0.2.1-rc.3 Release
常见问题
关闭 reasoningEffort 就能避开吗?
不一定。社区案例在不同推理档位都能复现,决定因素是协议响应中是否出现适配器未处理的块类型。
能把 redacted_thinking 转成普通文本吗?
不应这样做。它是不可展示的不透明协议内容,转换会破坏隐私边界和可能的签名要求。
为什么错误常在第二次 Tool Call 出现?
多步链路需要保存并回传上一轮 Assistant 内容,协议中此前未覆盖的块类型会在这时进入适配器的完整往返路径。