DeepSeek Harness(dsh)是 DeepSeek AI 于 2026 年 8 月开源的 Agent 运行时框架,基于"Everything is a Plugin"架构,开源 6 天突破 16 万 Star。正因为架构灵活、配置层次多,初次上手时最常被问到的反而不是功能本身,而是各类连接错误、配置错误和兼容性报错。本文从官方文档(docs/user/guide/providers.md)和 GitHub Issues 提取所有已知报错,按出现频率从高到低排列,每种报错给出对应的诊断路径和修复命令——包括如何将七牛云 Token Plan 等自定义 OpenAI 兼容网关接入 dsh,并在 settings.yaml 中正确配置。


快速诊断:先看报错关键词

遇到问题先对报错关键词分类,不同关键词对应完全不同的根因:

报错关键词

最可能原因

MISSING_CREDENTIAL

API Key 未配置或环境变量未注入

UNKNOWN_MODEL

模型未添加到自定义提供方配置

401 Unauthorized

API Key 错误或权限不足

GET /models 返回 401

发现端点不支持,需手动填写模型

网关拒绝每个请求(key 正确)

请求格式与 OpenAI 不兼容

只有推理模型失败

developer role 被网关拒绝

图片在发送前被拒绝

模型未声明 image modality

SQLite 历史会话消失

rc.8 存储格式不兼容旧版本

取消生成后前缀丢失

rc.7 及以前的已知 bug,升级到 rc.8 修复

自定义网关调用失败 / 推理内容缺失

rc.7 已知 bug,升级到 rc.8 修复


第一类:API Key 相关报错

MISSING_CREDENTIAL

报错信息:连接时提示 MISSING_CREDENTIAL,或 Settings → Models 页面提示凭据缺失。

原因:dsh 的凭据不写在代码或 cordis.yml 里,而是通过两种方式之一注入:

  1. 通过 Web UI 的 Settings → Models 页面录入(推荐)

  2. 通过环境变量,在 settings.yaml 中用 apiKeyEnv: YOUR_ENV_VAR_NAME 引用

解决方法

方案 A(推荐):打开 Web UI → Settings → Models → 找到对应 Provider 卡片 → 填入 API Key → 保存。保存后 Key 存入 $DSH_HOME/.credentials.yaml,页面只展示脱敏描述符,不展示原始 Key。

方案 B(settings.yaml 环境变量引用):

# $DSH_HOME/settings.yaml
llm-pi-ai:
  providers:
    my-gateway:
      apiKeyEnv: QINIU_API_KEY    # ← 引用环境变量名,不是 Key 本身
      api: openai-completions
      baseURL: https://api.qnaigc.com/v1
      models:
        - id: deepseek-v4-flash
        - id: kimi-k3

然后在启动 dsh 之前设置环境变量:

export QINIU_API_KEY="sk-your-actual-key-here"
npx @deepseek-ai/dsh web

注意apiKeyEnv 填的是环境变量名(字符串),不是 Key 本身。如果写成 apiKey: sk-xxx,这种形式在当前版本不被支持——官方文档明确说 "Secrets are cordis-native: schemastery Config with env fallbacks, fed from cordis.yml via !!js process.env.MY_KEY. Never read ad-hoc key files in code."


401 Unauthorized(获取可用模型时)

报错信息:在 Settings → Models 点击"Fetch available models"时返回 401。

原因:dsh 通过调用 GET /v1/models(OpenAI 兼容端点)自动发现模型列表,部分提供方未开放此接口。

解决方法:不依赖自动发现,在 settings.yaml 中手动填写模型 ID

llm-pi-ai:
  providers:
    qiniu:
      apiKeyEnv: QINIU_API_KEY
      api: openai-completions
      baseURL: https://api.qnaigc.com/v1
      models:
        - id: deepseek-v4-flash
        - id: deepseek-v4-pro
        - id: kimi-k3
        - id: glm-5.3

手动添加的模型 ID 需与提供方实际支持的 model 字段完全匹配。


第二类:模型配置报错

UNKNOWN_MODEL

报错信息:发送请求时报 UNKNOWN_MODEL,或 Settings 中模型选择器显示"Select model"并阻止输入。

原因:有两种情况:

  1. 会话记录了已删除 Provider 的模型,找不到对应路由

  2. 自定义 Provider 中的 models 列表未包含该 model ID

解决方法

情况 1——历史会话找不到 Provider:重新在 Settings → Models 中添加同名 Provider,或选择新的可用模型开启新会话。

情况 2——models 列表缺失:打开 settings.yaml,在对应 Provider 的 models 块中追加缺失的模型 ID:

models:
  - id: deepseek-v4-flash
  - id: deepseek-v4-pro    # ← 追加此行

特殊情况:Provider ID 是永久性的(requests、saved sessions、model defaults 和 credential references 都使用它)。如果误删了 Provider,必须用完全相同的 Provider ID 重新添加,才能恢复旧会话与该 Provider 的关联;更改 Provider ID 会导致所有引用失效。


第三类:自定义网关请求被拒(Key 正确但仍报错)

这是最容易让人困惑的一类报错——API Key 和 Base URL 都对,但网关每次都拒绝请求。原因是 请求格式与 OpenAI 不完全兼容

网关拒绝每一个请求

诊断:先用 curl 直接测试,确认 Key 和端点本身没问题:

curl -s https://api.qnaigc.com/v1/chat/completions \
  -H "Authorization: Bearer $QINIU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "deepseek-v4-flash", "messages": [{"role": "user", "content": "hello"}], "max_tokens": 10}'

curl 能返回正常响应,但 dsh 仍报错 → 请求格式差异问题。

最常见的两个格式差异

  1. system prompt 使用 developer role:dsh 的推理模型默认把系统提示以 "role": "developer" 发出,部分网关不识别,直接拒绝。

  2. max_completion_tokens vs max_tokens:dsh 对推理模型用 max_completion_tokens,旧版格式只认 max_tokens

修复方法:在 settings.yaml 的 route 上加 compat 配置:

llm-pi-ai:
  providers:
    my-gateway:
      apiKeyEnv: GATEWAY_API_KEY
      api: openai-completions
      baseURL: https://gateway.example/v1
      compat:
        supportsDeveloperRole: false     # 禁用 developer role,改回 system
        maxTokensField: max_tokens       # 使用旧版字段名
      models:
        - id: my-model

只有推理模型失败,普通对话模型正常

原因:推理模型(如 deepseek-v4-pro 的 reasoning 档位)会将系统提示以 developer role 发出,部分网关对此报 400 或 422。

修复方法:在网关路由或特定模型上关闭 developer role:

# 整个路由统一关闭
compat:
  supportsDeveloperRole: false

# 或只对特定模型覆盖
models:
  - id: my-model                   # 普通模型,继承路由设置
  - id: my-reasoner                # 推理模型,单独覆盖
    compat:
      thinkingFormat: deepseek     # 使用 DeepSeek 的推理格式

compat按字段生效的:模型级配置覆盖路由级,路由级覆盖已安装 catalog 的默认值。不需要重复声明未修改的字段。


compat 开关被拒绝("no value" 错误)

报错信息:dsh 提示某个 compat 开关因没有值而被拒绝。

原因:YAML 中写了冒号但没有值,例如 supportsDeveloperRole:(等价于 null/空,被拒绝)。

修复:给每个开关显式赋值,或整行删除恢复默认:

# 错误写法
compat:
  supportsDeveloperRole:    # ← 冒号后为空,被拒绝

# 正确写法
compat:
  supportsDeveloperRole: false

第四类:多模态相关报错

图片在发送前被拒绝

报错信息:附加图片时 dsh 直接拒绝,提示模型不支持图片,且标注了具体模型名。

原因:手动录入的模型默认为纯文本(text-only)。dsh 无法向端点查询模态能力,必须在 settings.yaml 中手动声明。

修复方法:给自定义提供方的模型添加 input: [text, image]

llm-pi-ai:
  providers:
    my-gateway:
      apiKeyEnv: GATEWAY_API_KEY
      api: openai-completions
      baseURL: https://gateway.example/v1
      models:
        - id: text-only-model             # 纯文本,无需声明
        - id: vision-model
          input: [text, image]            # ← 声明支持图片

如果路由下所有模型都支持图片,可以在路由级设置 defaultInput 作为回退:

defaultInput: [text, image]    # 路由级回退,单个模型未声明时生效

注意:DeepSeek 官方的 chat-completions 路由是纯文本的,设置 input: [text, image] 不会让它实际支持图片——端点本身不处理图片,请求会被提供方拒绝。只对确实支持视觉输入的端点声明 image modality。


提供方拒绝了带图片的请求

原因:模型声明了 image 能力,但端点实际不支持。

修复:从 inputdefaultInput 中移除 image,并开启新会话——已附加图片的历史会话会在每次请求中重复发送该图片,必须新开会话才能彻底避开。


第五类:SQLite 和历史会话问题

升级到 rc.8 后历史会话消失

原因:rc.8 对 SQLite 后端做了不向下兼容的存储格式变更,rc.7 写入的数据 rc.8 无法读取。这是官方已知的 breaking change(见 rc.8 release notes)。

修复方案

  • 如果需要旧会话:降回 rc.7,手动导出(复制数据目录)后再升级。

  • 如果已升级无法回头:旧数据暂时无法恢复——官方尚未提供迁移工具,等待后续版本。

  • 预防:每次大版本升级前,先备份 $DSH_HOME 目录(SQLite 文件所在位置)。

检查数据目录位置

echo $DSH_HOME
# 未设置时默认为 ~/.dsh
ls ~/.dsh/

第六类:自定义网关接入示例(七牛云 Token Plan)

七牛云 Token Plan(qiniu.com/ai/plan)是 OpenAI 兼容协议的多模型网关,支持 DeepSeek、Kimi、GLM 等多款模型统一 Key 接入。以下是完整的 settings.yaml 配置示例:

# $DSH_HOME/settings.yaml
llm-pi-ai:
  providers:
    qiniu-token-plan:                       # Provider ID(永久,勿随意修改)
      apiKeyEnv: QINIU_TOKEN_PLAN_KEY       # 环境变量名,不是 Key 本身
      api: openai-completions               # OpenAI 兼容协议
      baseURL: https://api.qnaigc.com/v1   # 七牛云 Token Plan 端点
      compat:
        supportsDeveloperRole: false        # 推荐:部分推理模型需要关闭
        maxTokensField: max_tokens          # 兼容旧版 max_tokens 字段
      models:
        - id: deepseek-v4-flash
        - id: deepseek-v4-pro
        - id: kimi-k3
        - id: glm-5.3
        - id: minimax-m3

启动命令:

export QINIU_TOKEN_PLAN_KEY="sk-your-token-plan-key"
npx @deepseek-ai/dsh web

配置保存后,Settings → Models 的模型选择器中会出现上述模型,切换模型只需修改选择器,不需要重启 dsh 进程,变更在下一次请求生效。

配置验证

# 直接测试端点,确认 Key 和 baseURL 正确
curl -s https://api.qnaigc.com/v1/chat/completions \
  -H "Authorization: Bearer $QINIU_TOKEN_PLAN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "deepseek-v4-flash", "messages": [{"role": "user", "content": "test"}], "max_tokens": 5}' | python3 -m json.tool

返回包含 choices 字段的 JSON → 配置正确,可以放心写入 settings.yaml。


第七类:rc.8 修复的已知 bug(升级即解决)

以下问题在 rc.7 及更早版本存在,升级到 rc.8 后自动修复,无需额外配置:

问题

rc.8 修复说明

取消流式生成后,已展示的前缀在后续提问/分叉中丢失

已修复,前缀正确带入

自定义 OpenAI 兼容网关调用失败,推理内容(reasoning_content)缺失

适配器层加入了兼容性处理

图片载荷超限(多轮图片累积)导致请求失败

适配器层自动裁剪载荷

如果你遇到以上问题,直接升级到最新版本:

npx @deepseek-ai/dsh web

npx 每次运行都会拉取最新版本,无需手动指定版本号。


完整排查流程

遇到任何连接或配置问题,按以下顺序逐步排查:

  1. 看报错关键词 → 对照文章顶部的分类表,定位根因类型

  2. 直接 curl 测试端点 → 排除网络/Key/端点本身的问题

  3. 检查 settings.yaml 中的 compat 配置 → 99% 的"Key 对但请求被拒"都在这里

  4. 确认 models 列表 → 手动填写的模型 ID 必须与提供方完全一致

  5. 检查 dsh 版本npx @deepseek-ai/dsh web --version 确认版本,考虑升级到 rc.8

  6. 查看 GitHub Issues → github.com/deepseek-ai/deepseek-harness/issues 搜索具体报错文本


FAQ

Q:settings.yaml 修改后需要重启 dsh 吗?

模型配置(providers/models)修改后,dsh 会在下一次请求时自动生效,不需要重启服务。但如果修改的是启动参数或端口配置,需要重启。安全做法:改完 settings.yaml 后,在 Web UI 的 Settings → Models 页面刷新确认配置已被读取。

Q:Provider ID 能不能包含大写字母或特殊字符?

官方文档要求 Provider ID 使用小写字母。Provider ID 是永久的,会写入会话记录和凭据引用,改名的唯一方法是添加新 Provider 再删除旧的。建议命名格式:qiniu-token-planopenai-official(小写字母加连字符)。

Q:自定义 Provider 的模型能自动发现吗?

可以尝试:在 Settings → Models → Add a custom provider 填写 baseURL 和 Key 后,点击"Fetch available models"。这会调用 GET /v1/models 端点。返回 200 → 自动填充候选模型;返回 401/404 → 手动填写 model ID。大多数国内网关都支持 GET /v1/models,可以先试一试。

Q:rc.8 的 SQLite 格式变更会在后续版本修复向下兼容吗?

官方 release notes 中标注为"开发者预览阶段的已知取舍",暂无数据迁移工具。建议每次升级前备份 $DSH_HOME 目录,等待后续稳定版本提供迁移路径。

Q:dsh 支持同时配置多个 Provider 吗?

支持。settings.yaml 中 providers 块可以列多个 Provider,每个有独立的 apiKeyEnv、baseURL、models 配置。模型选择器中会同时展示所有已配置 Provider 的模型,可以按会话自由切换。


结语

DeepSeek Harness 的排错核心只有两步:先看报错关键词定位类型,再用 curl 直接验证 Key 和端点是否正常。大多数"配置正确但就是不工作"的问题,本质上都是 compat 配置缺失——supportsDeveloperRole: falsemaxTokensField: max_tokens 这两行能解决 80% 以上的自定义网关兼容性问题。rc.8 修复了多个自定义网关相关 bug,升级到最新版本是排错的第一步。

数据来源(均为官方渠道,2026-08-20):

  • providers 配置指南:github.com/deepseek-ai/deepseek-harness/blob/main/docs/user/guide/providers.md

  • rc.8 Release Notes:github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.0-rc.8

  • cookbook/adding-an-llm-adapter:github.com/deepseek-ai/deepseek-harness/blob/main/docs/cookbook/adding-an-llm-adapter.md


延伸阅读