如果你在 2026 年还在纠结“到底哪个模型写代码更强”,那你可能已经错过了这一年最重要的工程转向。深度求索(DeepSeek AI)在 2026 年 8 月正式开源了 DeepSeek Harness(命令行名 dsh),它抛出的公式是 Agent = Model + Harness,口号是 Everything is a Plugin.(一切皆插件)。这不是又一个“封装几个 agent 的库”,而是一整套围绕模型运行环境搭建的插件化基础设施:模型、工具、技能、会话、沙箱、存储、循环、调度、UI 全部由插件组合,配置层即可替换,无需改动源码。本文分上下两篇,上篇先把“为什么需要 Harness”“dsh 是什么”“一切皆插件到底怎么落地”讲透,包括 Cordis 内核、无特权内核、Profile + 组合包 + patch 的四层叠加顺序、四种运行模式,并给出可直接粘贴运行的命令与代码;下篇再进入插件开发、事件驱动扩展点与实战工作流。
Agent = Model + Harness:为什么 2026 年的瓶颈从模型智能转向运行环境
先看官方那句话的完整表述:模型是 Agent 的灵魂,而 Harness 给予 Agent 理解环境、使用工具、在真实场景中持续工作的能力。这句话把职责切得很干净。模型负责“想”,它决定下一步该做什么、写什么代码、调用哪个工具;Harness 负责“活”,它把模型的意图翻译成对文件系统、终端、检索服务、子 Agent 的真实操作,并把操作结果重新组装成模型能理解的上下文,再送回去进入下一轮。灵魂再聪明,如果没有人给它手脚、记忆和感官,它在真实项目里连一次 git status 都跑不了。
这正是公式的深意:Agent 不是模型,Agent 是模型加驾驭层。当模型能力在 2023 到 2025 年间快速拉齐之后,行业里越来越多团队发现,同一颗模型换个运行环境,产出质量能差出一大截。素材里给了两个很有说服力的旁证:其一是 OpenAI 团队在 100 万行代码实验中的记录——5 个月里产出的全部代码都由 Agent 完成,工程师一行代码未写;其二是 LangChain 的对照实验——只优化外部驾驭环境(文档结构、验证回路、追踪系统),编码 Agent 在 Terminal Bench 2.0 上的得分就从 52.8% 提升到 66.5%,全球排名从第 30 位跃升到第 5 位,而底层模型一个参数都没动。
把这两件事放在一起,结论就非常直白:瓶颈不在模型智能,而在基础设施。模型再强,如果上下文喂得乱、工具调用没有校验回路、出错没有可观测的追踪,Agent 就是一个“看起来聪明、用起来翻车”的黑盒。反过来,一个普通的模型如果被放进约束清晰、反馈及时、状态可回溯的环境里,也能稳定地跑完整条工程链路。这就是为什么 2026 年的讨论焦点从“模型排行榜”转向了“Harness 怎么做”。

dsh 的官方定位也印证了这一点:它不优化模型本身,而是优化模型运行的环境。这句话看起来像营销语,但落到代码层面非常具体——它把模型运行所需的约束、反馈、工具、记忆、可观测性,全部做成可组合的插件基础设施,让每个团队都能按自己的方式驾驭 AI,而不是被厂商锁定在固定功能的黑盒里。对入门读者来说,理解这一层最关键的心态转变是:你不再是在“调用一个模型”,而是在“配置一个运行环境”。你要关心的不是 prompt 第几个字怎么改,而是这个环境里有哪些能力、它们怎么协作、出错时你怎么看到发生了什么。
也正因为是运行环境而非模型,dsh 天然带着几个工程属性:能力可插拔、状态可回放、配置可审查、模型可替换。这些属性会在下面每一节里反复出现,因为它们不是零散特性,而是同一个设计决策的不同侧面。理解了“Agent = Model + Harness”,后面所有“为什么插件化”“为什么无特权内核”“为什么要 dump-config”的问题都会迎刃而解。
从 Prompt 到 Context 再到 Harness Engineering:三次范式跃迁的优化对象对照
要真正理解 Harness 为什么重要,得先看清楚我们是怎么一步步走到这里的。这门手艺经历了三次范式跃迁,每一次的共同点都是:上一代方法并没有错,只是不够用了。
第一次是 提示词工程(Prompt Engineering),时间大致在 2023 到 2024 年。它优化的对象是输入措辞——prompt 怎么措辞、用什么格式、放几个示例。它解决的问题是单次对话的质量,交互模式基本是一问一答。那段时间大家比的是谁更会“把话说清楚”。
第二次是 上下文工程(Context Engineering),大约在 2025 年。它优化的对象变成了信息输入——文档、代码片段、历史对话怎么组织进上下文。它解决的问题是知识边界与幻觉,交互模式是“信息注入 → 生成”。这时候大家比的是谁更会给 AI 喂信息。很快,大家发现光喂信息也不够:知识边界清楚了,Agent 还是会在多轮工具调用里迷路。
第三次就是 驾驭工程(Harness Engineering),从 2026 年开始。它优化的对象是运行环境——约束、反馈回路、控制系统。它解决的问题是 Agent 的可靠性与可持续性,交互模式是“人类掌舵,Agent 执行”。这时候比的已经不是措辞或喂料,而是谁能把模型放进一个稳定、可观测、可替换的运行环境里。
| 范式 | 核心问题 | 优化对象 | 交互模式 | 时间线 |
|---|---|---|---|---|
| 提示词工程 | 怎么把话说清楚 | Prompt 的措辞、格式、示例 | 一问一答 | 2023 ~ 2024 |
| 上下文工程 | 怎么给 AI 喂信息 | 文档、代码片段、历史对话 | 信息注入 → 生成 | 2025 |
| 驾驭工程 | 怎么让 Agent 可靠工作 | 约束、反馈回路、控制系统 | 人类掌舵,Agent 执行 | 2026 ~ |
这张表最重要的读法是:三种范式不是替代关系,而是叠加关系。驾驭工程不是让你别写 prompt 了,而是说光有 prompt 和上下文已经不够,运行环境这一层必须有人负责。而 dsh 对应的正是“运行环境”这一层——它是一个把约束、反馈、可观测、可替换全部落地的开源实现,让驾驭工程不再停留在方法论,而是开箱即用的基础设施。
对入门读者来说,这里有一个很实用的判断标准:如果你花在“调 prompt 措辞”上的时间远多于“设计工具返回什么、出错怎么反馈、状态怎么存”,那你可能还在上一代范式里打转。Agent 的可靠性不来自某一句神奇提示词,而来自环境里的约束与反馈回路——权限策略拦住了越权操作,验证回路把失败信息喂回模型,追踪系统让每一步都可复盘。这些恰恰都是 Harness 的职责。
dsh 是什么:MIT 许可、TypeScript 编写、2026 年 8 月开源的开发者预览版
先把项目身份信息交代清楚,避免后面讨论时概念漂移。
- 全称与别名:DeepSeek Harness,命令行入口为
dsh,npm 包名为@deepseek-ai/dsh。 - 开发者:深度求索(DeepSeek AI)。
- 开源时间:2026 年 8 月正式开源。
- 许可证:MIT 许可证——这意味着你可以自由使用、修改、分发,包括商用。
- 语言:TypeScript 编写。
- 阶段:目前处于开发者预览阶段,官方明确提示未来将有破坏兼容性的变更。
- 定位:Agent Harness(智能体框架),不优化模型本身,而是优化模型运行的环境。
这里必须重点划线的是最后两条。很多初学者看到“开源了”三个字就默认它是稳定版,直接上生产,然后在某次升级后发现配置对不上、插件报错——这不是 dsh 的 bug,而是预览阶段的预期行为。官方的措辞很清楚:未来会有破坏兼容性的变更。这句话的工程含义是:
- 配置文件结构、插件 API、事件名都可能变,不要把它们硬编码进你无法快速迭代的生产系统。
- 升级前养成查看变更记录的习惯,升级前先用
dsh --profile web --dump-config对比配置树差异。 - 把它当作学习和内部试验的工具非常合适,当作对外承诺的长期基础设施则需要预留迁移成本。
- MIT 许可证意味着即便上游发生破坏性变更,你理论上可以 fork 并自行维护,但代价是失去上游更新。
另外,虽然 dsh 用 TypeScript 编写,但这不代表你必须会 TypeScript 才能用。素材里给出的基础能力要求很克制:命令行基础操作(必须,会用终端、会设环境变量)、Node.js 基础(必须,能通过 npx / pnpm 安装并启动 dsh)、基本 API 概念(了解即可,知道什么是 API Key 就行)、插件与配置文件概念(了解即可,进阶章节会用到)、Git 基础(可选)。操作系统上,Linux、macOS 或 Windows 装了 Node.js 就能跑。对 AI 研究背景和深度机器学习知识没有要求。
如果你只是想先把界面跑起来看一眼,一行命令即可:
# 安装 Node.js 后,一行命令启动 Web UI(默认 http://127.0.0.1:3080)
npx @deepseek-ai/dsh web
如果你想从源码安装、顺便看看项目长什么样,可以用下面的流程(需要 pnpm):
# 从源码安装并启动
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web
Web UI 的入门只要三步:第一步,打开设置 → 模型,填入 DeepSeek API 密钥并保存,模型路由立即可用、无需重启;第二步,选择工作区,把启动 dsh 时所在的项目目录添加并选中(注意:选中之前会话输入框是不可用的,这是新手最常见的“为什么打不了字”原因);第三步,发送一条任务,例如 Summarize this repository,Agent 会开始读写文件、运行命令、委派子代理,而超出权限策略的操作会先征求你的审批。这三步里藏着两个值得展开的工程点:模型路由无需重启与越权操作需审批,前者是模型无关设计的体现,后者是约束回路的体现,都会在下面继续展开。
Cordis 内核只干三件事:插件加载、卸载与依赖管理
理解了“一切皆插件”,接下来最反直觉的一点是:既然一切皆插件,那内核里到底有什么?答案是——很少。dsh 的底层由开源插件系统 Cordis 驱动,Cordis 内核只负责插件的加载、卸载与依赖管理。它不提供模型、工具、技能、会话、沙箱、存储、循环、调度、UI 中的任何一项能力。这些能力全部由插件提供。
这是一个非常激进、也非常干净的架构决策。传统的 Agent 框架通常是“内核里塞满核心能力 + 留几个扩展点”,你能改的只有被允许改的那几个地方,想换掉内置的会话存储或调度逻辑,就得 fork。dsh 反过来:内核极薄,能力全在插件,于是“换掉某个能力”不再等于“入侵内核”,而是“换一个插件”。
那插件之间靠什么协作?靠 Cordis 提供的两套机制:服务(Service)与事件(Event)。你可以这样理解:服务是插件对外暴露的能力接口,比如某个插件提供“会话存储服务”,别的插件想存会话就去调用这个服务,而不需要知道它背后是数据库还是文件;事件是插件之间广播的信号,某个插件发出一条事件,关心它的插件挂上监听器就能响应,双方互相不认识。这套“服务 + 事件”的组合,让所有能力可以自由替换和灵活重组。
为什么事件驱动在这里特别关键?因为 Agent 的运行是高度时序化的:一轮对话开始、上下文被注入、模型返回、工具被调用、工具返回结果、子 Agent 被调度……每一步都是一个天然的扩展点。如果这些扩展点靠继承和覆写,插件之间的耦合会迅速失控;靠事件广播,任何能力都可以在旁边“挂载策略与适配器”,随时换模型、换工具、换存储,而不触碰别人的代码。素材里明确提到,dsh 的事件驱动扩展点体系分为会话 / Agent / 能力三级事件,这套设计背后还有学术支撑——Cordis 的设计思想对应论文《A Programming Paradigm for Spatiotemporal Composability》。对入门读者来说,你不需要去读论文,但需要记住这个结论:dsh 的扩展方式是把新插件挂载到其他插件旁边,而不是修改已有代码。
把内核职责收窄带来的直接好处,是可观测性和可调试性。因为能力是插件、插件有依赖、依赖由内核管理,任意时刻运行的 dsh 本质上是一棵可枚举的插件树。你可以打印它、审查它、替换它——这就是下一节要讲的配置层能力的根基。反过来说,如果一个框架的内核里藏着大量隐式逻辑,你是无法“审查自己机器上到底跑着什么”的。
无特权内核与可逆副作用:为什么扩展 dsh 不需要打补丁
Cordis 架构里最关键的一条工程约束是:运行时不存在需要打补丁的特权内核。这句话值得逐字拆解。
在很多系统里,内核能力是“特权”的:它注册后无法撤销,想改它的行为只能打补丁或 monkey patch,打完之后整个系统就进入一种“只有作者知道真实行为”的状态。dsh 明确避开了这条路:每一项能力注册都是可逆副作用,插件卸载时自动撤销。
什么叫“可逆副作用”?通俗地说,插件在加载时会向内核注册自己提供的能力(比如注册一个工具、注册一个服务、挂一个事件监听),这些注册动作会被内核记录下来,当这个插件被卸载时,内核会把这些注册统统撤销——工具消失、服务下线、监听解除,系统回到它加载之前的状态。就像一个函数有配对的正向与反向操作,加载与卸载是严格对称的。
这条约束带来三个实际好处,对工程实践影响很大:
- 扩展不需要打补丁:想加能力,就写一个新插件挂载到其他插件旁边;想改能力,就用 patch 在配置层替换。源码永远不用动。
- 插件可安全试错:卸载即撤销,意味着你可以挂一个实验性插件跑一轮,不满意就卸掉,不会留下“幽灵注册”污染后续运行。
- 系统状态可推理:任何时刻系统里有什么能力,取决于当前加载了哪些插件,而不是“历史上曾经 patch 过什么”。这让可观测、可回放、可复现成为可能。
把这条和“一切皆插件”连起来看,你会发现 dsh 的扩展哲学非常一致:能力来自插件,插件由配置组合,卸载自动撤销,扩展就是挂载。素材里的原话是:扩展 dsh 的方式就是把新插件挂载到其他插件旁边。这句话没有留任何“修改源码”的空间——因为根本不需要。
这里也有一个新手常见的坑值得提前提示:正因为注册是可逆副作用,插件之间的依赖顺序和依赖声明就变得很重要。如果你的插件依赖某个服务,而提供该服务的插件还没加载,你注册时就会失败;这也是为什么内核要负责“依赖管理”。遇到“服务不存在”类报错时,第一反应应该是检查插件加载顺序与依赖声明,而不是去改内核。下篇讲到插件开发时我们会给出具体写法。
Profile + 组合包 + patch:一棵插件树的四层叠加顺序
既然运行中的 dsh 是一棵插件树,那这棵树是怎么长出来的?答案是分层叠加。素材给出了精确的叠加顺序,一共四层,从先到后依次是:
- 按 profile 列出的顺序,应用每个组合包(Bundle)。profile 决定用哪套组合、按什么顺序装。这是最基础的一层,决定了这棵树的主干。
- 叠加 profile 自己的
cordis.patch.yml。组合包装完之后,用这个 patch 文件在 profile 层面做修正或补充。 - 叠加 home 级的 patch。这是用户级(家目录级)的个性化配置,作用范围比单个 profile 更广,适合放“我在所有项目里都想要的调整”。
- 最后是任意
--patchoverlay。命令行临时传入的覆盖层,优先级最高,适合一次性实验、调试、临时换能力。
这个“Profile + 组合包”的分层模型有一个非常实际的工程价值:关注点分离。组合包是别人写好的能力集合,profile 是你的场景选择,profile 的 patch 是场景级的微调,home 级 patch 是你的个人偏好,--patch 是这一次运行的临时决定。四层各管一段,互不污染。想不通“我这个改动该放哪一层”的时候,就按“影响范围从小到大倒推”:只影响这次运行放 --patch,只影响这个 profile 放 profile 的 patch,影响我所有工作放 home 级 patch。
用一张表把四层对照清楚:
| 叠加次序 | 层级 | 来源 | 典型用途 | 影响范围 |
|---|---|---|---|---|
| 1 | 组合包(Bundle) | 按 profile 列出的顺序应用 | 安装能力主干:模型、工具、会话、存储、UI 等 | 整个 profile |
| 2 | profile 级 patch | profile 的 cordis.patch.yml | 对组合包做场景级修正与补充 | 当前 profile |
| 3 | home 级 patch | 用户主目录下的 patch 配置 | 个人跨项目的通用偏好 | 该用户所有运行 |
| 4 | --patch overlay | 启动命令行动态传入 | 一次性实验、临时替换某能力 | 本次运行 |
注意这张表的读法是从上到下逐层叠加,不是互相替代。后一层在前一层的结果上继续修改,这也解释了为什么排查配置问题时必须先看“实际生效的配置树”,而不是只看某一个 patch 文件——你看到的单个文件未必是最终生效的样子。这就引出了下一节的那行命令。
dsh --profile web --dump-config:一行命令审查实际启动的完整配置树
四层叠加带来一个问题:配置被分散在多个地方,我怎么能确定“此刻真正生效的是什么”?dsh 给的答案是 --dump-config。素材里的示例命令是:
# 打印机器上实际启动的完整配置树
dsh --profile web --dump-config
# 打印出的任何条目,都可以由你自己的 patch 替换
这行命令看起来平平无奇,但它是整个“开放可控”承诺的兑现方式。它做的是:把当前 profile 下、经过四层叠加之后实际生效的完整配置树打印出来。注意关键词是“实际生效”——不是某一个 patch 文件的内容,而是叠加之后的结果。对入门读者来说,这意味着你不需要在脑子里模拟四层叠加,直接打印出来看就行。
为什么这件事在工程上如此重要?因为它把“我的 Agent 到底是什么样”从一个黑盒问题变成了一个可读问题。你可以在几个场景里反复用它:
- 排查配置不生效:你改了一个 patch 但行为没变,dump 一下就知道是你的 patch 没被加载,还是被后一层覆盖了。
- 升级前做差异对比:预览阶段会有破坏兼容性的变更,升级前后各 dump 一次,diff 一下就能看出配置树哪里变了,比读变更日志更直接。
- 学习别人的配置:拿到一份 profile,dump 出来就能看清它装了哪些组合包、替换了哪些能力。
- 做替换的起点:想替换某个能力,先在 dump 结果里找到对应条目,再针对它写自己的 patch。
素材里那句注释是本节的关键:打印出的任何条目,都可以由你自己的 patch 替换。这意味着 dump-config 不只是“看”,它是“改”的入口——你看到的每一项,都是可被你接管的对象。这就是“你的 Agent 是什么样,你说了算”的具体操作路径:先审查,再替换。
这里有一个非常容易踩的坑:不要在没看 dump 结果之前就直接写 patch。因为四层叠加的存在,你写的 patch 可能与更高优先级的层冲突。正确顺序永远是:先 --dump-config 看清当前生效值 → 定位你要改的条目在哪一层被设置 → 在更高(或同级但更晚)的层写 patch。这个习惯能帮你省掉大量“改了没反应”的困惑。
四种运行模式对照:标准 / PTC / 极简 / 创造各自的能力构成
dsh 开箱提供四种运行模式,覆盖了从“功能完整的编码 Agent”到“最小化基准测试”,再到“自己造新模式”的全谱系。这四种模式的差异不是 UI 皮肤,而是能力构成的差异——也就是装了哪些插件、暴露了哪些工具。理解它们的构成差异,能帮你选对模式、也理解“一切皆插件”在实践中的意义。
| 模式 | 定位 | 能力构成 | 适合谁 |
|---|---|---|---|
| 标准模式 | 功能完整的编码 Agent | 文件编辑、Shell、文件与网页检索、Skills、计划、目标、子代理(subagent)与工作流 | 日常编码任务的主力模式 |
| PTC 模式 | 代码组合工具调用 | 具备标准模式全部能力,并通过 Code Mode SDK 呈现工具——模型用一个 TypeScript 程序组合多步操作 | 需要一次性组合多步工具调用的复杂任务 |
| 极简模式 | 最小化基准测试 | 仅保留持久 bash 与 str_replace_editor 两个工具 | 模型评测、对照实验 |
| 创造模式 | 自定义 Agent preset | 具备标准模式全部能力,并提供运行时检查、插件实验与 preset 创作指导 | 想组合出自己新模式的人 |
逐条看会更有感觉。
标准模式是功能完整的编码 Agent,能力清单包括文件编辑、Shell、文件与网页检索、Skills、计划、目标、子代理与工作流。这是一套相当完整的工具集:检索让它找到信息,文件编辑让它改代码,Shell 让它跑命令验证,计划与目标让它组织长任务,子代理让它把子任务委派出去并行或隔离处理。绝大多数入门场景直接从标准模式开始就好。
PTC 模式是这套体系里最有研究味道的一个。它具备标准模式全部能力,但工具的呈现方式不同——通过 Code Mode SDK 呈现工具,让模型用一段 TypeScript 程序来组合多步工具调用。素材里的说法是“PTC 模式(模型用一段 TypeScript 程序组合多轮工具调用)”。这个差别对入门读者来说可以这样理解:普通模式下模型是一步一步调用工具、等结果、再想下一步;PTC 模式下模型可以先写一段程序把这些多步操作串起来。这对多步骤、模式化、需要精确组合的任务非常有价值——这也是为什么素材把 PTC 列为吸引 AI/ML 从业者的一项特性。
极简模式最需要单独说明,因为它的能力构成非常克制:仅保留持久 bash 与 str_replace_editor 两个工具,用于最小化环境下的模型评测。为什么要有这种“简陋”的模式?因为做模型评测时,你希望变量尽量少——工具越多,行为越丰富,也越难判断到底是模型的贡献还是环境的贡献。把工具砍到只剩两个,就能在一个干净、可控的基础上观察模型本身的表现。这也反过来印证了“一切皆插件”的威力:模式之间的差异只是装了不同插件,而不是内核里有不同的硬编码分支。
创造模式则是给“我想自己造一个模式”的人准备的:它具备标准模式全部能力,并额外提供运行时检查、插件实验与 preset 创作指导。也就是说,你可以在运行时观察系统状态、试验插件,并在指导下创作自己的 preset,组合出属于你的新模式。对进阶读者来说,这是从“用 dsh”跨越到“定制 dsh”的入口,下篇会展开。

把这四种模式放在一起看,你会发现它们其实是同一套插件机制的不同组合结果:标准模式是“全量工具”,PTC 模式是“换一种工具呈现方式”,极简模式是“砍到只剩两个工具”,创造模式是“给你工具自己造”。模式不是内核里的硬编码,而是插件组合的配方。这正是“一切皆插件”从口号落到运行时的样子。
到这里,上篇已经把 dsh 的宏观图景铺开了:Agent = Model + Harness 的分工逻辑,从提示词工程到驾驭工程的三次跃迁,dsh 的项目身份与预览阶段注意事项,Cordis 内核只负责加载/卸载/依赖管理,无特权内核与可逆副作用带来的扩展方式,Profile + 组合包 + patch 的四层叠加顺序,用 --dump-config 审查实际生效的配置树,以及四种运行模式的能力构成差异。但这些都是“用”和“配”的层面。真正决定你能把 dsh 用多深的,是插件怎么写、事件扩展点挂在哪、能力如何被 patch 替换、会话日志与 Trajectory 如何支撑可观测与回放——这些是下篇要拆开的部分。在往下之前,建议你先按本文的两段示例把环境跑起来,并执行一次 dsh --profile web --dump-config,亲眼看一眼那棵属于你机器上的插件树。
在上一段里,我们已经拆开了 DeepSeek Harness(以下简称 dsh)的整体骨架:Cordis 内核居中、能力插件环绕,模型、工具、技能、会话、沙箱、存储、循环、调度、UI 全部由插件提供,并用 Agent = Model + Harness 这一句话把「模型负责智能、Harness 负责可靠运行」的分工说透了。下面这段我们把镜头拉近,从一份 TypeScript 程序怎么组合多步工具调用开始,一路讲到会话日志、事件体系、两条安装路径、Web UI 三步走、多形态 SDK 分工,最后落到 2026 年 9 月的社区玩法与一份可执行清单。
PTC 模式与 Code Mode SDK:让模型用一段 TypeScript 程序组合多步工具调用
先说一个很多人第一次用 Agent 时的痛点:想做一件稍微复杂的事,比如「找出仓库里所有引用了旧版配置字段的文件,逐个读出来,把字段名替换掉,再跑一次类型检查确认没坏」,模型往往要来回十几轮——读目录、读文件 A、读文件 B、写文件 A、写文件 B、跑 tsc、看到报错、再改……每一轮都是一次完整的「模型思考 → 输出工具调用 → 执行 → 结果回灌」循环。轮数一多,延迟累积、上下文膨胀、中间某一步的临时变量也没地方存,最后模型自己都容易绕晕。
dsh 的 PTC 模式就是冲着这个场景来的。PTC 全称对应的是「程序化工具调用」的思路:在标准模式能力之上,它额外通过 Code Mode SDK 把工具呈现给模型——注意,呈现方式变了。工具不再只是「一个可被调用的函数签名」,而是变成一套模型可以直接书写的 TypeScript API。于是模型不再需要「调一次、等一次、再调一次」,而是写下一段完整的 TypeScript 程序,把多步操作编排在一起,一次提交。
这件事的价值可以这样理解:标准模式下模型是「一问一答式地驱使工具」,PTC 模式下模型是「用代码把工具串成流水线」。前者受限于对话轮次,后者受限于程序表达力——而程序表达力显然宽得多。你可以在那段 TypeScript 里写循环、写条件分支、写 try/catch、把中间结果存进局部变量、在提交前先做一次校验。原本需要十几轮往返的工作,被收敛进一段程序里跑完。
PTC 的定位是「标准模式 + Code Mode SDK」,也就是说,文件编辑、Shell、文件与网页检索、Skills、计划、目标、子代理(subagent)与工作流这些标准模式的能力它一个不少,只是多了一层代码编排的表达方式。怎么落地到实际使用?一个直观的示意是这样的:
// 概念示意:在 PTC 模式下,模型可以书写类似这样的 TypeScript 程序
// 把「读文件 → 改字段 → 跑校验」这条流水线一次提交,而不是分成十几轮对话
import { tools } from "@deepseek-ai/dsh/code-mode";
const targets = await tools.file.search({ pattern: "src/**/*.ts", grep: "legacyFieldName" });
for (const file of targets) {
const source = await tools.file.read({ path: file.path });
if (!source.includes("legacyFieldName")) continue;
const patched = source.replaceAll("legacyFieldName", "newFieldName");
await tools.file.write({ path: file.path, content: patched });
}
// 全部改完后一次性跑校验,失败就把错误信息带回去给模型
const check = await tools.shell.run({ command: "pnpm run typecheck" });
if (check.exitCode !== 0) {
return { ok: false, log: check.stdout };
}
return { ok: true, changed: targets.length };
需要提醒的是,上面是概念示意代码,目的是帮你建立「一段程序 = 多轮工具调用」的直觉,具体的导入路径与 API 名称请以你本机 dsh 版本的 Code Mode SDK 文档为准。真正的工程价值在于三点:
- 轮次收敛:多步操作被压进一次程序执行,减少了「模型往返」这一最贵的开销,长任务更不容易中途跑偏。
- 中间状态有地方放:局部变量承担了临时存储,不必每一步都把结果灌回上下文,上下文更干净。
- 失败可整体处理:一段程序里可以用正常的错误处理逻辑应对失败,而不是靠模型在下一轮「猜哪里错了」。
和它形成对照的是极简模式:只保留持久 bash 与 str_replace_editor 两个工具,专门用于最小化环境下的模型基准测试。极简模式要的是「把变量压到最少,看模型裸能力」;PTC 模式要的是「把编排能力拉满,看 Harness 加成」。同一个框架里放出这两种极端,本身就是 dsh「一切皆插件」的一种体现——能力构成是配置出来的,不是写死的。
仅追加会话日志:系统提示词、思维链、工具调用与子 Agent 调度全部落盘
Agent 最难排查的问题是什么?是「它为什么这么干」。你看到它删了一个文件,但你看不到它在删之前脑子里过了什么;你看到它调了一个子代理,但你看不到它给子代理塞了什么上下文。黑盒 Agent 的调试体验,基本等于猜。
dsh 在这件事上的答案非常干脆:模型看到的一切都写入会话日志。系统提示词、思维链、工具调用与结果、子 Agent 调度、每一次上下文注入——全部落盘。而且这份日志采用仅追加(append-only)设计:只往后写,不回头改。这一条听起来朴素,带来的性质却很多:
- 可追溯:任何一个动作,都能沿着日志回看它是被哪条上下文、哪次工具结果诱发的。
- 可恢复:会话中断了,从日志的事件流里接着往下走,不必重跑前面的步骤。
- 可分叉:想在某个节点换一种走法?从那儿 fork 出一条新分支,原来的路径原样保留。
- 可检索:事件流是可被查询的对象,问「这次运行里工具调用总共失败了几次」不再需要人肉翻页。
- 可回放:恢复、分叉、检索与回放共享同一份事件流,意味着你回放看到的就是当时真实发生的事,不存在「日志和实际执行不一致」。
这几个能力的实现方式值得单独点一句:它们不是四套系统,而是同一份事件流的四种用法。这就是 append-only 设计的好处——数据只有一份,大家都是它的视图。如果日志是可随意覆写的,恢复和回放就会互相打架;正因为不可改,四种用法才能共存且自洽。
消费这份日志的界面是 Trajectory 视图。它按来源查看:系统提示词是一类来源、思维链是一类、工具调用与结果是一类、子 Agent 调度又是一类、上下文注入再一类。当一次运行的结果和预期不符时,你在 Trajectory 视图里就能顺着来源定位到「是提示词说得不清楚」「是工具返回了脏数据」还是「是子代理拿到的上下文被截断了」。对研究人员来说,这几乎是刚需——完整可观测的事件流本身就是研究材料;对工程师来说,这是把 Agent 从「玄学」拉回「工程」的那根绳子。
还有一个细节容易被忽略:素材特别提到,模型看到的每一次上下文注入都会落盘。上下文注入是个隐蔽的东西——它不改变你的代码,却实实在在改变了模型的行为。把它记进事件流,等于把「看不见的手」摊开在桌面上。
会话 / Agent / 能力三级事件:事件驱动扩展点如何挂载策略与适配器
「一切皆插件」要真正成立,光有插件加载器是不够的,还得有一张足够细的钩子网——插件之间靠什么协作?靠 Cordis 的 Service(服务)与 Event(事件)。dsh 把事件扩展点划分为三级:会话级、Agent 级、能力级。
这个划分不是拍脑袋来的,它对应了 Agent 运行时的三个尺度。会话级的事件关注「一次完整会话的生命周期」,比如会话开始、结束、被恢复、被分叉;Agent 级的事件关注「一次任务执行的过程」,比如 Agent 启动、规划、委派子代理、完成;能力级的事件关注「某一个具体能力的调用」,比如某次文件读写、某次 Shell 执行、某次检索。粗看是三层,细看是三个粒度:会话是容器,Agent 是执行体,能力是动作。
开发者怎么用这三层?答案是挂载策略与适配器。策略类插件监听事件做决策——比如在能力级事件上挂一个「凡是写操作先拦一下、等审批」的策略;适配器类插件监听事件做翻译——比如在 Agent 级事件上把某一个提供方的响应格式翻译成统一格式。下面的对照表把三级的关注点、典型用途和可替换的东西列了出来:
| 事件级别 | 关注尺度 | 典型用途 | 可用于替换的对象 |
|---|---|---|---|
| 会话级 | 一次完整会话的生命周期 | 会话恢复、分叉、检索、回放策略 | 存储、会话后端、日志消费方式 |
| Agent 级 | 一次任务执行的过程 | 规划策略、子代理调度、结果汇总 | 循环(agent loop)、调度器、模型路由 |
| 能力级 | 某一个具体能力的调用 | 权限审批、结果校验、格式适配 | 工具、检索、沙箱、UI 呈现 |
三层叠在一起,构成了一张没有死角的扩展网。换模型、换工具、换存储,全过程无需改动任何源码——你改的是配置与插件组合。这句话的分量在于:闭源 Agent 的能力边界是厂商画的,而 dsh 的能力边界是你自己画的。
这背后还有一条很关键的机制承诺:运行时不存在需要打补丁的特权内核。所有能力注册都是可逆副作用,插件卸载时自动撤销。这句话解决的是「插件系统常见的老大难」——装插件容易,干净卸掉难,残留的全局状态会让系统越来越不稳定。dsh 把「注册即副作用、卸载即撤销」做成了内核级约束,于是扩展 dsh 的方式就变成了一件很轻的事:把新插件挂载到其他插件旁边。没有特权层,就没有补丁的立足之地。
底层 Cordis 的设计思想对应论文《A Programming Paradigm for Spatiotemporal Composability》,有学术支撑,不是随手糊出来的轮子。事件驱动 + 可逆注册 + 配置层组合,这三件事合起来,才撑得住「一切皆插件」这句标语。
npx @deepseek-ai/dsh web 与源码安装:两条上手路径的完整命令
理论讲完,动手。dsh 的前置条件很轻:安装好 Node.js,操作系统 Linux、macOS、Windows 都可以。命令行的基本操作、Node.js 的基础、大致知道 API Key 是什么,就够了;不需要 AI 研究背景,也不需要深度的机器学习知识。
第一条路径是 npx 一键启动,适合想先把东西跑起来看看的人:
# 方式一:npx 一键启动 Web UI(无需预先全局安装)
npx @deepseek-ai/dsh web
# 启动后浏览器访问默认地址
# http://127.0.0.1:3080
这一行命令背后做的是:拉取 @deepseek-ai/dsh 这个 npm 包,以 web profile 启动,把 Web UI 挂在 http://127.0.0.1:3080。注意它默认绑的是本机回环地址,不对外暴露。
第二条路径是 源码安装,适合要读代码、要改插件、要参与贡献的人:
# 方式二:从源码安装
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web
四步分别是:克隆仓库、装依赖、构建、以 web profile 启动。这里用 pnpm 而不是 npm,是仓库约定;照着敲就行。两条路径的差别不在功能,而在「你能改到什么深度」:npx 路径你拿到的是一个装配好的成品;源码路径你拿到的是可以自己拆的整机。
无论走哪条,装完之后第一件事建议做同一步——审查实际启动的配置树:
# 打印当前 profile 实际启动的完整配置树
dsh --profile web --dump-config
# 输出的任何条目,都可以由你自己的 patch 替换
为什么这一步重要?因为 dsh 的配置是分层叠加的:启动时先按 profile 列出的顺序应用每个组合包(Bundle),然后是 profile 的 cordis.patch.yml,然后是 home 级 patch,最后是任意 --patch overlay。也就是说,运行中的 dsh 是一棵由多层叠加而成的插件树。--dump-config 让你看到「这棵树现在长什么样」,而输出里的任何条目都可以被你自己的 patch 替换。这是「开放可控」从口号变成事实的关键一步:不相信我?那就把配置树打出来看。
一定要记住一个前提:dsh 当前处于开发者预览阶段,采用 MIT 许可证,官方明确提示未来会有破坏兼容性的变更。这意味着两件事:一是升级前先看变更说明,别把生产流程赌在预览版的稳定性上;二是正因为 MIT 开源且配置层可组合,你完全可以在自己的 patch 层里把行为钉住,不受上游默认值变动的影响。
Web UI 三步走:设置 → 模型填密钥、添加工作区、发送任务
Web UI 是 dsh 最省事的入口,默认地址 http://127.0.0.1:3080。上手就三步:
- 配置模型:打开「设置 → 模型」,填入 DeepSeek API 密钥并保存。重点来了——模型路由立即可用、无需重启。这个特性看着小,体验差别很大:换模型不用停服务,对正在跑长任务的人来说就是能不能不中断的区别。
- 选择工作区:把启动 dsh 时所在的项目目录添加进来并选中。这里有个容易踩的坑——选中工作区之前,会话输入框是不可用的。第一次用的人常以为是界面卡了,其实是还没告诉 Agent「你在哪个项目里干活」。这个设计是刻意的:Agent 有明确的文件系统边界,不是随便哪都能读写。
- 运行任务:发送任务,比如「Summarize this repository」。接下来 Agent 会读写文件、运行命令、委派子代理。关于权限——超出权限策略的操作会先征求你的审批,不会闷头执行。这道闸门在多级事件体系里对应「能力级事件挂策略插件」的用法,也是把 Agent 放进真实项目时的基本安全线。
把三步串起来看,dsh 的设计意图很清楚:先定模型(灵魂)、再定边界(工作区)、再放任务(执行)。顺序不是随意的,它对应的是「模型从哪来、能碰什么、要干什么」这三个必须回答的问题。

多形态使用:Web UI、headless、CLI、Python SDK 与 TypeScript SDK 的分工
dsh 不只长着一个界面。它的多形态设计对应的是不同的使用场景,选错了形态会觉得别扭,选对了会很顺。
| 形态 | 形态定位 | 最适合的场景 | 使用要点 |
|---|---|---|---|
| Web UI | 图形界面,默认 http://127.0.0.1:3080 | 交互式探索、看 Trajectory、人工审批 | 三步走:设置模型 → 选工作区 → 发任务 |
| headless | 一次性运行、打印最终答案并退出 | 脚本、CI 流水线等无人值守场景 | 跑完就走,不进入交互循环 |
| CLI | 命令行直接操作 | 终端重度用户、配置文件审查 | 可配合 --profile / --dump-config 使用 |
| Python SDK | pip install deepseek-harness-sdk | 把 Agent 嵌进 Python 工作流与数据管线 | 自带运行时、无需系统 Node.js |
| TypeScript SDK | 面向 TS 生态的嵌入方式 | 与 dsh 本体同语言的深度集成与插件开发 | 与 Code Mode SDK 同属 TS 侧能力 |
逐条说清楚差别。
Web UI 是功能最全的形态,适合「人在场」的时候用:你要看它想干什么、要看某一轮工具调用返回了什么、要在 Trajectory 视图里逐来源排查,都在这儿。headless 反过来,它一次性运行任务、打印最终答案并退出——这个形态天生适合脚本与 CI,因为它没有「等你在界面上点一下」这个环节。比如在流水线里加一道自动检查,用 headless 形态最自然。
CLI 是终端里的入口,也是你执行 dsh --profile web --dump-config 这类配置审查命令的入口。Python SDK 这条线有一个很实用的细节:pip install deepseek-harness-sdk,而且它自带运行时、无需系统 Node.js。对 Python 团队来说这一条价值很高——不用为了嵌一个 Agent 而在环境里额外塞一个 Node 运行时,依赖面小了很多。下面给一段把 Agent 嵌进 Python 工作流的概念示意代码:
# 概念示意:用 Python SDK 把 dsh 嵌入自己的工作流
# 安装:pip install deepseek-harness-sdk(自带运行时,无需系统 Node.js)
from deepseek_harness_sdk import Harness
# 指向项目目录,构造一个一次性的 Harness 会话
harness = Harness(workspace="./my-repo")
result = harness.run(
"梳理这个仓库的模块依赖,输出一份 Markdown 概览",
# 超出权限策略的操作会先触发审批回调,这里全部自动拒绝
on_approval=lambda req: False,
)
print(result.final_answer)
# 完整事件流可另行导出,用于回放与检索
result.export_events("run-events.jsonl")
同样地,这里是概念示意代码,字段名与回调签名请以官方 SDK 文档为准,重点理解「构造 Harness → 传入任务 → 拿最终答案 → 导出事件流」这条链路。注意最后那行导出事件流——它把前面讲的 append-only 会话日志的价值带到了 SDK 里:不只是在 Web UI 里能看,你还可以把它接进自己的数据管线。
TypeScript SDK 则面向 TS 生态的深度集成,和插件开发、Code Mode SDK 同属 TS 侧能力。如果你的团队本来就写 TypeScript,从插件到编排可以用同一套语言栈完成,心智负担小。
把五种形态放一起看,dsh 的定位就清楚了:它不是「又一个写几个 agent 的库」,而是位于 SDK 与框架之上、解决「Agent 如何可靠运行」的完整一层。为了说明这条定位线,可以把当下几个热门工具摆在一张表里对比:
| 项目 | 定位 | 与 DeepSeek Harness 的关系 |
|---|---|---|
| Claude Code | 闭源商用编码助手 | 功能对标,但 dsh 完全开源、可自托管、能力可替换 |
| Hermes Agent | 自进化个人 Agent(Nous Research) | 侧重跨会话记忆与技能沉淀;dsh 侧重插件化组合与全程可观测,两者理念互补 |
| OpenClaw | 本地优先消息型 Agent | 侧重多渠道接入与数字主权;dsh 提供 Web UI / headless / SDK 多形态 |
| LangGraph / AutoGen / CrewAI | Agent 构建框架(编程库) | 框架解决「如何构建」;dsh 是完整 Harness——「如何稳定运行 + 如何替换能力」 |
这张表里最该记住的一句是最后一行:构建框架和 Harness 不是同一层问题。你用 LangGraph 之类的库把 Agent 搭出来,那是「构建」;搭好之后它稳不稳定、挂了能不能恢复、换个模型要不要动源码、出了问题能不能回放——那是「运行」。dsh 站在后一层。
顺带把行业的背景数据摆一下,这些素材里都有:OpenAI 团队在 100 万行代码实验中,5 个月产出全部由 Agent 完成、工程师一行代码未写;LangChain 仅优化外部驾驭环境(文档结构、验证回路、追踪系统),就让编码 Agent 在 Terminal Bench 2.0 的得分从 52.8% 提升到 66.5%,全球排名从第 30 位升至第 5 位,而底层模型一个参数都没动。瓶颈不在模型智能,而在基础设施——这正是 Harness 存在的理由。
如果把 AI 工程范式的演进理顺,可以看到三次跃迁:提示词工程(2023~2024,优化对象是输入措辞,解决单次对话质量,交互模式是一问一答)、上下文工程(2025,优化对象是信息输入,解决知识边界与幻觉,交互模式是信息注入后生成)、驾驭工程(2026 起,优化对象是运行环境,解决 Agent 可靠性与可持续性,交互模式是人类掌舵、Agent 执行)。dsh 就是驾驭工程理念的完整产品化落地。
2026 年 9 月最新进展:从 dsh --dump-config 出发的插件社区与 preset 实践
到 2026 年 9 月,围绕 dsh 的生态已经长出了比较清晰的玩法路径,而且这条路径的起点恰好就是上一节讲的那条命令:dsh --profile web --dump-config。为什么从它出发?因为它把「系统实际长什么样」摊开了。你看到的每一个条目,都是一个可以替换的装配点;而社区的玩法,本质上就是「拿别人的插件填这些点,或者把自己的插件塞进这些点」。
找插件的地方是 GitHub topics: dsh-plugin。用一个 topic 收敛插件生态,好处是很实际的:搜索、订阅、按主题浏览都走 GitHub 原生能力,不需要额外的中心化市场,也不存在「市场关了就全没了」的单点依赖。这和 MIT 开源、无遥测、无云端锁定的整体取向是一致的。
另一个 9 月前后很值得关注的方向是创造模式。它的定位是「自定义 Agent preset」,能力构成是标准模式全部能力 加上 运行时检查、插件实验与 preset 创作指导。换句话说,创造模式不只是一个运行档位,它更像一个「造 Agent 的工作台」:你在里面检查运行时状态、试验插件挂载、然后按指导把一个 preset 组合出来。
什么叫 preset?可以理解为「一整套插件组合 + 配置叠加」的快照。回到前面讲的叠加顺序:profile 列出组合包 → 应用每个组合包 → profile 的 cordis.patch.yml → home 级 patch → --patch overlay。一个 preset 就是把这条链上某一层次的组合固定下来,打包复用。于是社区里最自然的两种玩法就出现了:
- 横向玩法:换零件。模型、工具、技能、会话、沙箱、存储、循环、调度、UI 里任意一个,都可以找社区插件替换。比如把默认存储换成你团队内部的存储适配器,把检索换成你们自建的知识库。
- 纵向玩法:叠 preset。不改零件,改组合方式。针对「前端重构」「数据管线维护」「文档站生成」这类细分场景,各自组一个 preset,用时切一下就换了一套 Agent 的行为。
四条运行模式的谱系这时候就特别好理解了:标准模式是功能完整的编码 Agent(文件编辑、Shell、文件与网页检索、Skills、计划、目标、子代理与工作流);PTC 模式在标准能力上叠加 Code Mode SDK,让模型用一段 TypeScript 程序组合多步工具调用;极简模式只留持久 bash 与 str_replace_editor,用于最小化基准测试;创造模式是标准能力加上运行时检查、插件实验与 preset 创作指导。前三个是「用什么档位跑」,第四个是「怎么造新档位」。
这里给一份实践层面的配置骨架示意,帮你把「patch 从哪来、往哪叠」落到实处:
# 实践示意:用 --patch overlay 在不改源码的前提下替换能力
# 1) 先看清现状
dsh --profile web --dump-config > current-config.txt
# 2) 准备一层自己的 patch(示意命名,以官方 patch 格式为准)
# 把日志存储指向团队内部后端,并挂一个写操作审批策略
cat > my-overlay.patch.yml << 'EOF'
storage:
driver: team-internal-store
policies:
- name: approve-writes
on: capability.file.write
action: require-approval
EOF
# 3) 带着 overlay 启动,配置即生效
dsh --profile web --patch my-overlay.patch.yml
再次强调,这是结构示意而非官方配置样例,字段名请以你所用版本的文档为准;它想传达的是那个工程习惯——先 dump 现状,再叠自己的 patch,最后带着 overlay 启动。这个习惯能让你在预览版不断演进的过程中始终掌握主动:上游默认值怎么变,你的 overlay 都在你手里。
最后说三件 9 月前后特别值得留意的工程事项。第一,预览期的心态:官方明确提示未来会有破坏兼容性的变更,所以把自定义逻辑尽量收在自己的 patch 与插件里,而不是直接改上游源码,升级时痛苦会小很多。第二,可观测先行:既然每一次运行都写进 append-only 日志、Trajectory 视图可按来源查看,那就把它当第一手排查工具用,而不是出了事才想起来翻。第三,权限策略趁早配:超出权限策略的操作会先征求审批,这是好机制,但默认策略未必贴合你的项目,早一点通过插件把策略调成你团队的习惯,比事后补救省事。
总结与最佳实践
把全文要点压成一份可以直接照着做的清单:
- 先记住那条主线:Agent = Model + Harness。模型是灵魂,Harness 负责理解环境、使用工具、在真实场景中持续工作;瓶颈通常不在模型智能,而在基础设施。
- 理解架构内核:Cordis 内核只负责插件的加载、卸载与依赖管理;模型、工具、技能、会话、沙箱、存储、循环、调度、UI 全部由插件提供,通过 Service 与 Event 协作。运行时没有需要打补丁的特权内核,注册即可逆副作用,卸载即自动撤销。
- 选区选型:按场景挑运行档位——标准模式做完整编码 Agent;PTC 模式用 Code Mode SDK 把多轮工具调用收敛成一段 TypeScript 程序;极简模式只留 bash 与 str_replace_editor 做基准测试;创造模式用于运行时检查、插件实验与 preset 创作。
- 把可观测当默认动作:模型看到的一切都写入仅追加会话日志(系统提示词、思维链、工具调用与结果、子 Agent 调度、上下文注入)。恢复、分叉、检索、回放共享同一份事件流,用 Trajectory 视图按来源查看。
- 用三级事件挂扩展:会话级管生命周期、Agent 级管任务过程、能力级管具体调用。挂策略做审批与校验,挂适配器做格式与后端替换,做到换模型、换工具、换存储不改源码。
- 安装别纠结:想快速体验就
npx @deepseek-ai/dsh web;要读源码改插件就走git clone→pnpm install→pnpm run build→pnpm dsh web。前提是装好 Node.js。 - Web UI 三步走:设置 → 模型里填 DeepSeek API 密钥(路由立即可用、无需重启)→ 添加并选中工作区(未选中时输入框不可用)→ 发送任务,超权限操作先审批。
- 挑对使用形态:交互排查用 Web UI(默认 http://127.0.0.1:3080);脚本与 CI 用 headless(一次性运行、打印最终答案并退出);终端操作走 CLI;Python 工作流用
pip install deepseek-harness-sdk(自带运行时、无需系统 Node.js);TS 深度集成用 TypeScript SDK。 - 养成 dump 配置的习惯:动手前先跑
dsh --profile web --dump-config,看清 profile → 组合包 → cordis.patch.yml → home 级 patch →--patchoverlay 的叠加结果;要改行为,写自己的 patch 或插件,别改上游源码。 - 跟上社区:插件在 GitHub topics: dsh-plugin 里找;想造自己的 Agent,用创造模式的 preset 创作指导把「一套插件组合 + 配置叠加」固化下来,按细分场景复用。
- 预览期三条纪律:升级前看变更说明(官方已提示将有破坏兼容性变更);把自定义逻辑收在自己的 patch 层;权限策略趁早按团队习惯配置。
- 记住授权与边界:MIT 许可证、无遥测、无云端锁定,配置层自由组合,能力边界由你画——这正是「Everything is a Plugin.」落到工程上的含义。
如果只带走一句话,那就是:dsh 把「驾驭 AI」从方法论变成了可组合、可观测、可替换的基础设施。你不必从零写一个 Agent,也不必被锁在别人的黑盒里——把模型填进去,把插件按你的方式挂上去,然后在 Trajectory 视图里看着它一步一步把活干完。