DeepSeek Harness 上手实录:从启动 Web UI 到组装自己的 Agent

DeepSeek Harness 的 README 很短,直接运行只需要一条命令:

bash 复制代码
npx @deepseek-ai/dsh web

但如果只是启动页面、填上 API Key,然后把它当成另一个聊天工具,会错过这个项目最有价值的部分。

这篇不重复文档目录,而是走一遍真正的使用路径:启动、配置模型、选择工作区、理解会话,再创建自己的 Profile。

先把项目跑起来

直接体验可以使用 npx

bash 复制代码
npx @deepseek-ai/dsh web

需要研究源码或开发插件时,建议使用源码方式:

bash 复制代码
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness

corepack enable
pnpm install
pnpm run build
pnpm dsh web

当前源码要求 Node.js ^22.19.0 || >=24.0.0

服务默认监听:

text 复制代码
http://127.0.0.1:3080

我本地构建时,安装过程会提示 Linux 原生包不支持 macOS,这属于平台选择警告。只要 pnpm run buildpnpm dsh --help 正常通过,就不代表安装失败。

页面打开后,为什么输入框不能用

Harness 会把启动命令所在目录作为默认文件系统位置,但 Web UI 不会直接选中它。

需要点击"选择工作区",添加并选中项目目录。没有选中工作区时,输入框会保持禁用。

这个设计看起来多了一步,实际是在明确 Agent 的文件系统作用范围。它不会因为服务从某个目录启动,就默认允许新会话直接操作该目录。

选好工作区后,可以先执行一个只读任务:

text 复制代码
Summarize this repository and identify its main packages.

确认读取、命令执行和审批链路都正常后,再进行写文件任务。

API Key 保存在哪里

在"设置 → 模型"中添加 DeepSeek API Key 后,模型配置会立即生效,不需要重启服务。

Harness 把凭据和普通配置分开保存:

text 复制代码
$DSH_HOME/.credentials.yaml
$DSH_HOME/settings.yaml

前者保存凭据,后者保存 Provider、模型和凭据引用。

Web 页面保存成功后只会拿到脱敏描述,不会重新获取明文密钥。这比把 API Key 混在普通 JSON 配置里更适合长期运行。

如果使用环境变量,也可以在启动 Headless Agent 时提供:

bash 复制代码
DEEPSEEK_API_KEY=your_key \
pnpm dsh --profile headless "summarize this workspace"

真实项目里不要把 Key 写进 Patch、仓库配置或 Shell 脚本。

配置自定义模型时有两个坑

Harness 支持目录 Provider,也支持 OpenAI 兼容网关和自建服务。

自定义 Provider 通常需要:

yaml 复制代码
llm-pi-ai:
  providers:
    my-gateway:
      apiKeyEnv: GATEWAY_API_KEY
      api: openai-completions
      baseURL: https://gateway.example/v1
      models:
        - id: my-model

第一个坑是 Provider ID。

Provider ID 会写进会话日志、默认模型和凭据引用。一旦投入使用,就不适合原地重命名。正确做法是新增一个 Provider,再迁移并删除旧配置。

第二个坑是多模态能力。

手动添加的模型默认按纯文本模型处理。如果模型支持图片,需要显式声明:

yaml 复制代码
models:
  - id: vision-model
    input: [text, image]

这只是对端点能力的声明,不会验证服务端是否真的支持图片。声明错误后,最终仍会被 Provider 拒绝。

而且图片已经进入会话日志时,仅修改配置未必能解决问题。后续请求可能继续从日志派生出同一附件,此时应开启一个不包含该图片的新会话。

Web 和 Headless 不是两套产品

Web 模式适合交互式使用:

bash 复制代码
pnpm dsh web

Headless 模式适合自动化任务:

bash 复制代码
pnpm dsh --profile headless "inspect the repository"

两者共享同一套底层能力,只是加载的 Bundle 不同。

Web Profile 增加了服务器、前端和交互能力;Headless Profile 增加一次性任务运行器,不需要浏览器和服务器。

这也是 Profile 的核心用途:同一套能力可以被组合成不同产品形态。

不要直接改源码,先学会 Patch

假设我们有一个本地插件:

ts 复制代码
import type { Context } from '@deepseek-ai/cordis'

export const name = 'hello-plugin'

export function apply() {
  console.log('hello plugin loaded')
}

可以创建一个 cordis.yml

yaml 复制代码
- insert:
    - id: hello
      name: '/absolute/path/to/my-plugin.ts'

然后叠加到 Web Profile:

bash 复制代码
pnpm dsh web --patch ./scratch-plugin/cordis.yml

这比直接修改内置 Bundle 更适合实验,因为 Patch 只在本次启动中生效。

查看最终结果:

bash 复制代码
pnpm dsh --profile web --dump-config

--dump-config 很重要。Profile、Home 配置和多个 Patch 同时存在时,不要靠脑子推导最终配置,直接查看组装结果。

创建一套自己的 Profile

如果某组插件需要长期使用,可以创建独立 Profile:

bash 复制代码
dsh plugin --profile review add your-review-bundle
dsh --profile review --dump-config
dsh --profile review

Profile 会保存在:

text 复制代码
$DSH_HOME/profiles/review/
├── package.json
└── cordis.patch.yml

package.json 记录依赖和 Bundle 顺序,cordis.patch.yml 保存当前 Profile 的本地覆盖。

删除插件时使用:

bash 复制代码
dsh plugin --profile review remove your-review-bundle

这样可以维护多套用途不同的 Agent:

text 复制代码
web       日常交互
headless  自动化任务
review    只读代码审查
writer    文档与内容处理
sandbox   受限命令执行

真正的权限隔离仍然要依靠文件系统、进程和 Sandbox Provider,不能只靠 Profile 名称。

会话不是一组聊天消息

Harness 会把 Turn、Step、模型输出和 Tool 调用写成会话事件。

这会影响几个日常操作:

  • 修改默认模型主要影响新会话
  • 已发送过请求的会话保留自己的模型记录
  • Tool Call 和结果可以回放
  • 会话可以恢复或 Fork
  • UI 和模型上下文来自同一日志

所以遇到奇怪的历史行为时,不要只看当前 Settings,还要考虑会话日志中已经记录了什么。

权限控制发生在哪里

模型生成 Tool Call 后,不会直接碰文件系统或进程:

text 复制代码
模型输出 Tool Call
→ tools/pre-execute
→ 权限与审批
→ Tool execute
→ 文件系统或进程 Provider
→ tools/post-execute
→ 写入会话日志

这条链路比"在系统提示词里告诉模型不要乱删文件"可靠得多。

我更建议按用途拆 Profile:

  • 阅读代码时只提供读取能力
  • 修改代码时再开放写入
  • Shell 和网络分别授权
  • 不可信仓库使用 Sandbox Provider
  • 第三方插件锁定版本或 Commit SHA

模型的自律不是安全边界,Provider 和策略才是。

常用命令速查

bash 复制代码
# 启动 Web UI
pnpm dsh web

# 查看参数
pnpm dsh web --help

# 查看最终插件树
pnpm dsh --profile web --dump-config

# 临时加载 Patch
pnpm dsh web --patch ./extra.cordis.yml

# 运行一次 Headless 任务
pnpm dsh --profile headless "inspect this repository"

# 安装 Bundle
dsh plugin --profile demo add <package>

# 删除 Bundle
dsh plugin --profile demo remove <package>

上手 DeepSeek Harness 的关键,不是记住多少命令,而是建立一个认识:

你启动的不是固定 Agent,而是一套由 Profile、Bundle、Plugin 和 Patch 组合出来的运行时。

理解这一点后,后面的插件开发就顺了。

相关推荐
纯爱掌门人2 小时前
给 DeepSeek Harness 开发功能:别急着写 Tool,先找对扩展层
agent·deepseek
JaydenAI2 小时前
[基于OpenEvals的自动化评估-10]针对Agent对话的评估[上篇]
ai·langchain·agent·evaluation·openevals
纯爱掌门人2 小时前
我把 DeepSeek Harness 源码跑了一遍,终于看懂了它的“一切皆插件”
agent·deepseek
kyriewen2 小时前
DeepSeek Harness开源第一天我就上手了——和Claude Code的差距比想象中大
前端·ai编程·deepseek
张彦峰ZYF2 小时前
LangGraph 深入理解 ReAct:让 AI Agent 真正学会「边想边做」
人工智能·llm·agent·react·langgroup
梦想很大很大2 小时前
如果有一个本地优先的 Workflow 工具,你们团队会愿意用吗?
python·agent·workflow
302wanger3 小时前
聊天记录翻到烦,我让 DeepSeek Harness给自己写了个插件
deepseek
阿里云大数据AI技术3 小时前
AI Search+ES 9.4.X最佳实践:“更快、更准、更安全的企业级搜索引擎”"为AI Agent提供坚实底座”
人工智能·elasticsearch·agent
特立独行的猫A3 小时前
DeepSeek Harness(dsh)插件开发实战:从零实现一个会话导出插件
deepseek