从安装到插件开发:把大模型接进真实工作环境的 Agent 运行框架(MIT 开源 · 一切皆插件)
由 网络精灵 整理 · 2026-08-14 · AI 导航原创指南 · 基于官方 README / architecture.md / 社区实操
DeepSeek Harness(dsh)是 DeepSeek 于 2026-08-13 开源的 Agent 运行框架(MIT 协议)。 它不是新模型、不是 API 客户端,而是把大模型接入"真实工作环境"的执行层(Harness):文件系统、终端、网页、代码工具、其他 Agent,以及上下文管理、工具调用编排、任务执行与边界控制。
同一个模型,放进不同的 Agent 系统,表现可能天差地别。原因很简单:
社区里最经典的例子(评测者 sentdex):DeepSeek V4-Flash-0731 在极简 harness 下 Terminal-Bench 只拿 44/89,换到功能完整的 Oh My Pi harness 直接跳到 64/89——同一模型、同一基准,差了 20 题。所以"模型易得,Agent 难建",工程化执行层才是下一阶段竞争焦点。
Model(大脑) + Harness(身体) = Agent(能干活的数字员工)
DeepSeek 给自己的定位:补齐"Vibe Coding / AI 编程执行层"入口,对标 OpenAI Codex、Anthropic Claude Code,但不绑定自家模型。
这是 dsh 最反常规的设计。在 dsh 里,模型适配器、工具、技能、会话、沙箱、存储、Agent Loop 本身、调度、UI —— 全部是插件,由配置组合,无需改框架源码。
底层是 Cordis 插件元框架(理念来自北大 + DeepSeek 联合论文《A Programming Paradigm for Spatiotemporal Composability》)。Cordis 只管"插件怎么加载/卸载/互相依赖",具体能力由插件提供。
模式 = 默认加载不同"插件集",在 UI 里切换:
| 模式 | 默认插件集 | 适用场景 |
|---|---|---|
| Standard 标准 | 完整工具组合 | 日常开发,开箱即用 |
| PTC(Programmatic Tool Calling) | 模型生成代码来组合多轮工具调用 | 复杂工作流、需要编排多步操作 |
| Minimal 极简 | 仅一个 shell 工具 + 一个文件编辑工具 | 跑分/基准验证的基线 |
| Creation 创造 | 可检视运行时、在内存里试验 Cordis 插件 | 开发新插件、拼装新模式 |
web(带浏览器)、headless(无服务器的一次性运行器)等模板;dsh --profile web(然后 UI 里选标准/PTC…)。| 维度 | DeepSeek Harness | 典型 Harness |
|---|---|---|
| 架构 | 一切皆插件(Cordis) | 单体核心 + 扩展点 |
| 扩展方式 | 挂插件,不改源码 | 通常要 fork/patch 核心 |
| 可观测性 | 追加式会话日志 + 轨迹视图 | 参差不齐,常只记部分 |
| 运行模式 | Standard / PTC / Minimal / Creation | 通常单一模式 |
| 许可证 | MIT 开源 | 各异 |
| 工具调用 | 经典 + PTC(代码组合调用) | 通常仅经典 |
registry.npmjs.org 与现代 CDN。https://api.deepseek.com(默认模型端点)。node -v # 期望 v18 或以上
corepack enable # 让 pnpm 命令可用(Node 16.13+ 自带 corepack)
pnpm -v
npx @deepseek-ai/dsh web
@deepseek-ai/dsh 包并启动。git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web
docs/(architecture.md、cordis-primer.md、cordis-tutorial/)、examples/(acp-agent、native/landlock-run 沙箱)、各类 cookbook。pnpm 报命令不存在:corepack enable 后再试;或 npm i -g pnpm。# 看本机实际会启动的插件树(每行都可被 patch 替换)
npx @deepseek-ai/dsh --profile web --dump-config
能正常打印一大棵配置树,说明安装 OK。
| 现象 | 排查 |
|---|---|
npx 卡在下载 | 检查 npm 源/代理;可 npm config get registry 后切官方源 |
| 启动后打不开 3080 | netstat -ano | findstr 3080 看是否被占用;关掉占用进程或换端口 |
| Node 版本过低报错 | 升级到 18+,用 nvm 或官方安装包 |
pnpm 不是命令 | corepack enable 或全局装 pnpm |
| 启动后白屏 | 清浏览器缓存;看终端日志有无构建报错 |
dsh 的模型适配器本身就是插件,所以换模型 = 换/加一个提供方配置,不改代码。
deepseek-v4-pro(1M 上下文、强 Agent 能力)、deepseek-v4-flash(便宜、快)。https://api.deepseek.com)。配置文件位于 $DSH_HOME/settings.yaml($DSH_HOME 是 Harness 主目录,默认 ~/.dsh 之类;如不确定,--dump-config 输出顶部会显示)。
llm-pi-ai:
providers:
my-gateway:
apiKeyEnv: GATEWAY_API_KEY # 从环境变量读 Key
api: openai-completions # 协议类型
baseURL: https://api.example.com/v1
models:
- id: model-name-here
然后命令行注入环境变量即可,模型变更无需重启 dsh,下次请求自动生效:
export GATEWAY_API_KEY="your-key-here"
npx @deepseek-ai/dsh web
| 类型 | 是什么 | 凭据 | 适用 |
|---|---|---|---|
| DeepSeek | 官方端点 | DeepSeek API Key(只写) | 默认、最快上手 |
| 目录提供方(Catalog) | dsh 已收录的厂商(Anthropic、OpenAI、Bedrock、Vertex、Azure、Codex 等) | 各家 Key;原生认证需各自填 | 接主流厂商 |
| 自定义提供方 | 公司网关、自建 OpenAI 兼容服务 | Provider ID + baseURL + 协议 + 凭据 + 模型 | 目录里没有的端点 |
添加自定义提供方时字段:
| 字段 | 说明 | 必填 |
|---|---|---|
| Provider ID | 小写永久标识;请求、已存会话、凭据引用都用它。不可改名(要改就删了重建) | 必填 |
| 显示名称 | 界面显示名 | 可选 |
| 基础 URL | 端点 baseURL | 必填 |
| API 协议 | 如 openai-completions、anthropic | 必填 |
| 凭据 | API Key 或环境变量引用(如 env:GATEWAY_API_KEY) | 必填 |
| 模型 | 至少一个模型 ID;可"获取可用模型"自动拉 | 必填 |
只要兼容 OpenAI Chat Completions 或 Anthropic 协议,都能接:
openai-completions,baseURL 填网关地址。anthropic 或目录里选 Anthropic 提供方。http://localhost:8000/v1),模型填本地模型名。env:XXX 引用环境变量。.env / settings.yaml 在 .gitignore 里。npx @deepseek-ai/dsh web
打开 http://127.0.0.1:3080 后:
C:\soft\Slogan 或任意文件夹)。
直接下自然语言任务,例如:
report.md 里。dsh 会自己完成:找文件 → 读内容 → 计算 → 写文件,全程在轨迹里可见。
更复杂的(它最擅长):
| 想体验 | 怎么做 | 观察点 |
|---|---|---|
| Standard | 默认即可 | 完整工具:文件、Shell、网页、搜索 |
| PTC | 切到 PTC | 让模型先"写一段代码"来编排多轮工具调用,再执行 |
| Minimal | 切到 Minimal | 只有 shell + 文件编辑,看基线能力 |
| Creation | 切到 Creation | 可检视运行时、在内存里临时挂插件试验 |
# 启动 Web UI(最常用)
npx @deepseek-ai/dsh web
# 查看本机实际启动的插件树
npx @deepseek-ai/dsh --profile web --dump-config
# 用 patch 覆盖某一行配置(不改动源码)
npx @deepseek-ai/dsh --profile web --patch ./my-overlay.yml web
# Headless:一次性跑完任务自动退出(无服务器)
npx @deepseek-ai/dsh --profile headless "运行测试套件并报告失败的测试"
--profile:启动形态(web / headless,以及模板)。--dump-config:把"你的机器实际会 boot 的插件树"打印出来,每一行都能被你自己的 patch 替换——这是调试/定制的核心入口。--patch <file>:命令行覆盖层,叠加在 profile 的 cordis.patch.yml、用户级 patch 之上。适合脚本调用、CI/CD:
# 单次任务:运行并打印结果后自动退出
npx @deepseek-ai/dsh --profile headless "为 src/utils.ts 补单元测试,覆盖率不低于 80%"
Headless 是"无服务器的一次性运行器",不会常驻端口。
官方提供 Python SDK,适合把 Harness 嵌入已有系统(CI/CD、自动化测试、批量代码审查):
# 示意:具体 API 以官方 SDK 文档为准
from deepseek_harness import Harness
h = Harness(profile="headless")
result = h.run("审查 PR #123 的改动并列出风险点")
print(result)
python/ 目录与官方文档为准;预览期可能变动,使用前先看 docs/development.md。packages/ 之下的东西前,必须读完本节。前提是先懂 Cordis(仓库内有 cordis-primer.md 和 cordis-tutorial/)。ctx(Context)贡献一个带类型的服务,如 ctx.tools、ctx.llm、ctx.fs。ctx.effect() 注册的资源,在插件卸载时自动撤销。装/卸对称,不会留下孤儿状态。// 最小插件:心跳定时器(来自社区拆解,最直白展示 effect 可逆性)
export function apply(ctx: Context) {
ctx.effect(() => {
const timer = setInterval(() => console.log('tick'), 200)
return () => { clearInterval(timer); console.log('heartbeat cleaned up') }
})
}
卸载时 clearInterval 一定被调用——这就是"装什么、收什么"。
cordis.patch.yml。web 和 headless 是内置模板。每个包在自己的 package.json 用 dsh 字段声明:
dsh.profile:列出该 profile 的 bundles;dsh.bundle:指向该 bundle 的 patch 文件。一个运行中的 dsh = 启动时从有序分层组装出的插件树。层级顺序:
profile 里列出的每个 bundle(按列表顺序)
→ profile 的 cordis.patch.yml
→ 用户级 patch
→ 命令行 --patch 覆盖层
顶层 dsh-base 是每个 profile 的第一层,提供:模型适配器、工具、持久化、沙箱、审批策略、设置、凭据、遥测。其上:
dsh-web-app:加浏览器应用;dsh-headless:加无服务器的单次运行器。dsh --profile web --dump-config 打印的树,就是真相;任何一行都能被你的 patch 替换。| 包 | 负责 | ctx key |
|---|---|---|
core/session | 追加式 SessionEvent 日志 + 内存存储 | ctx.sessions |
core/system-prompt | 系统提示分区 + 工具 schema 组装 | ctx.systemPrompt |
core/tools | 作用域化工具注册表 + 受保护执行流水线 | ctx.tools |
core/agent | Agent 接口、实时注册表、agent/* 事件 | ctx.agents |
core/agent-loop | 默认驱动,实现该接口(可整体替换) | ctx.agentLoop |
core/scope | 每 Agent 作用域注册原语 | 库,无 key |
llm/llm | 消息/流词汇 + 适配器接缝 | ctx.llm |
事件就是扩展点。Cordis 明确区分四种分发语义,且这是事件的公开契约一部分:
| 模式 | await | 顺序 | 有返回值 | 语义 |
|---|---|---|---|---|
emit | 否 | 按注册顺序 | 否 | 观察(fire-and-forget) |
waterfall | 否 | 按注册顺序 | 是 | 环绕式中间件(around-middleware) |
parallel | 是 | 所有监听器并行 | 否 | 扇出 |
serial | 是 | 按注册顺序 | 是 | 顺序执行 |
最关键是 waterfall:相当于 around-middleware。监听器收到 (...args, next),调用 next() 把(可能被改过的)结果交给下一个;直接 return 不调 next() 就短路整条链。Agent 框架里的拦截全靠它。
事件分三个域:
session/event 广播(重载后仍在)。agent/*):携带活体 Agent(inbox/step/status/request/validation/continuation),用于观察或拦截。fs/*、tools/*、telemetry/*),不碰 loop。agent/pre-step、agent/request、llm/stream、三个 tools/* 是 waterfall(监听器必须调 next());agent/turn-stopping 是 serial,无 next()。
turn/start
claim 下一步输入 + 一条排队的消息
组装提示分区 + 工具 schema
-> agent/pre-step (reject | enter(messages))
step/start
把 enter 的消息作为 user/message 追加
从日志推导模型历史
agent/request -> llm/stream -> assistant/chunk* -> assistant/message
tool/call* -> tools/pre-execute -> tools/execute -> tools/post-execute -> tool/result*
step/end
工具还欠一次请求 / 新输入到达 -> claim -> 下一个 step
-> agent/turn-stopping
turn/end
turn/*、step/*、user/message、assistant/*、tool/* 是持久会话事件;其余是三域的实时扩展点。
所有"模型可见"的数据都必须能从追加式 SessionEvent 流重建,deriveMessages() 投影出模型历史。assistant/chunk 原始流保留以支撑回放和 UI。分叉(fork)、续跑(resume)、轨迹回放、遥测、持久化都从这条流派生——不需要另写快照逻辑。
因此:任何新的"模型可见输入"都必须新增一个会话事件(扩展 SessionEventMap 并从日志渲染)。
Seam = 一个可替换能力,含三角色:
一个包可兼任多角色,但三者齐备才构成完整 seam。换掉一个 Provider 就全局改变产品——例如把文件系统与子进程 Provider 指向远程沙箱,Bash、PTY、LSP 会一起迁移,无需 fork 任何 Provider。
一个 dsh 插件(Cordis 函数插件)长这样:
export const name = 'my-plugin'
// 声明依赖的服务;Cordis 保证 apply 执行时 ctx.tools 已就绪
export const inject = ['tools']
export async function apply(ctx: Context, config: Config) {
// 注册一个工具(返回 disposer,卸载自动撤销)
ctx.tools.register(defineTool({
name: 'my_tool',
description: '...',
parameters: { type: 'object', properties: { q: { type: 'string' } } },
async execute({ q }) { return `处理结果: ${q}` },
}))
// 非 Cordis 原生资源,用 ctx.effect 显式绑定生命周期
ctx.effect(() => {
const conn = connectExternal()
return () => conn.close() // 卸载时执行
})
}
服务依赖用 inject 声明;外部资源用 ctx.effect() 绑定到插件 fiber 生命周期。这两个机制组合后:任何外部协议集成,只需把它的资源映射到 ctx 上的注册调用。
| 目标 | 机制 | ctx key / 事件 |
|---|---|---|
| 加模型提供方 | 在 ctx.llm 注册适配器 | ctx.llm |
| 加一个面向模型的工具 | 在 ctx.tools 注册(schema 自动进提示组装) | ctx.tools |
| 给某会话不同能力集 | 组合 agent preset(其 service 行需 isolate realm) | — |
| 加 shell 执行 | 注册 ctx.shell 后端(本地经 ctx.subprocess 拉起) | ctx.shell |
| 加持久终端 | 注册 ctx.terminals 后端 + dsh-tool-terminal | ctx.terminals |
| 加人工命令(不走模型轮次) | 注册到 ctx.commands | ctx.commands |
| 加后台工作 | 注册到 ctx.jobs(job_* 工具收集/停止) | ctx.jobs |
| 加文件系统访问/策略 | 注册 ctx.fs Provider 或监听 fs/* | ctx.fs |
| 限制派生进程 | 用 ctx.sandbox 后端,consumer 在 spawn 前包 argv | ctx.sandbox |
| 拦截请求/工具/轮次 | 用对应 agent/* 或 tools/* 事件 | agent/*, tools/* |
| 注入模型可见上下文 | 调 agent.inject() | agent.inject() |
| 加 UI / 编辑器集成 | 驱动 ctx.agents,从 session/event 渲染 | ctx.agents |
| 加 Web Chat 节点 | 注册 ConversationNodeDefinition + 键控渲染器 | — |
| 加持久会话状态 | 扩展 SessionEventMap,从日志渲染/回放 | SessionEventMap |
| 生成会话标题 | 注册唯一的 ctx.sessionTitle Provider | ctx.sessionTitle |
| 同会话目标管理 | 用 ctx.goals,经 agent/* 续跑 | ctx.goals |
| 分叉活跃会话 | ctx.sessions.fork(source, boundary?, childSessionId?) | ctx.sessions |
| 把注册限定到某 Agent | 用该 Agent 的 agent.ctx | agent.ctx |
// 在每次模型请求前改写/拦截(agent/pre-step 是 waterfall)
ctx.on('agent/pre-step', (next) => {
return (payload) => {
// 改 payload.messages、或 reject 掉
return next(payload)
}
})
tools/pre-execute / tools/execute / tools/post-execute 同理可包一层做审计、超时、权限。
官方 @deepseek-ai/dsh-mcp-client 是一个标准 Cordis 函数插件,精髓:
ctx.effect(() => { names.add(name); return () => names.delete(name) })。两个实例同名 → 后加载的 apply 阶段直接 throw(不是运行时静默覆盖);HMR 热替换时旧命名空间自动释放。startConnection() 返回普通 { ready, dispose() },只有 ctx.effect(() => () => connection.dispose()) 这一行把生命周期绑到 fiber。ctx.tools.register():MCP tool 和原生 tool 共用同一注册路径 → 模型看到的 schema、权限策略、timeout、compaction 行为完全一致,不存在"MCP tool 是特殊的"这种概念。命名规范 mcp__<server>__<raw> 是纯函数(有损时附 12 字符 SHA-256 防碰撞)。connecting → connected → (断开) → backoff → connecting → …,预算耗尽 → disabled;存活超过 maxDelayMs 会重置预算(偶发崩溃可无限恢复,crash-loop 被正确终止)。Skill 是完整的 Capability Seam。核心数据结构 ScopedLayers 与 ctx.tools 同款分层模型:
读取时,全局层 + 查看者 scope 链逐层合并,近层同名覆盖远层。registerProvider() / register() 返回 disposer。
package.json 声明 dsh 字段:
dsh.bundle 指向该 bundle 的 patch 文件(配置行 + 挂载代码)。cordis.patch.yml,或--patch 覆盖层。dsh-plugin 话题(GitHub topic)提升可发现性。Creation 模式里先试(检视运行时、内存里挂插件)
→ 打包成 Bundle
→ 挂到 Profile(cordis.patch.yml 或 --patch)
→ 用 --dump-config 核对启动树
(呼应之前"底部菜单栏排序与首页不一致"的问题。)把工作区指向 C:\soft\Slogan\frontend\h5,下任务:
src/App.vue 和 src/views/Home.vue,理解底部菜单栏(首页/优惠券/订单/我的)与首页内容的排序关系。如果两者应一致,给出修改方案并直接改 App.vue 让底部栏顺序与首页逻辑一致;改完跑 pnpm build(或 npm run build)确认不报错,并把改动写成一个 git commit。dsh 会自己:定位文件 → 读代码 → 判断 → 改 → 构建验证 → 提交。你在 Web UI 里逐条审批它的写文件/跑命令操作即可。
dsh 支持子 Agent 编排(subagent providers 背后是统一接口:从全新子 Agent 到"把一轮委托给另一个产品"都能换)。可以用 Creation 模式或在 profile 里组合不同 agent preset 来做"一个规划 Agent + 多个执行 Agent"的分工。
仓库 compaction/ 包定义了可替换的压缩接口(含基础实现)。社区已有第三方插件做:自适应上下文压缩(ACP)、长期记忆、因果图检索。要做长任务不爆上下文,就挂这类插件——这正是"一切皆插件"的价值所在。
v0.1,明确会有兼容性破坏的修改。今天写的插件明天可能要改。env:XXX)或 $DSH_HOME/settings.yaml,绝不进 git。# 在本机执行,把服务器 3080 转到本机 3080
ssh -N -L 3080:127.0.0.1:3080 user@123.57.12.205
然后本机浏览器开 http://127.0.0.1:3080。你的 ECS 已禁用密码登录、仅密钥,这点做得对,继续保持。
dsh --profile web --dump-config:看实际启动树,定位要 patch 哪一行。deriveMessages() 投影出的就是模型真实看到的上下文——"模型表现怪"先查日志。npx @deepseek-ai/dsh web # 起 Web UI(默认 3080)
npx @deepseek-ai/dsh --profile web --dump-config # 看实际启动插件树
npx @deepseek-ai/dsh --profile headless "任务" # 一次性跑完退出
npx @deepseek-ai/dsh --profile web --patch x.yml web # 覆盖层
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness && pnpm install && pnpm run build && pnpm dsh web
https://api.deepseek.comdeepseek-v4-pro、deepseek-v4-flashhttp://127.0.0.1:3080$DSH_HOME/settings.yamlopenai-completions / anthropic / 自定义| 资源 | 链接 |
|---|---|
| GitHub 仓库 | github.com/deepseek-ai/deepseek-harness |
| 架构文档 | 仓库 docs/architecture.md |
| Cordis primer/tutorial | 仓库 docs/cordis-primer.md、docs/cordis-tutorial/ |
| 扩展手册 | 仓库 docs/cookbook/(加包/工具/LLM适配器/Chat节点) |
| Cordis 框架 | github.com/cordiverse/cordis |
| Cordis 论文 | github.com/cordiverse/paper |
| DeepSeek API 文档 | api-docs.deepseek.com |
| 申请 Key | platform.deepseek.com/api_keys |
| Discord 社区 | discord.gg/Ycq5dCaS4 |
| 插件话题 | GitHub topic dsh-plugin |
Q:免费开源吗?
A:是,MIT,源码全在 github.com/deepseek-ai/deepseek-harness。预览版 2026-08-13 开放。
Q:能接非 DeepSeek 模型吗?
A:能。模型适配器本身就是插件,可换/加提供方(OpenAI 兼容、Anthropic、本地 vLLM 等)。
Q:四种模式怎么选?
A:Standard 日常;PTC 复杂工作流(模型写代码编排工具);Minimal 跑分基线;Creation 开发/试验插件。
Q:能上生产吗?
A:预览期不建议。破坏性变更频繁。
Q:和 Claude Code / Codex 比?
A:最大差异是"无特权核心、一切可配置替换" + 追加式会话日志可完整回放。Claude Code/Codex 多为单体核心 + 扩展点。
Q:插件写错会搞崩整个 dsh 吗?
A:不会全局崩——Cordis 的可逆效果保证插件卸载时注册自动撤销;坏的 bundle 用 --dump-config 核对、用 patch 覆盖或移除即可。
npx @deepseek-ai/dsh web 跑起来,再在 Creation 模式里试写第一个插件。