一切皆插件 · DeepSeek Harness 实战绿皮书

从五分钟跑通,到写出你自己的插件

把 DeepSeek 开源的 Agent Harness(dsh)讲透——上手、原理、组合、开发、自动化、生态

作者:我是雷神(王明雷) | AI+HR 落地实战派 · AI 赋能企业落地专家
版本:v1.0(2026-08) | 全书 20 章 + 附录,分三部:基础篇 · 进阶篇 · 生态篇 | 对应 dsh 开发者预览版
基于官方文档 + Cordis 论文 可断网阅读 附插件生态图谱配套页 所有命令可直接复制运行
微信公众号「人力资源数字化探索」二维码
微信公众号
人力资源数字化探索
扫码关注 · 获取本书更新
这本书在讲什么:2026 年,DeepSeek 开源了自己的 agent harness——DeepSeek Harness(dsh)。它不是又一个聊天客户端,而是一套「一切皆插件」的智能体运行环境:模型适配器、工具、沙箱、会话、甚至 agent 主循环本身,全都是可替换的插件。这本绿皮书带你走完整条路:先跑起来(基础篇)→ 理解它为什么这样设计、并把它用成系统(进阶篇)→ 进入生态一起共建(生态篇)。它同时也是一本「读源码之前先读我」的向导:书里每一条命令、每一段配置、每一个包名,都来自官方仓库与文档。

全书地图:三部怎么读

全书是一条完整的成长路径——先能跑(基础篇)→ 用成系统(进阶篇)→ 参与共建(生态篇)。按你所处的阶段进入即可:

包含篇章读完你能做到
一、基础篇
先跑起来
1.1 上手篇(六步跑通)
1.2 认知篇(第 1–3 章)
一条命令启动 Web UI、配好模型、跑通第一个任务、会用 headless 和 profile、能把自己的插件树打印出来看;并且理解「一切皆插件」到底解决什么问题。
二、进阶篇
把 Harness 用成系统
2.1 组合篇(第 4–6 章)
2.2 开发篇(第 7–10 章)
2.3 机制篇(第 11–14 章)
2.4 自动化篇(第 15–17 章)
用 patch 分层定制自己的 dsh 而不 fork 源码;写出并发布第一个插件;看懂轮次/事件/服务这套引擎机制;用 headless、Python SDK 把 dsh 接进自己的工作流。
三、生态篇
从使用者到共建者
3.1 生态与社区
3.2 两层世界
知道去哪找现成插件(附两张配套生态图谱页)、怎么参与社区,以及应用层产品与 harness 层底座的关系——什么时候用哪一层。
怎么快速定位自己:没装过 dsh → 从 1.1 上手篇 开始;跑通了但想定制 → 直接进 2.1 组合篇;会写 TypeScript、想扩展它 → 从 2.2 开发篇 切入;只想做技术选型判断 → 读 1.2 认知篇 + 3.2 两层世界
版本提醒:dsh 目前处于开发者预览(developer preview)阶段,官方明确说「未来将出现破坏兼容性的变更」。本书基于 2026 年 8 月的仓库与文档写成;如果你读到时命令或配置对不上,以官方仓库 deepseek-ai/deepseek-harness 的最新文档为准——本书教你的「怎么理解它」不会过时,具体参数可能会。
一、基础篇 · 1.1 上手篇 · 第一步

dsh 是什么:Agent Harness 与「一切皆插件」

在敲第一条命令之前,先用三分钟搞清楚你装的是什么。这决定了你后面每一步的预期。

DeepSeek Harness(命令名 dsh)是 DeepSeek AI 开源的 agent harness——直译是「智能体挽具」,实际角色是智能体的运行环境:模型只负责思考,harness 负责把思考变成安全落地的行动——调工具、读写文件、跑命令、管会话、管权限、管持久化,再把整个过程呈现给你审批和观察。

它有三个身份,对应你使用它的三种深度:

  • 一个开箱即用的产品:一条命令启动 Web UI,配上 DeepSeek API 密钥就能让 agent 在你的项目目录里干活;
  • 一套可组装的底座:通过配置分层(profile / 组合包 / patch),你可以替换其中任何一块——包括换模型、换工具、换界面,甚至换掉 agent 主循环;
  • 一个插件生态的起点:官方鼓励社区写插件,用 GitHub 话题 dsh-plugin 互相发现。

一句话记住它的架构立场

一切皆插件(Everything is a Plugin):产品的每一部分都是插件——模型适配器、工具注册表、会话日志、乃至 agent loop 本身——因此每一部分都可以从配置替换。不存在需要打补丁的特权内核。

这句话来自官方架构文档,是全书反复回到的锚点。它的底层框架叫 Cordis,其设计对应一篇正式论文《A Programming Paradigm for Spatiotemporal Composability》——1.2.3 章会用大白话讲清楚这篇论文在说什么,以及它为什么重要。

你可能熟悉的东西dsh 对应物差别
聊天机器人网页dsh Web UIdsh 的对话对象是一个能动手的 agent:读写工作区文件、跑命令、委派子任务,高危操作先请求审批
Claude Code / Codex 这类编码 agentdsh 全体同类产品,但 dsh 把「可组装」提到第一优先级:整个系统是一棵可以逐行替换的插件树,且开源(MIT)
VS Code 插件系统Cordis 插件系统VS Code 卸载一个扩展要重启宿主;Cordis 插件卸载时副作用自动完全回收,热插拔是数学保证(见 1.2.3)
本章要点:dsh = 产品 + 底座 + 生态三合一。你可以只把它当产品用(基础篇够了);但它真正的价值在「可组装」,那是进阶篇的内容。
一、基础篇 · 1.1 上手篇 · 第二步

五分钟启动 Web UI

只需要 Node.js 和一条命令。这一章跑完,你的浏览器里就有一个本地 agent 驾驶舱。

方式一:npx 直接跑(推荐首次体验)

安装 Node.js 后,在你想让 agent 干活的项目目录里执行:

npx @deepseek-ai/dsh web

命令会启动 Web UI,默认地址 http://127.0.0.1:3080(终端会打印实际地址)。注意一个细节:你在哪个目录启动 dsh,哪个目录就是默认的工作区根——所以别在 C 盘根目录随手一敲,先 cd 到一个演练项目里。

方式二:从源码跑(想改代码 / 想装本地插件)

git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web

源码方式是后面开发篇(2.2)的前置条件:本地插件教程需要在仓库检出里进行。只是使用的话,npx 就够。

启动后你会看到什么

  • 一个会话列表 + 输入框的界面——但输入框暂时不可用,因为还没选工作区(下一章解决);
  • 设置入口——先去配模型密钥(下一章第一件事)。
安全提醒:dsh 是跑在你本机、能读写文件和执行命令的系统。首次体验请在演练目录(比如专门建一个 dsh-playground 文件夹)里启动,观察它的审批请求都长什么样,再决定放到真实项目里用。这和你第一次给任何 agent 授权的原则一致。
一、基础篇 · 1.1 上手篇 · 第三步

配置模型:DeepSeek 密钥与更多提供方

dsh 的模型路由是热生效的:改完下一次请求就用新配置,不用重启服务器。

最短路径:填一个 DeepSeek API 密钥

  1. 打开 设置 → 模型
  2. 在 DeepSeek 卡片里输入 API 密钥,保存。

就这两步。有个值得点赞的设计:密钥是只写的——保存后页面只显示脱敏描述符,永远不会回显明文。密钥落盘在 $DSH_HOME/.credentials.yaml(dsh 的用户目录),设置文件里只保留一个凭据引用。

接入其他提供方:三个层次

层次操作适用
目录提供方「添加提供方」→ 选 Anthropic、OpenAI 等 → 填密钥主流厂商。端点、协议、模型列表都由内置目录提供,填个密钥就完事
原生认证提供方Bedrock / Vertex / Azure / Codex 各自用 AWS 凭据与区域、ADC 项目、api-version、OAuth云厂商托管模型。只填 API 密钥字段是配不通的,要按各家原生方式来
自定义提供方「添加自定义提供方」→ 填小写 Provider ID、基础 URL、API 协议、凭据、至少一个模型公司网关、自建 vLLM/代理、任何 OpenAI 兼容端点。「获取可用模型」按钮可直接拉取端点的模型列表
一个不可逆的坑:自定义提供方的 Provider ID 是永久的——请求、已保存会话、模型默认值、凭据引用都挂在它上面。起名前想清楚;要改名只能新建一个再删旧的。

进阶:视觉模型要自己声明

手动录入的模型默认按纯文本对待。如果你的自定义端点上有支持图片的模型,需要在 $DSH_HOME/settings.yaml 里给它加一行 input

llm-pi-ai:
  providers:
    my-gateway:
      apiKeyEnv: GATEWAY_API_KEY
      api: openai-completions
      baseURL: https://gateway.example/v1
      models:
        - id: legacy-chat
        - id: vision-preview
          input: [text, image]

整条路由都是视觉模型的话,用 defaultInput: [text, image] 设一次回退值即可。记住这些字段是「你对端点的断言」而不是「dsh 替你做的检查」——声明了端点没有的能力,请求会被提供方拒绝。

一、基础篇 · 1.1 上手篇 · 第四步

跑通第一个任务:工作区 · 会话 · 审批

模型配好了,现在让 agent 干第一件实事。三个概念一次搞懂:工作区决定它能碰哪里,会话承载一次协作,审批是你手里的闸。

第一步:选择工作区

点击选择工作区,把你启动 dsh 时所在的项目目录添加进来并选中。选中工作区之前,会话输入框是禁用的——这是有意设计:agent 必须先有明确的活动范围,才能开始接活。

第二步:发出第一个任务

官方指南给的第一个任务就很好,直接抄:

Summarize this repository and identify its main packages.
(总结这个仓库,识别它的主要模块。)

你会看到 agent 开始读取工作区文件、运行命令、组织回答。它能做的事包括:读取和编辑工作区文件、运行命令、委派工作(子代理)、维护计划。

第三步:理解审批

当某个操作在当前权限策略下需要审批时,Web UI 会先弹窗询问你。第一次使用时,建议每个审批都点开看清楚它要干什么、在哪个目录干——这是你建立信任边界的过程。dsh 底层有完整的沙箱与审批策略体系(进程限制支持 bwrap / Landlock / Seatbelt 等后端),权限策略本身也是插件树里的可配置行。

中文任务照样可以

任务 A · 摸底

"总结这个仓库的结构和主要模块,输出一份 docs/overview.md,中文。"

任务 B · 整理

"扫描 input 目录里的文件,按类型分类,先给我一份分类方案清单,我确认后再执行移动。"

任务 C · 小改动

"给 README 增加一节'快速开始',包含安装和启动命令,改完把 diff 摘要发我。"

验收习惯从第一天养成:任务里写清楚目标、输入、动作、约束、输出五要素,并给出验收标准("清单条数 = 实际文件数"这种可核对的)。这个习惯与工具无关,在任何 agent 上都值钱。
一、基础篇 · 1.1 上手篇 · 第五步

CLI 三种姿势:web · headless · profile

dsh 命令本质是一个「profile 启动器」。搞懂这一点,你就同时学会了它的三种用法。

入口模式一览

命令作用
dsh web启动 Web UI(它其实是 dsh --profile web 的别名)
dsh --profile headless "任务描述"无头模式:新起一个持久化会话跑完这一个任务,把最终回答打印到终端,然后退出。适合脚本和 CI
dsh --profile <name>启动 $DSH_HOME/profiles/<name> 下的具名 profile(你自己组装的版本)
dsh plugin --profile <name> <pnpm 参数>管理某个 profile 的插件——本质是把参数转发给该 profile 目录里的 pnpm

webheadless 两个 profile 首次使用时会从内置模板自动初始化;其他 profile 要用 dsh plugin 创建。

参数的分界线

启动器只解析自己认识的 flag,第一个它不认识的 token 开始,后面全部交给被启动的应用去解析:

dsh --profile web --port 8080     # --port 是 web 应用的参数
dsh --profile headless "run the tests"
dsh --profile web --help          # 打印 web 应用的帮助,不是启动器的
dsh --help                        # 启动器自己的帮助
headless 的实战价值:它让 dsh 变成一个「可以在终端里调用的一次性 agent」。比如在 CI 里跑 dsh --profile headless "检查本次提交的文档链接是否有效,输出坏链清单"。会话照样持久化,回头可以在 Web UI 里翻记录。
一、基础篇 · 1.1 上手篇 · 第六步

看清你的插件树:--dump-config

「一切皆插件」不是口号,是可以打印出来的事实。这一章教你把它打印出来。

运行中的 dsh 是一棵插件树,由启动时按序叠加的配置层组合而成。想看你机器上实际会启动什么:

dsh --profile web --dump-config          # 打印最终组合出的配置树
dsh --profile web --dump-default-config  # 只打印内置组合包那几层

你会看到一长串条目:模型适配器、工具注册表、会话持久化、沙箱策略、Web 服务器……每一行都是一个插件条目,带着自己的 id 和 config。关键在官方那句话:

它打印出的任何条目,都可以由你自己的 patch 替换。

这就是 dsh 和「有插件机制的软件」的本质区别——后者是核心 + 插件挂载点,前者是整棵树都由同一种机制组成。怎么替换,是进阶篇 2.1 的主题;现在你只需要建立这个视觉印象:你的 agent 是一份可以逐行审查、逐行修改的清单。

排障第一招:以后遇到"为什么我的 dsh 行为和文档不一样",第一反应就是 --dump-config,看看是哪一层把配置改了。它相当于 dsh 世界的 git diff
一、基础篇 · 1.1 上手篇 · 第七步

越用越好的 10 个技巧

前六步是「能跑」。这十条是把 dsh 用顺手的经验清单,每条都有出处。

  1. 永远从演练目录开始。dsh 以启动目录为默认工作区根——第一次试新玩法,先 cd 进沙盒目录再启动。
  2. 模型配置是热生效的。换密钥、加提供方、改模型,下一次请求即生效,别浪费时间重启服务器。
  3. --dump-config 当体检。装了新插件、改了 patch 之后先 dump 一遍,确认改动落在了你以为的那一层。
  4. headless 是最好的「第二入口」。重复性任务写成一条 dsh --profile headless "...",扔进脚本或定时任务。
  5. 独立任务用独立会话。官方基准测试的纪律同样适用于日常:不相关的任务分开跑,需要延续上下文(包括持久 shell 状态)时才复用会话。
  6. 密钥只进凭据文件。API 密钥存 $DSH_HOME/.credentials.yaml,不要贴进对话里;对话是会持久化的。
  7. 会话日志是可审计资产。每个会话是一份 JSONL 日志,含组装后的模型请求与工具调用——出问题时它就是「黑匣子」。
  8. --patch 做实验。想试一个改动,用启动参数挂一个 patch 文件(2.1.2 详解),不满意删掉文件就还原,profile 本体不动。
  9. 找现成插件先看 dsh-plugin 话题。GitHub 上搜这个 topic,或直接翻本书配套的生态图谱页(3.1.1)。
  10. 想深入就跟官方教程走。仓库里有一套七课的 Cordis 教程(docs/cordis-tutorial/),从第一个插件到组合与热更新,全部动手向。
一、基础篇 · 1.2 认知篇 · 第 1 章

为什么 Agent 需要 Harness

模型能力每几个月上一个台阶,但「模型」和「能替你干活的系统」之间隔着一整层工程。这一层,就是 harness。

把一个大模型变成能安全干活的 agent,至少要补齐这些事:

  • 工具执行:模型说「我要读这个文件」,谁去真的读?读之前谁检查它有没有权限?
  • 会话与记忆:几十轮对话、几百次工具调用,怎么持久化、怎么回放、怎么在上下文超限时压缩?
  • 权限与沙箱:agent 要跑命令,怎么保证它只能碰工作区、碰不到你的系统盘?
  • 人机协作:什么操作先斩后奏、什么操作先请示?审批流放在哪一步?
  • 可观察性:任务跑了十分钟,中间发生了什么?哪一步花了多少 token?
  • 编排:子代理、后台任务、工作流、计划模式——多股工作怎么协调?

这些事和模型无关,但决定了 agent 能不能用、敢不敢用。业内把承担这层的系统叫 agent harness。你熟悉的 Claude Code、Codex 都是 harness;dsh 是 DeepSeek 给出的开源答案。

dsh 的差异化立场

同类 harness 大多是「产品优先」:功能围绕官方设定的形态生长,扩展靠预留的挂载点。dsh 反过来,把「可组装」放在第一位——先造一套让任何能力都能插拔的机制(Cordis),再用这套机制把产品拼出来。于是:

  • 官方拼出来的形态(Web UI、headless)只是参考组合,不是唯一形态;
  • 社区可以替换任何一层,做出终端 UI 版、企业定制版、教学精简版;
  • 连「agent 自己修改自己」都成为一等公民能力(2.3.4 章)。
本章要点:选 harness 本质是选「你和 agent 之间的工程契约」。dsh 的契约是:一切透明、一切可换、开源 MIT。代价是它还在开发者预览期,兼容性会破坏式演进——这笔账怎么算,读完 3.1.2 再下结论。
一、基础篇 · 1.2 认知篇 · 第 2 章

一切皆插件:没有特权内核

大多数软件的插件系统是「核心恩赐给外围的接口」。dsh 把这个关系拆了:核心自己也是插件。

运行中的 dsh = 一棵 Cordis 插件树(每个方块都是插件,都可替换) Cordis 上下文(ctx)· 服务容器 + 类型化事件 + 可逆副作用 插件通过 ctx 注册能力 · 卸载时自动回收 · 依赖通过 inject 声明 模型适配器ctx.llm 工具注册表ctx.tools 会话日志ctx.sessions 沙箱与审批sandbox / interaction Web UIhost / client Agent 主循环ctx.agentLoop —— 它也只是一个插件 子代理 · 任务 · 工作流subagent / jobs / workflow
图 2.1 「一切皆插件」:连 agent 主循环都是挂在 Cordis 上下文里的普通插件,可以整体替换

这个立场换来三件实事

① 扩展 = 挂插件,不是打补丁

官方原话:「扩展 dsh 的方式是把插件挂载到其他插件旁边,而各项注册都是副作用,会在其插件卸载时撤销。」你想改它的行为,不需要 fork 源码,把你的插件挂上去、或者用 patch 把某一行换掉即可。

② 自举:官方和你用的是同一套机制

官方组装 Web UI 用的组合文件格式,和你定制专属 agent 用的是同一种。系统对自己和对外部暴露同一个机制——这叫 dogfooding,也是「没有特权」的最硬证明。

③ 元能力:系统可以审视并修改自己

因为一切都是插件条目,agent 可以查看自己由哪些插件组成,甚至(在审批之下)动态挂载新插件、修改自己的组合。这是「自进化 agent」的机制基础,2.3.4 章专门讲。

类比记忆:传统软件像精装房——装修队预留了几个插座给你;dsh 像乐高底板——官方作品也是拼上去的,你可以拆任何一块换成自己的。插座模式的上限是厂商的想象力,底板模式的上限是社区的想象力。
一、基础篇 · 1.2 认知篇 · 第 3 章

Cordis 与时空组合性:一篇论文打的地基

「一切皆插件」谁都会喊,难的是插件卸得干净、装得上瘾。dsh 底层的 Cordis 框架为此配了一篇正式论文,把这件事从工程直觉变成了数学保证。

论文叫《A Programming Paradigm for Spatiotemporal Composability》(时空可组合性的编程范式),作者来自北京大学与 DeepSeek-AI。用大白话讲,它回答了动态插拔的两个根本难题:

时间维度:卸载一个插件,怎么保证擦干净?

想想 VS Code:禁用一个扩展要重启整个扩展宿主,因为运行中的代码留下的副作用(监听器、定时器、状态)没法安全撤销。论文给的答案叫可逆效应(revertible effects):每个副作用在产生时就带上自己的「逆操作」,运行时自动追踪;卸载插件 = 按序执行所有逆操作。关键定理证明了:组合效应的逆,可以由各原子逆自动推导——插件作者只需为最小操作提供撤销方式,整个插件的完整清理是框架结构性保证的,不靠作者自觉。

落到代码里就是你会在 2.2 章见到的 ctx.effect():注册时顺手返回清理函数,剩下的框架全包。

空间维度:插件之间的依赖,怎么随插拔自动重连?

论文的第二个机制叫响应式余效应(reactive coeffects):插件声明自己依赖哪些服务(dsh 里的 inject),运行时监控这些依赖的可用性——依赖到齐才激活,依赖被拔走就自动停用,提供方换了就自动重连。更讲究的是顺序保证:依赖者会先于提供方完成停用,且在自己收尾的全程还能用到那个依赖(比如关闭连接池时还能把连接还回去)。

合流性:折腾一万次,等于从头装一次

论文压轴的定理(合流性)翻译过来是:不管你运行中装了拆了换了多少次插件,系统最终静止的状态,和「按最终配置从零启动一次」完全一致——动态历史不留痕迹。这就是为什么 dsh 敢做配置热重载、敢让 agent 改自己的插件树:怎么折腾都不会「越用越脏」。

论文概念dsh 里的样子你得到的保证
可逆效应ctx.effect() / ctx.on() 自动回收插件卸载不留垃圾,不用重启
响应式余效应inject 声明依赖,就绪才启动加载顺序不用手排,热替换自动重连
合流性配置热重载 / HMR / patch 分层最终状态只由配置决定,与折腾路径无关

还有一个信心来源:Cordis 不是为 dsh 新造的实验品。它已经在开源聊天机器人框架 Koishi 里跑了四年,支撑着 4000 多个社区插件的生态——热插拔、依赖联动这套机制是被真实生态验证过的。dsh 相当于把一套久经考验的插件底盘,装到了 agent harness 这个新赛道上。

本章要点:读懂这三个词,进阶篇的一切设计都顺理成章——effect(副作用可逆)、inject(依赖声明)、合流性(怎么折腾都干净)。论文原文在 github.com/cordiverse/paper,88 页硬核数学,本章是它的五分钟版本。
二、进阶篇 · 2.1 组合篇 · 第 4 章

Profile 与组合包:一棵插件树的分层

你已经在 1.1.6 打印过自己的插件树。这一章讲清楚这棵树是怎么一层层叠出来的——这是定制 dsh 的全部原理。

两个核心名词:

  • 组合包(bundle):插件配置及其挂载代码的分发格式。官方内置三个:
    • dsh-base——每个 profile 的第一层:模型适配器、工具、持久化、沙箱与审批策略、设置、凭据、遥测;
    • dsh-web-app——在 base 之上增加浏览器应用;
    • dsh-headless——增加一次性运行器,完全不带服务器。
  • Profile:存放在 $DSH_HOME/profiles/<name> 的具名组装。目录里有 package.json(声明 dsh.profile.bundles 有序组合包列表 + 树外插件依赖)和 cordis.patch.yml(你自己的覆盖层)。
配置分层:后面的层可以按 id 替换前面任何一行 ① 组合包层:dsh-base → dsh-web-app(按 profile 声明的顺序) ② profile 的 cordis.patch.yml(这个 profile 自己的定制) ③ $DSH_HOME/cordis.patch.yml(机器级、跨 profile 的定制) ④ --patch overlay(启动参数临时挂载,实验专用) 自上而下依次应用在空条目列表之上 · 一条 patch 按 id 定位条目并替换其整个 config,或插入新条目
图 4.1 dsh 配置的四层叠加顺序:组合包 → profile patch → home patch → --patch overlay

这个分层设计的聪明之处:组合包插入的内容,始终可以被它上面的任何一层 patch 掉。官方升级组合包不会覆盖你的定制,你的定制也不用碰官方的文件——两边永远在不同的层里。

对照理解:玩过 Docker 的想想镜像分层,玩过前端的想想 CSS 层叠——同样的思想用在了「组装一个 agent」上。你要记的只有一句:想改什么,就在更高的层里按 id 覆盖它
二、进阶篇 · 2.1 组合篇 · 第 5 章

Patch 覆盖:不 fork 就能改一切

上一章讲了层,这一章动手写 patch。三种典型操作:插入一个插件、替换一行配置、临时做实验。

操作一:插入你的插件(--patch 实验层)

写一个最小的 patch 文件(YAML),用 insert 插入新条目:

# my-overlay.yml
- insert:
    - id: hello
      name: '/absolute/path/to/your-plugin.ts'

挂着它启动:

dsh web --patch ./my-overlay.yml

不满意?去掉 --patch 参数就完全还原。这是最安全的实验方式——profile 本体一个字节都没动。

操作二:持久化定制(profile / home 层)

实验满意后,把同样的条目并入 $DSH_HOME/profiles/web/cordis.patch.yml(只影响 web profile)或 $DSH_HOME/cordis.patch.yml(影响这台机器所有 profile)。patch 的语义:按 id 定位某个条目并替换其整个 config,或插入新条目。也就是说你可以精确地把官方树里任何一行换成自己的实现——比如换掉某个工具、某个模型路由策略。

操作三:条目里的动态表达式

配置文件支持 !!js 表达式节点:条目的 config 会在其声明的注入激活后、基于插件上下文插值,disabled 字段则在每次挂载决策时基于 loader 上下文插值。这让「按环境开关插件」「引用运行时值」成为配置层的能力。官方建议:由环境选择插件时,优先用 overlay 而不是复杂表达式。

纪律:每加一层定制,就跑一次 dsh --profile web --dump-config 验证结果。分层系统的调试铁律是「相信打印出来的最终态,不要相信自己对层叠顺序的记忆」。
二、进阶篇 · 2.1 组合篇 · 第 6 章

Agent 预设:组装你的专属 agent

前两章定制的是「整个 dsh 进程」。这一章的颗粒度更细:按会话组装 agent——同一个 dsh,不同会话可以跑完全不同配置的 agent。

dsh 的 preset 包提供了这个能力:由 preset 的 cordis.yml 按会话组装 agent。也就是说,一个 agent 预设本质上就是一份组合文件——和官方组装整个宿主用的是同一种机制。这正是 1.2.2 讲的「自举」:

  • 宿主组合持有跨会话共享的能力:注册表、持久化、模型路由、子代理后端;
  • Agent 预设持有单个会话的贡献:这个 agent 有哪些工具、什么人设、哪些提示词片段。

「某个能力应该放宿主层还是预设层」是用 dsh 做定制时的一等架构决策。判断标准很朴素:要跨会话共享、要持久化的,放宿主;只属于某类任务角色的,放预设

官方给的参考样本

仓库 examples/ 里有多个可以直接研究的组合:例如 jsonrpc-agent 的 minimal 组合——一个只带持久 bashstr_replace_editor 两个工具、关闭上下文压缩的极简编码 agent(2.4.2 章会跑它)。读懂一份 minimal 组合,你就有了搭建自己预设的起点:从最小集合开始,一行一行往上加。

实战思路(从 WorkBuddy 方法论迁移过来):把「专家」理解为「预设」——研究员 = 搜索/抓取工具 + 研究方法提示词;重构师 = 文件/LSP 工具 + 代码规范提示词。在 dsh 里,一个专家就是一份 cordis.yml,版本管理、评审、分发都走文件,这比在网页里维护提示词模板要工程化得多。
二、进阶篇 · 2.2 开发篇 · 第 7 章

Cordis 五个核心概念

写插件之前,五个概念先立住。这五条来自官方 Cordis 入门文档,是全部插件开发的世界观。

  1. 插件是实现 Service 的对象。可以是一个带可选 injectapply(ctx) 的函数,也可以是一个 Service 子类,生命周期由 Cordis 挂到当前上下文。
  2. 上下文是服务的容器。一个服务占据一个稳定的 ctx.<key>(如 ctx.toolsctx.llmctx.sessions);其他插件通过 key 查找服务,而非导入具体实现。
  3. 通过 inject 声明服务依赖。插件声明所需服务后,会等这些服务就绪才启动——加载顺序通过依赖表达,不用手动编排。
  4. 类型化事件用于通信。事件按四种模式分发(下表),分别对应观察、包装、并行扇出、按序执行。
  5. 注册是可逆的副作用。提示词片段、工具 schema、适配器、监听器都通过 ctx.effect()ctx.on() 安装,reload 和 teardown 时按预期撤销。

四种事件分发模式

模式是否 await分发顺序有无返回值典型用途
emit按注册顺序观察广播通知
waterfall按注册顺序包装拦截 / 改写(中间件)
parallel并行并发扇出
serial按注册顺序执行顺序检查点

其中 waterfall 最重要(agent 的关键扩展点都是它):监听器拿到 (...args, next),调用 next() 才委托给下游;不调用直接返回就是短路。协作式监听器改共享对象后委托,策略式监听器在拥有决策权时直接短路——这是设计意图,不是坑。

实践规则(官方版):把行为封装为插件——工具流水线的事归 ctx.tools,模型流式输出归 ctx.llm;拦截和策略优先用事件,直接能力调用优先用服务方法;每个注册都要有对应的清理(disposer),teardown 有顺序要求的资源放同一个 effect 里。
二、进阶篇 · 2.2 开发篇 · 第 8 章

第一个插件:apply(ctx) 十行起步

跟官方教程走一遍最小插件,从建文件到在 Web UI 里生效,全程五分钟。前置条件:完成 1.1.2 的「从源码运行」。

① 建目录和插件文件

mkdir -p scratch-plugin/src

创建 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!')
}

一个插件就是「导出 apply 函数的 TypeScript 模块」——框架加载时调用 apply 并传入 ctx,你通过 ctx 注册一切能力。这就是完整结构,没有隐藏的样板代码。

② 写一个 overlay 把它插进去

创建 scratch-plugin/cordis.yml(插件路径必须是绝对路径):

- insert:
    - id: hello
      name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts'

③ 挂着 overlay 启动

pnpm dsh web --patch ./scratch-plugin/cordis.yml

打开 http://127.0.0.1:3080,启动期间终端会打印 [hello-plugin] plugin loaded!。恭喜,你的代码已经和官方插件运行在同一棵树里、享受同样的待遇。

下一步去哪:仓库里的 docs/cordis-tutorial/ 有完整七课——第一个插件 → 生命周期与效应 → 服务 → 事件 → 配置 → 组合与 HMR → 进入 harness。本书接下来两章覆盖其中最常用的部分。
二、进阶篇 · 2.2 开发篇 · 第 9 章

依赖、副作用与配置:插件的三块肌肉

Hello world 之后,真实插件靠三样东西干活:inject 拿到别人的服务,effect 管好自己的资源,config 接受用户的定制。

① inject:声明依赖,就绪才启动

import type { Context } from '@deepseek-ai/cordis'

export const name = 'my-tool-plugin'
export const inject = ['tools']

export function apply(ctx: Context) {
  // 运行到这里时,ctx.tools 一定已就绪
  ctx.tools.register(/* ... */)
}

这一行 inject 背后就是 1.2.3 讲的「响应式余效应」:框架保证依赖到齐才调用你的 apply,依赖被卸载时你的插件也会被正确停用——顺序问题从此不归你管。

② effect:有借有还的副作用

通过 ctx 注册的东西(事件监听、工具、定时器)卸载时自动清理。自己管理的资源,用 ctx.effect() 告诉框架怎么还:

export function apply(ctx: Context) {
  ctx.effect(() => {
    const timer = setInterval(() => {
      console.log('heartbeat')
    }, 5000)
    // 返回的函数会在插件卸载时执行
    return () => clearInterval(timer)
  })
}

这就是「可逆效应」的代码形态。养成习惯:凡是打开的,注册时就写好怎么关。做到这一点,你的插件天生支持热插拔和 HMR。

③ config:把可调参数交给条目

插件条目里的 config 字段会传给插件,用户在 patch 里就能定制你的行为:

- insert:
    - id: hello
      name: '/absolute/path/to/my-plugin.ts'
      config:
        greeting: '你好'

官方约定是「无硬编码的可调参数」——任何值得调的东西都应该走 config 暴露出去,配置错误则响亮失败。具体的 schema 声明方式见官方 docs/user/develop/basic/config 文档。

三块肌肉的关系:inject 是「我需要什么」,effect 是「我留下了什么、怎么收回」,config 是「我可以被怎么调」。把这三件事说清楚的插件,就是生态里受欢迎的好公民。
二、进阶篇 · 2.2 开发篇 · 第 10 章

发布与被发现:dsh-plugin

插件写完,走完最后一公里:发出去、让别人装得上、找得到。

发布三件事

  1. 发包:把插件发布为 npm 包(官方包用 @deepseek-ai/dsh-* 命名空间;社区包用你自己的名字即可)。
  2. 打标:给插件的 GitHub 仓库加上 dsh-plugin 话题——这是官方指定的被发现渠道。
  3. 写清楚 README:官方对自家包的要求值得抄——用途、API、扩展点、已知限制,一个不少。

用户怎么装你的插件

dsh 的插件安装走 profile 机制:dsh plugin --profile <name> ... 会把参数转发给该 profile 目录里的 pnpm,包会装进 profile 自己的 node_modules;然后在 profile 的 cordis.patch.yml 里插入条目启用它。树外插件与 dsh 本体完全隔离——卸载 = 删条目 + 删依赖,干干净净。

能写什么类型的插件

官方 cookbook(docs/cookbook/)给了几条现成路线:

  • 加一个工具(adding-a-tool):给 agent 一个新动作,比如调用你公司的内部 API;
  • 加一个 LLM 适配器(adding-an-llm-adapter):接入一个新模型提供方;
  • 加一个会话节点(adding-a-conversation-node):在 Web UI 对话流里渲染新的卡片类型;
  • 加一个包 / vendor 包:向 dsh 本体贡献代码的规范路径。
生态位建议:预览期生态刚起步,最缺的是「垂直场景插件」——行业工具集、企业内网适配、领域预设。写通用能力你要和官方赛跑,写垂直场景你就是唯一玩家。配套的生态图谱页(3.1.1)可以帮你看清现在的空位。
二、进阶篇 · 2.3 机制篇 · 第 11 章

轮次与步骤:一次对话的完整旅程

你在 Web UI 里发一句话,到 agent 回你一个结果,中间发生了什么?看懂这条流水线,你就能在任何一个环节上挂自己的逻辑。

dsh 的执行单位有两级:步骤(step)= 一次模型请求加上它调用的工具;轮次(turn)= 零个或多个步骤——在领取首条输入前打开,在不再欠任何工作时关闭。

turn/start agent/pre-step step/start 组装提示词+工具 agent/request → llm/stream assistant/chunk* tool/call* → tools/execute tool/result* step/end (还有欠账?再来一个 step) turn/end

几个关键节点的含义:

节点类型你能在这做什么
agent/pre-stepwaterfall步骤的守门员:可以拒绝这一步、改写进入的消息。上下文压缩就在这里处理压力
agent/request / llm/streamwaterfall模型请求的组装与流式过程:改请求参数、拦截或改写流
tools/pre-execute → execute → post-executewaterfall工具执行三段:前置检查(审批就在这类位置生效)、执行、后处理
agent/turn-stoppingserial轮次收尾检查点:最后的机会决定要不要续

注意流水线上的事件分两类:turn/*step/*user/messageassistant/*tool/*持久会话事件——写进日志、可回放;其余是实时扩展点——挂逻辑用的。waterfall 事件的监听器必须调 next() 才委托下去,这是 2.2 学过的语义在真实战场上的应用。

本章要点:dsh 没有「魔法主循环」——整条流水线由公开事件串成,每个环节都可拦截、可替换。想做审计插件?监听持久事件。想做策略插件?挂 waterfall。这就是「agent loop 也是插件」的具体含义。
二、进阶篇 · 2.3 机制篇 · 第 12 章

事件三域:会话 · Agent · 能力

「事件就是扩展点,而选对事件域是大多数改动的第一个决定。」——官方架构文档的这句话,是插件设计的第一课。

事件域是什么什么时候用
会话事件追加到日志并通过 session/event 广播的持久事实某个事实必须在重新加载后仍然存在时(审计、回放、SDK 消费 transcript)
Agent 事件
agent/*
携带活跃 Agent 的实时协调:inbox、步骤、状态、请求、续跑要观察或拦截进行中的工作时(steering、请求改写、错误处理)
能力事件
fs/* tools/* telemetry/*
挂在某个能力接缝上的策略与适配,无需进入主循环给文件系统加策略、给工具执行加把关、接遥测

判断口诀:要留痕 → 会话事件;要干预 → agent 事件;要给某个能力加规则 → 能力事件。官方还维护了一份「事件生产方/消费方映射表」(docs/event-producer-consumer.md),查某个事件谁发谁听,比读源码快得多。

给 SDK 用户的一条铁律

需要可回放 transcript 数据的,消费 session/eventagent/* 只用于实时协调。把实时事件当持久数据用,重启后你的数据就没了。

二、进阶篇 · 2.3 机制篇 · 第 13 章

核心服务地图:ctx 上都挂了什么

写插件时你会不断问一个问题:「这件事该找哪个服务?」这一章是答案的速查版。

主干服务(core)

职责ctx 键
core/session仅追加的 SessionEvent 日志和存储ctx.sessions
core/system-prompt提示词片段与工具 schema 的组装ctx.systemPrompt
core/tools作用域化的工具注册表和带把关的执行流水线ctx.tools
core/agentAgent 接口、活跃 agent 注册表和 agent/* 事件ctx.agents
core/agent-loop实现该接口的默认驱动器(可替换!)ctx.agentLoop
llm/llm消息与流式词汇表 + 适配器接缝ctx.llm

能力系列(按「接缝 + 实现 + 面向模型的工具」组织)

dsh 的能力包大多遵循同一个三件套模式:Service Definition(接缝定义)+ Service Provider(具体实现)+ Consumer(面向模型的工具),三个角色可独立演进——这是「换实现不换接口」的关键。主要的能力系列:

系列提供什么
fs / shell / terminal文件系统、一次性 Bash、持久 PTY——agent 的手
web搜索 / 网页获取——agent 的眼
lsp语言服务器接入,代码智能
sandbox进程限制接缝:bwrap / Landlock / Seatbelt 后端
interaction人机协作平面:审批接缝、权限预设、询问用户的工具
subagent / jobs / workflow子代理委托、后台任务(job_* 工具)、工作流引擎(workflow / ralph 工具)
skill / todo / plan / goal技能目录与加载、todo_write、计划模式、会话目标
compaction / spill / guard上下文压缩、超大结果外溢存储、循环卫生守卫(重复调用提醒、执行超时)
session-query会话检索:全文搜索、血缘、语义过滤

完整清单见附录。官方有一条依赖纪律值得所有插件作者遵守:扩展插件依赖 Service Definition,绝不依赖具体提供方——这样当用户把本地实现换成远程实现时,你的插件不用改一行。

二、进阶篇 · 2.3 机制篇 · 第 14 章

自我修改:agent 给自己装插件

这是 dsh 最有未来感的一章:因为一切皆插件,「agent 修改自己」不再是科幻,而是一个有审批、有回滚的工程流程。

dsh 的 extensions 包提供「agent 运行时自修改」能力,官方描述是两句话:实时插件/服务检查 + 模型所写插件的挂载/卸载。拆开看:

  • 自省:agent 可以查询自己当前由哪些插件组成、有哪些服务和事件——「我是谁、我有什么」对模型可见;
  • 自改:agent 可以起草一个新插件(它自己写代码),经过审批后挂载进自己的运行时;不满意可以卸载回滚。整个过程有完整的生命周期管理。

为什么这在 dsh 上是安全的

回到 1.2.3 的三个保证:可逆效应保证挂载的插件卸得干净;响应式依赖保证新插件与现有插件的连接自动理顺;合流性保证折腾多少次系统状态都等价于从头组装。Cordis 论文的结语其实就点了这个方向:自进化 agent harness 是这套数学最重要的应用场景——每一次自我修改都是一次动态组合,没有时空组合性的保证,频繁自改会把系统改成废墟。

务实提醒:自修改能力务必配合审批策略使用,并且先在演练环境玩。它是「预览期最值得关注的方向」而不是「今天就该在生产用的功能」。关注它的意义在于:这条能力线走通之后,「agent 持续为自己长出新工具」会成为常态,而你已经懂它的机制了。
二、进阶篇 · 2.4 自动化篇 · 第 15 章

Headless:不开浏览器跑任务

Web UI 适合协作和观察,自动化场景要的是「一条命令进,一个结果出」。headless profile 就是为此存在的。

dsh --profile headless "Inspect the repository and fix the failing tests."

行为语义:新起一个持久化会话,跑完这一个任务,把最终回答打印到终端,然后退出。它由 dsh-headless 组合包组装——在 dsh-base 之上加一个一次性运行器,完全不带服务器。

三个典型接法

A · 定时巡检

crontab / 计划任务里跑:dsh --profile headless "检查 docs 目录所有链接有效性,输出坏链清单到 report.md"

B · CI 里的智能检查

流水线步骤:dsh --profile headless "审查本次变更的 SQL 迁移脚本是否有破坏性操作,有则非零退出"

C · 批处理

shell 循环喂任务列表,每个任务独立会话,事后在 Web UI 里统一翻记录复盘。

headless 和 web 共享同一个底座(dsh-base),所以模型配置、凭据、权限策略都是通的——配一次,两个入口都能用。会话照样落盘,自动化跑的活也留完整档案。

与技巧 5 呼应:批量自动化时严格「一任务一会话」。会话里的持久状态(比如 shell 工作目录、环境变量)会跨调用保留,混用会话会让任务互相污染。
二、进阶篇 · 2.4 自动化篇 · 第 16 章

Python SDK:把 harness 当库用

如果你的自动化生活在 Python 世界(数据管线、评测脚本、内部平台),官方 Python SDK 让你直接 import 一个 harness。

安装

python -m venv .venv
. .venv/bin/activate
python -m pip install deepseek-harness-sdk

要求 Python 3.10+;支持 Linux x64 / arm64 与 macOS 14+ (arm64)。SDK 自带同版本的内置运行时,不需要系统装 Node.js。凭据走环境变量:

export DEEPSEEK_API_KEY=sk-your-key-here
# 走 OpenAI 兼容代理时:export DEEPSEEK_BASE_URL=http://127.0.0.1:8000/v1

核心 API:一个上下文管理器

from pathlib import Path
from deepseek_harness import DeepSeekHarness

config = Path("examples/jsonrpc-agent/minimal.cordis.yml").resolve()

with DeepSeekHarness(
    provider="deepseek-official",
    model="deepseek-v4-flash",
    max_tokens=49_152,
    cwd="/absolute/path/to/workspace",       # agent 的工作区
    session_root="/absolute/path/to/sessions",  # 会话日志目录
    cordis=str(config),                      # 用哪份组合
) as harness:
    result = harness.run(
        "Inspect the repository and fix the failing tests.",
        session_id="example-001",
    )

print(result.final_response)

注意 cordis= 参数——SDK 调用方直接指定 agent 组合,2.1 学的组合能力在这里变成了 Python 的一个参数。官方示例用的 minimal 组合值得记住它的形状:

属性minimal 组合的取值
面向模型的工具仅持久 bashstr_replace_editor 两个
Bash 超时 / 编辑器输出上限300 秒 / 16,000 字符
上下文压缩关闭
会话持久化session_root 下未压缩 JSONL
权限danger-full-access——只能在可丢弃的检出或容器里跑!

复用同一个 harness 与 session id 会保留该会话的 Bash 进程(工作目录、导出变量、shell 函数都在);独立任务用新 session id。官方基准测试(BENCHMARK.md)跑的就是这套 minimal 变体。

两个硬限制:① minimal 组合是 danger-full-access + 裸文件系统,agent 能改运行时进程可达的任何路径——务必容器或一次性检出;② 持久 PTY 后端需要 POSIX 终端,这套组合不支持 Windows 上跑 agent(Windows 用户建议 WSL 或远程 Linux)。
二、进阶篇 · 2.4 自动化篇 · 第 17 章

协议与桥:RPC · ACP · MCP · hooks

除了 Web UI 和 Python SDK,dsh 还准备了一组「接口面」,让它能被程序驱动、与其他 agent 工具互通。挑你需要的用。

接口面包 / 示例干什么用
JSON-RPC SDKpackages/sdk · examples/jsonrpc-agent进程外运行时 SDK:JSON-RPC 协议 + TypeScript 客户端 + 服务器插件。Python SDK 底下走的就是它;其他语言可按协议自接
ACP 服务器packages/acp · examples/acp-agent面向自动化的 Agent Client Protocol 服务器——用支持 ACP 的客户端 / 编辑器驱动 dsh
MCPpackages/mcp · examples/mcp-memoryModel Context Protocol 接入:示例演示把 MCP 记忆服务器接进 harness,让 agent 获得外部记忆能力
hooks 桥packages/hooks钩子桥接 + 共享的 Claude Code / Codex 线协议库——与既有 agent 工具链的互操作层
无头运行器examples/headless-agent非交互 agent 的参考实现,配自动化剧本用

这张表传递的信号比每一行本身更重要:dsh 不打算做孤岛。它把「被集成」当成一等需求——你可以把它塞进任何一个已有的自动化体系,也可以让它和 Claude Code / Codex 系的工作流并存互通。

选型速判:Python 世界 → Python SDK(2.4.2);Node/TS 或其他语言 → JSON-RPC SDK;已有支持 ACP 的编辑器/客户端 → ACP;想给 agent 挂外部记忆/工具服务器 → MCP;从 Claude Code / Codex 迁移或混用 → 关注 hooks 桥。
三、生态篇 · 3.1 生态与社区 · 第 18 章

插件生态地图

「一切皆插件」的最终兑现,不在架构图里,在生态里。这一章告诉你现在的生态长什么样、怎么逛、空位在哪。

官方指定的发现机制:一个 GitHub 话题

dsh 生态的目录不在某个中心化市场里,而在 GitHub 话题 dsh-plugin 上——官方 README 明确请插件作者给仓库打这个标。这个选择很「dsh」:去中心化、零审核门槛、天然带 star/issue/README 等信任信号。逛生态就三步:

  1. GitHub 搜索 topic:dsh-plugin,按 star 或更新时间排序;
  2. 读 README 看它注册了什么(工具?适配器?UI?预设?)、依赖哪些服务;
  3. 用 2.2.4 的方式装进一个演练 profile 先试。

本书配套:两张生态图

为了看得更直观,本书配了两张基于 topic:dsh-plugin 数据的交互页(与本书同目录,可离线打开):

生态知识图谱

插件之间的关系网络:谁依赖谁、哪些能力扎堆、哪些孤岛待连接。适合找「生态空位」。

生态 Dashboard

插件清单的看板视图:分类、活跃度、作者分布。适合做选型和跟踪生态节奏。

读生态的三个视角

  • 用户视角:先看「工具类」和「预设类」插件——它们决定你的 agent 能干多少活;
  • 开发者视角:看「适配器类」(模型、沙箱、存储的替代实现)——它们标记了接缝的成熟度;
  • 投资视角:数一数垂直行业插件的数量——现在还很少,这正是 2.2.4 章说的机会窗口。
三、生态篇 · 3.1 生态与社区 · 第 19 章

社区、贡献与预览期注意

开源项目的可持续性看社区。这一章讲清楚参与渠道,以及在开发者预览期使用它的正确姿势。

参与渠道

渠道用途
GitHub Discussions官方指定的反馈与 bug 报告入口
dsh-plugin 话题发布插件、被生态发现
企微群 / 微信公众号中文社区:仓库 README 有企微小助手与入群问卷二维码
Discord国际社区(英文 README 提供邀请链接)
CONTRIBUTING.md代码贡献规范;docs/development.mddocs/architecture.md 是改代码前的必读

一个值得注意的细节:仓库根目录有 AGENTS.md(还有面向 Claude 的 CLAUDE.md)——这个代码库从第一天起就是「为 agent 协作而组织的」,官方开发指南甚至建议用 agent 来探索代码库。用 dsh 开发 dsh,是官方自己的日常。

预览期使用姿势

  • License 放心:MIT,第三方依赖许可证在 THIRD_PARTY_NOTICES.md 里完整披露;
  • 兼容性谨慎:官方明说会有破坏性变更——你的 patch、插件、SDK 集成要做好跟版本走的准备;
  • 生产环境克制:预览期适合评估、内部工具、实验性集成;对外服务再等等;
  • 升级纪律:升级后先 --dump-config 对比插件树,再跑你的回归任务清单。
怎么判断它的演进方向:盯三个信号——① 组合包的拆分粒度(越细说明接缝越稳定);② extensions 自修改能力的开放程度(决定自进化叙事的兑现速度);③ 生态图谱里适配器类插件的增长(决定「可替换」从理论变现实的速度)。
三、生态篇 · 3.2 两层世界 · 第 20 章

应用层与 Harness 层:什么时候用哪个

读过《WorkBuddy 实战绿皮书》的朋友一定会问:我已经在用 WorkBuddy 这类 AI 工作台了,dsh 和它是什么关系?答案是:不是竞争关系,是上下层关系。

应用层(WorkBuddy 这类 AI 工作台)Harness 层(dsh 这类底座)
面向谁业务人员、不写代码的实干者开发者、技术团队、产品构建者
交付什么开箱即用的任务、专家团、自动化可组装的运行时:插件树、接缝、协议
定制方式装 Skill、配专家、写自动化规则写插件、叠 patch、组预设
类比整车:上车就开底盘 + 发动机:造你自己的车

三种人的行动建议

业务实干者
继续用好应用层

你的主战场还是 WorkBuddy 绿皮书那套:任务五要素、专家团、自动化闭环。读这本书的价值是「知其所以然」——理解了 harness 层,你对应用层产品的能力边界和选型判断会准得多。

技术团队 / 开发者
评估 dsh 作为自建底座

如果你在给公司搭内部 agent 平台,dsh 给了你一个「不用从零造、又处处可改」的起点:接内部模型网关(2.1)、加内网工具(2.2)、配权限策略、用 SDK 嵌进现有系统(2.4)。

产品构建者
在 harness 层上长应用层

应用层产品的护城河正在从「会调模型」转向「场景 + 数据 + 信任」。用 dsh 这类开源底座省下运行时的成本,把力气全部押在你的场景上——这是这一波开源 harness 给创业者的真实红利。

最后回到本书反复出现的那条线:模型在快速变强,harness 在快速开源,真正稀缺的是「把它们落进真实业务的人」。上一本绿皮书讲怎么落地应用层,这一本讲怎么理解和驾驭底座层——两层都通的人,会是接下来几年最值钱的角色。

附录

命令速查 · 目录速查 · 包清单 · 名词表

A. 命令速查

命令作用
npx @deepseek-ai/dsh web启动 Web UI(默认 http://127.0.0.1:3080)
dsh --profile headless "任务"无头跑一个任务,打印最终回答后退出
dsh --profile <name>启动具名 profile
dsh plugin --profile <name> <pnpm 参数>管理 profile 的插件(转发给 pnpm)
dsh --profile web --dump-config打印最终组合的插件树(排障第一招)
dsh --profile web --dump-default-config只打印内置组合包层
dsh web --patch ./overlay.yml挂临时 overlay 启动(实验用)
dsh --profile web --port 8080启动器后的参数交给 web 应用解析
pnpm install && pnpm run build && pnpm dsh web源码方式构建并运行
pip install deepseek-harness-sdk安装 Python SDK(自带运行时,免 Node)

B. 目录与文件速查

路径是什么
$DSH_HOME/profiles/<name>/具名 profile 目录(web、headless 首次使用自动初始化)
…profiles/<name>/package.jsonprofile 清单:dsh.profile.bundles 组合包列表 + 树外插件依赖
…profiles/<name>/cordis.patch.yml该 profile 的用户覆盖层
$DSH_HOME/cordis.patch.yml机器级覆盖层(跨 profile 生效)
$DSH_HOME/.credentials.yamlAPI 密钥等凭据(只写,UI 不回显明文)
$DSH_HOME/settings.yaml用户设置(如自定义提供方的模型模态声明)
会话目录(如 SDK 的 session_root每会话一份 JSONL 日志:组装后的模型请求与工具调用,可回放可审计
启动 dsh 时所在目录默认工作区根

C. 包分组清单(精选)

npm scope 统一为 @deepseek-ai/dsh-*;完整表见仓库 packages/README.md

职责
core/产品 API 主干:会话、提示词、工具、agent 服务与默认循环
llm/LLM 能力系列:抽象服务 + 提供方适配器
fs/ shell/ terminal/文件系统、Bash、持久 PTY 能力系列
web/ lsp/ skill/搜索与网页获取、语言服务器、技能系统
sandbox/ interaction/进程限制(bwrap/Landlock/Seatbelt)、审批与权限预设
subagent/ jobs/ workflow/子代理委托、后台任务、工作流引擎
session/ session-query/会话持久化(JSONL/SQLite)、检索与全文搜索
compaction/ spill/ guard/上下文压缩、超大结果外溢、循环卫生守卫
todo/ plan/ goal/ schedule/待办工具、计划模式、会话目标、会话内定时
preset/ bundle/ boot/按会话组装 agent、可安装补丁层、启动粘合
settings/ credentials/ storage/ workspace/设置、凭据、非会话存储、工作区实体
host/ client/ api/ typert/Web GUI 宿主半侧与浏览器半侧、RPC 网关、类型图
sdk/ acp/ mcp/ hooks/JSON-RPC SDK、ACP 服务器、MCP 接入、Claude Code/Codex 桥
extensions/agent 运行时自修改:插件自省 + 模型所写插件挂载/卸载
subprocess/ code-runtime/ e2b/子进程能力、代码执行(Code Mode)、E2B 沙箱(POC)
attachment/ feedback/ identity/ context/附件存储、人类反馈、匿名身份、模型可见请求上下文

D. 名词表

  • Agent Harness:智能体运行环境——工具执行、会话、权限、编排、观测这一整层工程。
  • 一切皆插件:dsh 的架构立场——产品每一部分(含 agent 主循环)都是可替换的插件,没有特权内核。
  • Cordis:dsh 底层的插件框架,设计对应论文《A Programming Paradigm for Spatiotemporal Composability》。
  • 时空组合性:时间维度 = 插件卸载时副作用可完全回收(可逆效应);空间维度 = 插件间依赖随插拔自动重连(响应式余效应)。
  • 合流性:无论运行中怎样装拆插件,最终静止状态等价于按最终配置从零启动——「动态历史不留痕迹」。
  • ctx(上下文):服务的容器;插件经由 ctx 查找服务、注册能力。
  • inject:插件对所需服务的声明;服务就绪才启动。
  • effect:可逆副作用的注册方式;返回清理函数,卸载时自动执行。
  • waterfall:环绕中间件式的事件分发;监听器调用 next() 委托,不调用即短路。
  • Profile:$DSH_HOME 下的具名组装(组合包列表 + 用户 patch)。
  • 组合包(bundle):插件配置及挂载代码的分发格式(dsh-base / dsh-web-app / dsh-headless)。
  • Patch / Overlay:按 id 替换或插入插件条目的配置层;--patch 为启动时临时层。
  • Agent 预设(preset):按会话组装 agent 的 cordis.yml——一份「专属 agent」的完整描述。
  • 轮次 / 步骤(turn / step):执行单位——步骤 = 一次模型请求 + 其工具调用;轮次 = 零到多个步骤。
  • 会话事件:追加进日志的持久事实,可回放;与实时的 agent/*、能力事件相区分。
  • headless:无服务器的一次性运行模式——一条命令,一个会话,一个结果。
  • danger-full-access:全放开权限档位;仅限可丢弃环境使用。
  • dsh-plugin:GitHub 话题,插件生态的官方发现机制。
联系作者

找到雷神

读完有想法想聊、想交流 dsh 与 AI 落地实战、或想第一时间收到本书和生态图谱的更新——扫下面两个码。

加雷神个人微信
一对一交流 · 添加时请注明「dsh 绿皮书」
雷神个人微信二维码
关注微信公众号
人力资源数字化探索 · AI 落地实战内容首发
微信公众号「人力资源数字化探索」二维码
姊妹篇《各行各业 AI 落地实战 · WorkBuddy 实战绿皮书》:workbuddy.leishenai.eu.cc——应用层怎么落地,那本讲得更细。