
2026 年 8 月 13 日,DeepSeek 开源了 DeepSeek Harness(
dsh)——不是新模型,而是一套 Agent 的运行时底座。发布 24 小时内收获约 4.6 万星。很多人把它当成"又一个对标 Claude Code 的 CLI",但把三代编程 AI Agent 放在一起看,你会发现它站在一条清晰的进化线上。 这篇文章想站在架构师视角,讲清楚三件事:编程 AI Agent 是怎么一步步进化的,dsh 凭什么敢说"一切皆插件",以及这对所有用过 Claude Code、Pi 的开发者意味着什么。
先退一步看背景。
过去两年,AI 编程助手之间的竞争焦点是"谁的模型更聪明"。但越来越多的人意识到一件事:模型能力正在趋同,真正拉开差距的是框架层——上下文怎么管理、工具怎么接入、能力怎么扩展、跑了半天怎么恢复。
而"框架竞争"不是一个静态的概念,它已经在三代产品里演进了三轮:
三代产品回答的是同一个问题——"一个编程 Agent 应该怎么被构建、怎么被扩展"——但答案一代比一代激进。本文就沿着这条线走:先看前两代解决了什么、留下了什么,再看 dsh 凭什么敢做第三代。
Claude Code 是"AI 编程 Agent"这个品类的定义者,这一点没有争议。
它赢在大而全:开箱即用就是一套完整的 Agent——文件读写、差分编辑、终端执行、网页检索、内置子代理、上下文工程、会话管理,全部配齐。你不需要组装任何东西,装好就能干活。对绝大多数人来说,这恰恰是对的:他们要的是一个能用的产品,不是一堆要自己拼的零件。
它也不是封闭的。Claude Code 开放了一套扩展体系,载体是 Plugin,聚合四类能力:
听起来很开放,但第一代的本质没有变:内核是闭源的、厂商定义的。 你可以在它周围加东西——加技能、加工具、加钩子——但核心逻辑你碰不到:模型怎么被调用、循环怎么转、上下文怎么组装、出了事怎么审计,全是黑盒。
"大而全"还有第二个代价:扩展之间没有组合纪律。Hook 注册了要靠你自己记得清理,插件依赖要靠人工编排,卸载不干净就是状态污染。在这个体系里,"扩展"永远是"往上叠加",而不是"替换"。
这不只是 Claude Code 的问题。Cursor、Codex 都属第一代——功能完整、内核私有、扩展是产品的附属品。它们的边界就是"产品"划定的边界,你始终在租借一个别人的 Agent。
第一代的局限,催生了第二代。
Pi 是 libGDX 作者所在的 earendil-works 组织开发的、MIT 许可的开源 AI Agent 工具集,在 GitHub 上积累了近万 stars。它的出现代表一次方向反转:不要大而全,要小而美。
它的定位非常鲜明:不把"功能"内置成死特性,而是提供"原语"(Primitives, Not Features),让你自己拼装出属于你的 Agent。官方金句是 Adapt Pi to your workflows, not the other way around——让 Pi 适应你的工作流,而不是反过来。
这个哲学落到产品上,体现为几个"自主":
~/.pi/agent/),不上传任何遥测或使用数据,源码开源可审计。最值得注意的是它的极简内核:定义"Agent 到底能做什么"的核心抽象,只有三个文件、约 1,370 行代码。其余的一切——会话管理、模型解析、扩展加载——都被设计成"可替换的能力",在运行时挂上去。
更极端的是,Pi 会故意不内置很多同类工具默认携带的功能,然后给出替代方案:
不内置的功能 | Pi 的替代方案 |
|---|---|
MCP 协议集成 | 把工具写成带 README 的 CLI,或安装 MCP 扩展 |
子 Agent | tmux 开多会话,或自己写扩展 |
权限确认弹窗 | 放进容器跑,或自己写确认流程扩展 |
计划模式 | 把计划写文件,或写扩展 |
内置待办事项 | 用 TODO.md,或装扩展 |
后台 bash | tmux 获得完整可观测性 |
它的扩展体系分三层:Extensions(TypeScript 模块,可以注册工具、注册斜杠命令、拦截事件)、Skills(实现 Agent Skills 标准,兼容 Claude Code / Codex 的技能格式)、Pi Packages(pi install 从 npm / git / 本地安装,分发像 npm 包一样简单)。会话管理上,它有被社区高频称赞的树形会话——历史任意分叉不丢分支,配合上下文压缩让超长会话能继续下去。
在权限这件事上,Pi 非常诚实:README 里明确不内置权限系统,默认以启动用户的权限运行,推荐用容器、微 VM 或策略沙箱隔离。
把二代和一代并排看,进化很清楚:
但 Pi 也留下了两个天花板,第三代正是从这里起步:
第一个天花板:加法,不能替换。 Pi 的扩展是事件总线 + TS 模块,本质是"往上加"——注册一个工具、挂一个监听、装一个技能包。你可以加,但几乎换不掉核心、卸不净副作用。内核再薄,也还是一块不可动的骨头。
第二个天花板:可靠性自理。 会话事件是喂给界面的瞬时信号,UI 刷完就没了,不可重放、不可审计;权限要自己容器化;没有一条运行时不变式来保证"模型看到的,一定有据可查"。
二代把内核做到了极薄,三代的问题是:能不能更进一步,让内核不存在?
在回答之前,先看一个所有做插件系统的人都绕不过去的坑:
装上容易,卸干净难;组合起来容易,拆开还原难。
插件 A 注册了一个事件监听,插件 B 往配置表里加了一行,插件 C 起了个后台定时器。现在你要卸载 A——得记得把它注册的监听、定时器、配置全部手动清掉。漏一个,就是内存泄漏、幽灵监听、状态错乱。
更麻烦的是依赖。插件 B 依赖插件 A 的能力,如果 A 还没加载完 B 就启动,程序直接崩。于是你得手写"启动顺序编排"——而顺序一旦写死,系统就僵了,动态加载和热更新基本没戏。
一代的 Hook、二代的扩展,都靠开发者自觉维护这些清理和顺序。dsh 的底层框架 Cordis,把这套问题背后的两个维度分别形式化了,合起来叫——时空可组合性(Spatiotemporal Composability)。这来自一篇论文:A Programming Paradigm for Spatiotemporal Composability。
Cordis 把这两件事做成了运行时机制,统一成"组件"的编程范式。而 dsh,整个就是建立在这套机制之上。
这句话值得重复一遍,因为它太容易被当成营销词了:dsh 的"一切皆插件"不是一句口号,它背后有一篇论文、一套形式化理论、和一个把理论变成运行时机制的框架。
理解了时空可组合性,就能看懂 dsh 最反直觉的设计——它没有特权核心。
传统架构里,再插件化的系统,也有一块"所有功能都必须围着它改"的超级核心。但在 dsh 里:
这意味着两件很实际的事:
第一,扩展产品 = 把插件挂到别的插件旁边。 想换模型?挂一个新的 provider 插件。想换沙箱?挂一个新的 sandbox 插件。想调整 Agent 的循环逻辑?挂一个新的 loop 插件。没有任何一块需要 fork 仓库去打补丁。
第二,注册是可逆的。 插件卸载时,它注册的一切——监听、工具、配置——自动撤销。这在其他系统里要靠开发者自觉维护清理逻辑,在 dsh 里是框架保证的。一代的 Hook 靠人记得清理,三代把它变成了运行时义务。
dsh 甚至把这种"可组合"延伸到了部署配置。运行中的 dsh 不是固定模块的集合,而是一棵插件树,由启动时按序叠加的各层组成:profile(具名组合)→ bundle(可分发组合包)→ 用户自己的 patch 文件。你随时可以运行 dsh --profile web --dump-config 打印出这台机器实际启动的配置树,树里的任何一条,都能被你的 patch 替换。
想换掉内置的沙箱、换掉提示词组装逻辑、甚至换掉 agent loop——都不用改一行产品代码,写一个 patch overlay 上去就行。
这就是 dsh 相比第一代产品最本质的区别:它是一个白标、可嵌入的产品内核,不是一个开箱即用的应用。 一代让你用 Agent,二代让你拼 Agent,三代让你换 Agent 的每一块骨头。
如果说"一切皆插件"是 dsh 最显眼的设计,那下面这个就是它最被低估、也最硬核的设计——它直接回答了二代留下的"可靠性自理"天花板。
一个 Agent 跑起来,会产生海量东西:用户说了什么、模型回了什么、调了哪些工具、工具返回了什么、上下文是怎么注入的……这些东西散落在各处,最后喂给模型。
一代和二代对这件事的态度是:够用就行。一代的会话格式私有,产品自管;二代的树形会话已经比"聊天记录"强了,但它回放的是给界面看的瞬时事件,不是经过校验的完整真相。
dsh 的态度截然不同。它把会话日志定义为唯一事实源,并立了一条运行时不变量:
模型可见即已记录(Model-visible means logged)。 任何抵达模型请求的东西,都必须能从事件日志重建出来。
这句话不是道德宣言,而是机器保证。dsh 用一个状态机 + 序列号在线校验整个事件流:turn/start 和 turn/end 必须配对,step 必须嵌套在打开的 turn 里,tool/result 必须有对应的 tool/call。任何违反,当场报错。所以如果你要给模型新增一种"能看到的新输入",就必须先新增一个会话事件类型——这不是建议,是强制。
为什么这么较真?因为 dsh 的 fork、恢复、回放、遥测、UI 渲染,全部派生自这条事件流。deriveMessages() 从日志投影出模型历史,原始的事件 chunk 保留着回放保真度。一旦日志不完备,所有这些派生功能全错。
这套机制带来了前两代都没有的能力:
这条不变式是 dsh 全部架构里"最不性感、但最值钱"的设计。它不产生任何炫酷的演示效果,但它决定了这个 Agent 值不值得被信任——尤其是当它要跑长任务、跑不可信代码、或者在合规场景里被审计的时候。
顺带说一句工程纪律:为了让这套机制可信,dsh 把正确性从"口头规范"变成了"运行时硬断言"。它还做了一件事——文档是自动生成的。docs/subsystems/*.md 那些几万字的规格、模块依赖图、事件消费关系图,都是从代码和类型声明里抽出来的,CI 里有新鲜度门禁,文档和代码脱节直接挂。对一个想深入研究它的人来说,这一点太重要了。
"一切皆插件"要真正好用,光有理论还不够,还得有一个清晰的扩展模型。dsh 把它叫作 seam(接缝),固定三个角色:
这三个角色各自独立演化,是 dsh 的纪律:加一个能力,意味着设计完整的三个角色,而不是只写一个实现。一代的 Hook、二代的扩展都在强调"可扩展",但 seam 把"扩展"的形式定死了——不是往上叠加,而是定义接口、替换实现。
这个设计有一个精妙的效果。看这个例子:文件系统与子进程的提供方共享同一个"执行世界"。所以你把它们指向一个远程沙箱,Bash、PTY、LSP 会一并被搬过去——不需要为每种能力写专门的远程分支。你换 Provider,所有消费方自动跟着变,因为它们只依赖接口,不依赖具体实现。
这个模型还回答了一个很多人会问的问题:dsh 和 Claude Code / Codex 到底是什么关系?
答案是:在 dsh 的抽象里,它们不是竞品,而是可替换的零件。dsh 的 subagent 能力提供了一组 provider——subagent-claude-code、subagent-codex、进程内 fork、SDK 直连……你的 dsh Agent 跑着跑着,可以把一个轮次委派给 Claude Code 去干;反过来,Claude Code 也可以把 dsh 当成一个可调用的子 Agent。
在第一代的世界里,Claude Code 是终点;在第三代的视角里,Claude Code 和 Codex 只是"实现同一个 subagent 接口的不同提供方"。这个格局,比"谁更智能"的竞争高出整整一层。
有人给这个定位起了个名字:dsh 想当"Agent 世界的 Kubernetes"——不跟你抢上层应用,而是定义底层的组合与运行规范。
把三代放在一张表里看,进化逻辑一目了然:
维度 | 第一代 Claude Code | 第二代 Pi | 第三代 dsh |
|---|---|---|---|
内核 | 大而全,闭源黑盒 | 极薄,约 1,370 行 | 没有特权核心,每一块都可替换 |
扩展 | Plugin 聚合 Skill / MCP / Hooks,叠加在闭源内核上 | 事件总线 + TS 模块,加法式 | 能力 seam,替换式 |
会话 | 私有格式,产品自管 | 树形会话,喂 UI 的瞬时事件 | 唯一事实源日志,可审计、可续跑、可回放 |
安全 | 产品自带确认弹窗,不可定制 | 不内置,用户自己容器化 | 沙箱、文件策略、审批做成内建 seam |
掌控权 | 只能扩展,不能拥有 | 全开源,可拼装 | 全开源,可换一切 |
三代各自的答案,也可以浓缩成三句话:
进化不是单纯的功能竞赛,它一直在解决两件事:把"扩展"从厂商的恩赐变成系统的地基,把"可靠性"从用户自理变成运行时保证。一代把前者做成了产品功能,二代把前者做到了极致、但留下了后者的空白,三代同时补上。
进化的结果甚至写进了账单。第三方实测:在同一个 DeepSeek 模型上,Claude Code 的 harness 每次任务成本接近最便宜 harness 的 7 倍(约 0.195 vs 0.028),因为它的请求形态不是为 DeepSeek 的前缀缓存设计的。换句话说——你选的架构,会左右你的账单。第一代的"大而全"在体验上无可挑剔,但它的骨架决定了它对某些模型并不经济。
还有一个信号值得注意:dsh 发布当天,插件生态就自发成型——dsh-web-ui、dsh-cc-tui、dsh-vision-toolkit 等一批 dsh-plugin 话题下的项目冒了出来,现在社区目录收录的插件已达上千个。一个开源项目的插件生态在发布当天就自发组织起来,这本身就是"开放范式"最有力的注脚——它和第一代"厂商定义生态"、第二代"社区小生态"形成了鲜明对照。
写到这里,给一个不绕弯的判断。它不只是"要不要用 dsh",更是"你处在三代中的哪一代需求"。
第三代真正适合的场景:
现在还不适合的:
如果你是第一代用户,追求开箱即用和成熟生态,Claude Code 依然是低风险选择;如果你享受"完全拥有"的感觉,Pi 已经把第二条路走到了极致。三代不是互相取代,而是按需求分层。
最后回到开头的判断。
你未必需要今天就迁移到 dsh。但理解这条进化线,对每个用过 AI Agent 的人都有价值,因为它回答了一个所有 Agent 项目迟早要面对的问题:
当 Agent 从"个人玩具"走向"生产工具"时,什么样的架构才能让它可信、可维护、可演进?
一代证明了 Agent 可以成为产品,二代证明了 Agent 可以属于个人,三代给出了生产工具的答案:可逆副作用让你敢装敢卸;会话日志唯一事实源让你敢让它跑长任务、敢审计它;能力 seam 让你敢把它嵌进更大的系统;运行时不变式把"正确性"从口号变成了机器保证。
历史上有过相似的剧本:浏览器靠开放扩展生态爆发,编辑器靠插件市场繁荣。编程 AI Agent 的三代进化,走的是同一条路——让 Agent 的每一块都能被替换,让组合本身成为一门有理论支撑的学科。
你可以不用它,但你很难忽视它代表的趋势:Agent 正在从一个"产品",变成一个"可插拔的操作系统"。
npx @deepseek-ai/dsh web 即可体验)docs/architecture.md——官方说改 packages/ 之前必读dsh-plugin 话题、awesome-deepseek-harness 精选清单