DeepSeek Harness 实践指南:从安装到自写插件,吃透「一切皆插件」

目录
- 1. 先建立正确预期
- 2. 30 分钟跑通:安装与首次配置
- 3. 四种模式怎么选(实战决策)
- 4. 「一切皆插件」落到工程上是什么
- 5. 实战:写一个模型可调用的工具插件
- 6. 挂载、安装与调试清单
- 7. 权限、轨迹与日常工作流
- 8. 常见坑与排错表
- 9. 总结与下一步
- 参考链接
1. 先建立正确预期
官方把 Agent 拆成一句公式:
Agent = Model + Harness
- Model:负责推理、规划、生成工具调用
- Harness:负责读文件、跑命令、管会话、做沙箱、调度子 Agent、把结果写回日志
DeepSeek Harness 的口号是 Everything is a Plugin(一切皆插件)。
和常见 Coding Agent 的差别在于:
| 类型 | 你能改什么 | 典型产品感 |
|---|---|---|
| 成品 Coding Agent | 外围 Skill / MCP / 少量 hooks | 开箱即用,黑盒多 |
| DeepSeek Harness | 模型适配、工具、会话、沙箱、甚至 Agent Loop / UI | 乐高底座,毛坯感更强 |
所以:
- 想「打开就能写代码」→ 先用 标准模式,别一上来创造模式
- 想「改运行时、写插件、做内部 Agent 平台」→ 这才是 dsh 的主场
- 它目前是 开发者预览版,官方明确会有破坏性变更;适合学习、试点、自托管实验,不建议一上来绑生产关键路径
项目入口:
- 官网:https://www.deepseek.com/harness/
- 仓库:https://github.com/deepseek-ai/deepseek-harness
- 文档站:https://deepseek-harness.github.io/deepseek-harness/
2. 30 分钟跑通:安装与首次配置
2.1 环境要求
- Node.js:官方要求较新(实践中建议 22.19+ 或 24+)
- 操作系统:Linux / macOS / Windows 均可;涉及强沙箱能力时,Linux / WSL 更稳
- 一个可用的 模型 API Key(默认 DeepSeek 开放平台)
- 一个可丢弃的练习目录当工作区(别直接指向生产仓库)
先检查 Node:
node -v
npm -v
2.2 最快启动(推荐新手)
npx @deepseek-ai/dsh web
成功后本地 Web UI 默认在:
http://127.0.0.1:3080
首次会看到开发者预览声明,点继续即可。
2.3 源码方式(准备写插件时用)
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web
源码方式的好处:能直接读 docs/、本地 --patch 插插件、对照 cookbook。
2.4 首次必做的 5 件事
- 填 API Key
设置 → 模型;也可先设环境变量DEEPSEEK_API_KEY再启动。 - 选工作区
例如:
mkdir DeepSeekProjects
在 UI 里把该目录加为 workspace。不选工作区,很多文件/命令能力等于没边界。
3. 选模型
Flash 适合轻任务;复杂多步规划更常上 Pro 档。
4. 选模式
新手直接 标准模式。
5. 确认权限
日常推荐 workspace-write:只在工作区写文件,越界操作会触发审批。danger-full-access 名字已经说明风险,练习阶段别开。
2.5 第一条验证任务
把下面丢给 Agent,验证「读盘 + 写文件 + 给预览说明」整条链路:
请在当前工作区创建一个简单待办网页:
1. 使用 HTML/CSS/JS
2. 可添加任务、勾选完成
3. 风格简洁,适配手机
4. 完成后列出生成文件,并说明如何本地打开预览
能稳定创建文件并解释结果,说明基础环境 OK。
2.6 Headless:塞进脚本/CI
dsh --profile headless "run the tests and summarize failures"
一次性跑完、打印最终答案后退出,适合批处理。
3. 四种模式怎么选(实战决策)
先记住一句:四种模式不是等级,而是四套插件模板(preset)。
同一套 Harness 宿主,装入不同插件组合,就长成不同「形态」。

| 模式 | 你实际得到什么 | 什么时候用 |
|---|---|---|
| 标准 Standard | 文件编辑、Shell、检索、Skills、计划、目标、子 Agent、工作流 | 日常开发、陌生任务探索 |
| PTC / Code | 标准能力 + Code Mode SDK:模型写 TypeScript,一次 run_code 组合多步工具 |
路径/参数已稳定的重复流程,想压缩工具往返 |
| 极简 Minimal | 持久 Bash + 文件编辑器;提示词极短;少附加能力 | 模型基准对比、控制变量实验 |
| 创造 Creator | 标准能力 + 检查 Cordis 运行时、内存试验插件、创作 preset | 学插件系统、改装 Agent 自己 |
实战选型口诀
- 陌生任务 → 标准
- 流程已跑通、工具往返很碎 → 再试 PTC
- 只想比模型裸 Agent 能力 → 极简
- 要改装工具/预设 → 创造
PTC 的真实体感(避免踩预期坑)
- PTC 不是「自动更快」:模型要先写出正确的编排程序
- 路径规则写错(例如 Glob 写法不符合 SDK 约定)会空跑一轮
- 第一次探索陌生仓库,多数人用标准更省心;稳定后把重复链路迁到 PTC 更划算
4. 「一切皆插件」落到工程上是什么
4.1 Cordis:只做三件事的内核
底层是 Cordis 插件框架。内核几乎不做业务,只负责:
- 加载 / 卸载插件
- 按
inject管理依赖 - 用可逆 effect 回收副作用
因此:
- 模型适配器是插件
- 工具注册表是插件
- 会话日志是插件
- Agent Loop 也是插件
- Web UI 也是插件
扩展方式不是 fork 主仓库改 loop,而是:旁挂插件 + 订事件 + 改配置组合。
4.2 运行中的 dsh = 一棵插件树
启动时从空配置开始,按层叠加:
- Profile 声明的 Bundles(如
dsh-base→dsh-web-app) - Profile 自己的
cordis.patch.yml - Home 级
$DSH_HOME/cordis.patch.yml - 命令行
--patchoverlay(最高优先,适合临时调试)

想看清本机真实装了什么:
dsh --profile web --dump-config
打印出来的每一行,理论上都能被你的 patch 按 id 替换。
注意:patch 是整行替换 config,不是深合并。只改一个字段时,别把其它必要字段覆盖丢了。
4.3 五个必须会的 Cordis 词
| 概念 | 实践含义 |
|---|---|
| 插件 | 导出 apply(ctx) 的模块(也可对象/类) |
Context ctx |
服务仓库:ctx.tools / ctx.llm / ctx.sessions… |
| inject | 硬依赖声明;服务没就绪就 PENDING,不瞎跑 |
| effect | 注册即带 disposer;卸载自动撤销 |
| 事件 | 扩展点:emit 观察、waterfall 拦截改写(记得 next()) |
4.4 能力 seam:为什么换一个 Provider 能搬整条链路
可替换能力通常拆三角色:
- Service Definition:接口与事件词汇(如 shell 能力定义)
- Service Provider:具体实现(本地 bash / 远程沙箱…)
- Consumer:面向模型的工具(
dsh-tool-bash)
你换 Provider,Consumer 仍调同一接口——这就是「一切皆插件」在工程上的可替换性,而不是只会在外围挂 MCP。
4.5 Session Log:模型可见 ⇔ 已记录
会话不是随便一份消息数组,而是 仅追加的事件日志。
系统提示、工具调用、结果、注入上下文,最终都要能从日志重建。
Trajectory 视图就是这条事件流的「黑匣子回放」,排错极有用。
5. 实战:写一个模型可调用的工具插件
目标:做一个 greet 工具,让模型在对话里真正调用它。

以下路径假设你已 clone 源码仓库,并完成
pnpm install/pnpm run build。
5.1 建临时插件目录
mkdir -p scratch-plugin/src
5.2 最小插件骨架(先证明能加载)
scratch-plugin/src/my-plugin.ts:
import type { Context } from '@deepseek-ai/cordis'
export const name = 'hello-plugin'
export function apply(ctx: Context) {
console.log('[hello-plugin] plugin loaded!')
}
要点:
- 函数插件请用具名导出
export function apply/export const inject - 不要「默认导出 + 具名 inject 混用」——Loader 可能丢掉
inject元数据,表现为「装上了但不依赖、行为诡异」
5.3 用 patch 插入本地插件
先在仓库根目录拿到绝对路径,再写 scratch-plugin/cordis.yml:
- insert:
- id: hello
name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts'
启动:
pnpm dsh web --patch ./scratch-plugin/cordis.yml
终端出现 [hello-plugin] plugin loaded! 即挂载成功。
5.4 升级为真正的 Tool
替换为:
import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'
export const name = 'greet-tool'
export const inject = ['tools']
export function apply(ctx: Context) {
ctx.tools.register(defineTool({
name: 'greet',
description: 'Greet someone by name. Use when the user asks to greet.',
parameters: {
name: {
type: 'string',
required: true,
description: 'The name to greet',
},
},
output: {
schema: { type: 'string' },
render: (_args, value) => [{ type: 'text', text: value }],
},
async execute(args) {
return `Hello, ${args.name}!`
},
}))
}
重启同样的 --patch 命令,在 Web UI 说:
请使用 greet 工具问候 Ada
模型应发起 greet,并拿到 Hello, Ada!。
5.5 这段代码为什么「像官方」
inject: ['tools']
保证ctx.tools就绪后再apply。defineTool
参数 schema 自动校验;execute里拿到的 args 与 schema 一致。- 只返回规范值
output.schema声明返回形态;render负责变成模型可见文本。 - 注册可逆
register附着在插件 fiber 上,卸载/HMR 时工具会从注册表消失。 - schema 自动进提示词组装
模型「看得到」这个工具,不需要你手写进 system prompt。
5.6 给插件加可配置项(部署期参数)
可调参数不要写死,做成 Config:
import type { Context } from '@deepseek-ai/cordis'
import Schema from '@deepseek-ai/schemastery'
import { defineTool } from '@deepseek-ai/dsh-tools'
export const name = 'greet-tool'
export const inject = ['tools']
export interface Config {
greeting: string
}
export const Config: Schema<Config> = Schema.object({
greeting: Schema.string().default('Hello'),
})
export function apply(ctx: Context, config: Config) {
ctx.tools.register(defineTool({
name: 'greet',
description: 'Greet someone by name.',
parameters: {
name: { type: 'string', required: true, description: 'The name to greet' },
},
output: {
schema: { type: 'string' },
render: (_args, value) => [{ type: 'text', text: value }],
},
async execute(args) {
return `${config.greeting}, ${args.name}!`
},
}))
}
在 patch 行里带 config.greeting,即可不改代码切换文案。
配置非法应在加载期直接失败(fail loud),不要运行时静默怪行为。
5.7 需要外部资源时:ctx.effect
定时器、连接池等必须留下 disposer:
export function apply(ctx: Context) {
ctx.effect(() => {
const timer = setInterval(() => {
console.log('heartbeat')
}, 5000)
return () => clearInterval(timer)
})
}
插件卸载、依赖服务消失、HMR 重载时,清理函数会按栈逆序执行。
5.8 进阶:用事件做权限门(钩子插件)
不新增工具、只想拦截调用时,挂 tools/pre-execute:
import type { Context } from '@deepseek-ai/cordis'
import type { PreToolDecision, ToolExecution } from '@deepseek-ai/dsh-tools'
async function isAllowed(_exec: ToolExecution): Promise<boolean> {
return true
}
export const name = 'permission-gate'
export function apply(ctx: Context) {
ctx.on('tools/pre-execute', async (exec, next): Promise<PreToolDecision> => {
if (!(await isAllowed(exec))) {
return { kind: 'deny', reason: 'Denied by local policy.' }
}
return next()
})
}
waterfall 铁律:要放行必须 next()。忘记调用 = 整条链被你短路。
6. 挂载、安装与调试清单
6.1 三条挂载路径
| 路径 | 适用 | 做法 |
|---|---|---|
| 临时 overlay | 本地调试、演示 | dsh web --patch ./overlay.yml |
| 外置插件包 | 自研可分发 | `dsh plugin --profile web add <path |
| 仓库内正式包 | 给 dsh 本体贡献 | packages/<group>/<pkg> + cookbook 清单 |
安装示例:
dsh plugin --profile web add ./hello-plugin
dsh plugin --profile web add github:some-org/my-plugin
dsh plugin --profile web remove my-plugin
社区发现标签:GitHub topic dsh-plugin。
6.2 正式函数插件的「四导出」
养成肌肉记忆:
export const name = 'my-plugin' // 诊断名
export const inject = ['tools'] // 硬依赖
export const Config = /* schemastery */ // 可选
export function apply(ctx, config) {} // 唯一副作用入口
6.3 插件三种形态怎么选
- 函数:大多数工具/钩子够用
- 对象:需要附带字段时
- 类
extends Service:你要 对外提供ctx.xxx服务时
6.4 Host 平面 vs Agent preset 平面(高频概念坑)
- boot profile(如
web/headless):启动哪棵宿主插件树 - agent preset(标准/PTC/极简/创造):这个会话装哪些工具与人格
不要对 CLI 写 dsh --profile standard——standard 通常是 preset,不是 boot profile。
另外:preset 里若发布服务,注意 isolate realm,否则多会话同名服务可能撞车;纯消费 tools 的工具行,很多场景应平铺在顶层,而不是错误包进空 isolate。
6.5 社区插件怎么用(实践向)
常见增强方向:
@文件引用(减少模型反复扫目录)- 更好的侧边栏/工作台 UI
- 视觉能力补充
- 插件市场/发现器
安装后按插件 README 重启 profile,再在「设置 → 插件」确认启用。
插件=可执行代码:看 README、看权限、看维护活跃度,固定版本更稳妥。
7. 权限、轨迹与日常工作流
7.1 权限三档(先安全后爽)
| 级别 | 含义 | 建议 |
|---|---|---|
| Read Only | 只读工作区 | 审计/讲解代码 |
| Workspace Write | 工作区内读写 + 受限命令 | 日常默认 |
| Full access | 宽权限 | 仅明确需要且可回滚环境 |
越界写文件时,好的体验应是:沙箱拒绝 → UI 弹出升级/单次允许 → 轨迹里留痕。
7.2 用 Trajectory 排错
任务失败别只看最终一句话,打开轨迹检查:
- 模型本轮到底看到了哪些工具
- 哪一次 tool 参数错了
- 是否被 pre-execute 拒绝
- 是否在错误路径上空转
这是 dsh 相对「只给最终答案」的产品,对开发者最值钱的部分之一。
7.3 建议的日常节奏
- 练习目录 + 标准模式 + workspace-write
- 先让 Agent 完成小任务,确认权限与模型 OK
- 缺能力 → 先搜社区插件,再考虑自写
- 自写 →
--patch验证 → 再plugin add固化 - 重复链路稳定后,再评估 PTC 是否值得
7.4 多模型
Harness 模型无关:设置里可添加其它提供方或 OpenAI 兼容端点。
实践建议:同一任务固定「模型 + preset + 权限」再对比,否则变量太多得不出结论。
8. 常见坑与排错表
| 现象 | 优先检查 |
|---|---|
| 插件「没反应」 | 模块路径/包名拼写;解析失败可能只打日志不崩 |
| 有代码但模型看不到工具 | 是否 inject: ['tools'];是否被 preset scope / restrict 滤掉 |
| apply 一启动就挂 | 设计如此:加载失败 fail loud,查依赖与 Config schema |
| patch 改了无效 | 是否按 id 命中;是否整行 config 覆盖丢字段 |
| waterfall 逻辑怪 | 是否忘记 next() |
| HMR 后残留监听/工具 | 是否裸写全局副作用,而不是 ctx.on / register / effect |
--profile standard 报不存在 |
分清 boot profile 与 agent preset |
| Windows 沙箱不稳 | 优先 WSL/Linux 路径做强隔离实验 |
git 安装插件缺 lib/ |
作者需 prepare 构建;pnpm≥10 可能要 allowBuilds |
官方开发文档入口:
- 第一个插件:https://deepseek-harness.github.io/deepseek-harness/develop/basic/
- 架构参考:https://deepseek-harness.github.io/deepseek-harness/reference/
- Cordis 教程:https://deepseek-harness.github.io/deepseek-harness/develop/cordis-tutorial/
9. 总结与下一步
- dsh 是 Agent 运行时底座,不是对标某成品 Code 助手的换皮。
- 一切皆插件 = 无特权内核 + 配置层组合 + 可逆注册。
- 四种模式是 四套插件模板,标准起步,创造改装,极简评测,PTC 压缩稳定流程。
- 写插件抓手只有一条链:
apply→inject→ctx.tools.register(defineTool)→ patch 挂载。 - 排错先看
--dump-config+ Trajectory + 是否 next()/effect`。 - 预览版接口会变:冻结版本、小范围试点、权限默认收紧。
建议学习顺序(继续深挖)
- 官方 Cordis 教程 7 章(无 Key 也能跑概念)
- cookbook:adding-a-tool / capability seam
- 读
examples/headless-agent/cordis.yml,对照自己的插件树 - 做一个「只服务你工作流」的小工具(质检、发布检查、仓库约定扫描)
- 再考虑打包 bundle 与分享到
dsh-plugintopic
「一切皆插件」真正爽的时刻,不是背概念,而是:
你改了一行 patch,模型多了一个工具;你卸掉插件,世界干净回到从前。
把这条闭环在自己的机器上跑通,这篇实践教程的目标就达成了。
参考链接
- DeepSeek Harness 官网:https://www.deepseek.com/harness/
- GitHub 仓库:https://github.com/deepseek-ai/deepseek-harness
- 架构文档:https://deepseek-harness.github.io/deepseek-harness/reference/
- 第一个插件教程:https://deepseek-harness.github.io/deepseek-harness/develop/basic/
- Cordis 教程:https://deepseek-harness.github.io/deepseek-harness/develop/cordis-tutorial/
- 社区插件发现:https://github.com/topics/dsh-plugin
- Cordis 论文仓库:https://github.com/cordiverse/paper
更多推荐


所有评论(0)