跳过主要内容
全部文章
教程

修复 dsh 中的 UNKNOWN_TOOL 与 HTTP 400 网关报错

排查 DeepSeek Harness 接入 OpenAI 兼容网关(如通义千问 Qwen/DashScope)时的 UNKNOWN_TOOL、HTTP 400 developer role 报错与工具名被清空问题。

UNKNOWN_TOOLdeveloper role rejected (HTTP 400),以及工具调用返回时名字为空——这几种报错,几乎都是因为你接入的 OpenAI 兼容网关的实现方式,和 DeepSeek Harness 适配器预期的行为存在方言差异,而不是你的 prompt 或模型选择出了问题。排查思路是:先用官方 DeepSeek API 跑一遍同样的配置做对照,再用 --dump-config 查看最终生效的配置,然后逐项核对网关是否支持 dsh 依赖的特定 role 与流式行为。本文会带你走一遍这条排查路径,并覆盖本周 GitHub Discussions 里出现频率最高的几个网关相关问题。

本文是 在 DeepSeek Harness 中使用 OpenAI、Anthropic 或任意 OpenAI 兼容 API 的姊妹篇,那篇讲的是如何配置自定义或 OpenAI 兼容 provider;本文接着往下讲——provider 已经配好、dsh 也能连上了,但一旦真正跑起 Agent 会话,工具调用就开始报错。

为什么会出现这类问题

"OpenAI 兼容"描述的是一种线上协议格式,不是行为完全一致的保证。自建代理、第三方聚合网关、以及国内厂商(如阿里云的 Qwen/Bailian,即 DashScope)各自只实现了 OpenAI API 表面的一个子集,而最容易出现分歧的部分,恰恰是 Agent harness 最依赖的那几处:接受哪些消息 role、流式工具调用分片的结构如何组织、以及工具的 name 字段是在每个续传分片里都重复携带,还是只在第一个分片发送一次。dsh 的 llm-deepseek 适配器是按官方文档记录的 OpenAI 方言来构建的;网关只要在这几处有一点点偏差,就会产生看起来像 harness bug、实际是协议不匹配的报错。

症状清单

症状可能的根因修法
会话中途报 UNKNOWN_TOOL网关在 tool_calls 里返回的工具名,和 dsh 在请求里声明的名字对不上——被截断、重新编码,或规范化方式不同先试一次非流式调用,确认名字是否完整往返;如果对不上,说明网关在改写工具名,需要网关侧修复
developer role rejected (HTTP 400)网关的 OpenAI 兼容实现不接受较新的 OpenAI 方言消息格式里用来取代 systemdeveloper role查网关自己的 API 文档确认支持哪些 role;dsh 没有自动降级到 system 的机制,网关不加支持就会一直被拒
工具调用名返回为空流式 tool_calls 被拆成多个分片,网关只在第一个分片带上 name 字段,续传分片不重复携带——Discussion #3767 有此报告社区变通方案:如果网关支持非流式模式,对工具调用密集的会话关闭流式;或换一个已知会在分片间保留 name 的网关/代理

三种症状指向同一个根源:OpenAI 兼容实现之间在 role 支持、流式工具调用分片语义、以及工具名传递方式上存在差异。它们都不是单靠改 dsh 侧配置就能解决的配置错误——但通常几分钟内就能确认自己踩到的是哪一种。

排查步骤

按顺序逐条排查,而不是凭感觉猜修法:

  1. 先用官方 DeepSeek API 验证配置本身没问题。 保持其他一切不变,把同一个会话指向 DeepSeek 官方 endpoint(或另一个已知可用的目录内置 provider)。如果工具调用在那边能成功,问题就出在你的网关实现上,而不是 prompt、工具或 bundle 配置。

  2. 导出最终生效的配置。 执行:

    dsh --profile web --dump-config
    

    这会打印完整合并后的配置树——bundle 默认值、profile 自己的 cordis.patch.yml$DSH_HOME/cordis.patch.yml,以及任何 --patch 覆盖层——让你确认 dsh 实际在用的 provider、Base URL 和模型条目,而不是你以为自己配置的那样。

  3. 检查 provider 说的是哪种 API 方言。 自定义 provider 会在 settings.yaml 里声明 api: openai-completions(或其他受支持的线上格式)。确认你的网关实际实现的是 chat completions,而不是 Responses 风格的 API 或某个不完整的子集——这里如果对不上,会产生本文覆盖的这类格式错误报错。

  4. 直接对网关核实 role 和流式支持情况。 问清楚它是否接受 developer role,流式 tool_calls 是否在每个分片都重复携带 name 字段还是只在第一个分片带。查网关厂商文档,或绕开 dsh 直接对 endpoint 发一次原始 curl,通常比在会话里反复试错更快得到答案。

  5. 尝试切换流式开关,或换一个 endpoint 路径,进一步缩小范围。 如果网关同时提供流式和非流式的补全路径,两边都测一遍,可以判断问题究竟出在流式分片本身,还是请求本身就有问题。

回顾几个常见配置错误

在认定自己踩到的是网关方言差异之前,先排除 配置你的 DeepSeek API Key 与模型在 DeepSeek Harness 中使用 OpenAI、Anthropic 或任意 OpenAI 兼容 API 里讲过的几种更常见的配置失误:

  • MISSING_CREDENTIAL——provider 没有解析到可用的 key;在 Settings → Models 里设置,或通过环境变量提供。
  • UNKNOWN_MODEL——选中的模型 ID 不在任何已配置 provider 的模型列表里;添加到自定义 provider 的 models: 条目,或者对目录内置 provider 用 modelOverrides
  • 附图在发送前就被拒绝——settings.yaml 里该模型条目缺少 input: [text, image];未声明的模型默认按纯文本处理。

这几种会产生各自独立、明确标注的报错信息,值得优先排除——它们是你这边的配置失误,不是网关方言问题,修法也只是一行 YAML 改动,而不需要绕行方案。

国内网关个案:阿里云 Qwen / Bailian(DashScope)

本周社区反馈指向阿里云 Qwen 和 Bailian(DashScope)的 OpenAI 兼容端点存在兼容性问题,表现正是上面的 UNKNOWN_TOOL 和 HTTP 400 role 拒绝症状。截至 2026 年 8 月 21 日,这仍是社区报告的现象,DeepSeek Harness 官方或阿里云官方均未就根因给出正式确认——后续版本可能会在任意一方修复。如果你正用这类网关,建议先走一遍上面的排查步骤,确认自己踩到的是不是这一类已被他人报告过的问题,再考虑提 issue。

另一个相关但不同的问题——网关不是不兼容而是根本连不上——见 Discussion #3550:一位用户通过国内厂商访问 DeepSeek V4 Flash 时没有直连的网络路径,最终通过社区插件 dsh-llm-proxy 让 dsh 走本地代理绕开。这是网络可达性的变通方案,不是上面那类协议方言问题的修法——值得了解,但如果你的实际症状是能连上网关却报 UNKNOWN_TOOL,就不需要去装代理插件。

一个相关但容易混淆的安装期坑

在排查网关配置的过程中,你也可能碰到一个无关但容易混为一谈的问题:当某个插件的 package.json 带有字节顺序标记(BOM)时,dsh plugin add 会直接因为 JSON.parse 崩溃,见 Discussion #2798。这是安装期的解析 bug,和网关或模型 provider 没有关系——如果你在同一次排查过程中装插件时碰到,可以看 修复 DeepSeek Harness 插件安装报错

什么时候该报告 bug

deepseek-ai/deepseek-harness 仓库的 GitHub Issues 已关闭——唯一的反馈渠道是 GitHub Discussions。如果你已经走完上面的排查步骤,工具调用在自己的网关上仍然跑不通,建议提一条 Discussion 而不是找 Issue,并附上:

  • dsh --profile web --dump-config 的完整输出(记得脱敏 API key 和其他密钥)。
  • 你所用网关或 provider 的名字(Qwen/Bailian、某个具体代理产品、自建实现等)。
  • 同一个会话在官方 DeepSeek API 或另一个目录内置 provider 上是否能成功。
  • 是否开启了流式,关闭流式后症状是否变化。

这几项信息通常足够让维护者或其他遇到同类问题的用户快速判断你踩到的是不是已知的网关方言缺口,还是一个新问题。

FAQ

UNKNOWN_TOOL 是 DeepSeek Harness 自身的 bug 吗?

不完全是——它几乎总是因为 dsh 发送的工具名和网关在 tool_calls 里返回的名字对不上,而这取决于该网关具体是怎么实现 OpenAI 兼容 API 的。先用官方 DeepSeek API 跑同一个会话做确认;如果那边正常,变量就在网关上。

为什么我的网关会报 "developer role rejected (HTTP 400)"?

一些 OpenAI 兼容网关只实现了较旧的 system role,还没加上较新的 OpenAI 方言消息格式里用来取代它的 developer role。dsh 不会自动降级到 system——要么等网关加支持,要么这类工作负载换一个别的 provider。

工具调用能跑,但返回的工具名是空的,这是怎么回事?

这个问题在会把流式 tool_calls 拆成多个分片、但只在第一个分片带 name 字段(续传分片不重复携带)的网关上被专门报告过——见 Discussion #3767。如果你的网关支持非流式路径,目前最可靠的变通方案就是关闭流式。

阿里云 Qwen/Bailian 的兼容性问题官方确认了吗?

没有——截至 2026 年 8 月 21 日,这仍基于 GitHub Discussions 里的社区报告,DeepSeek Harness 或阿里云任何一方都没有给出正式的根因确认。把它当作一个值得排查确认的已知现象,而不是板上钉钉的诊断结论,后续版本任何一方都可能修复它。

网关兼容性 bug 应该去哪里报告?

仓库的 GitHub Issues 已关闭;改用 GitHub Discussions,并附上你的 --dump-config 输出和网关名字,方便他人确认是否命中已知问题。

Next steps

如果还没配完初始 provider,先看 在 DeepSeek Harness 中使用 OpenAI、Anthropic 或任意 OpenAI 兼容 API;凭据存储细节见 配置你的 DeepSeek API Key 与模型。网关报错之外更广泛的安装/运行问题,见 DeepSeek Harness 故障排查;在断定网关报错是新问题而非版本相关之前,先看一眼 DeepSeek Harness 升级指南。到 模型与 Provider 浏览更多 provider 与网关相关插件,或在 全部插件 里搜索网关专用工具。