第七部分 · 结语
第 19 章:结语——插件化的赌注
它赌了什么、哪些模式值得带走、哪些代价还没有付清
回望:三条路线,一个共同问题
把三本书放在一起,它们其实是同一个问题的三个答案。问题在《Pi Agent 源码解析》里第一次提出:Agent 的复杂性应该放在哪里?pi 的回答是「挡在核心之外」——核心小而稳,复杂性进扩展系统;《Prime Agent 源码解析》的回答是「搬进解释器之内」——持久 IPython 让一切能力成为命名空间里的值;DeepSeek Harness 的回答是「宣布核心不存在」——模型适配、工具注册表、会话日志、Agent 循环,全部是配置拼出的插件树里平等的一行。
这一章不重复结论,而是做三件事:盘点 dsh 的架构赌注、提炼可迁移的模式、诚实面对尚未付清的代价。
架构赌注盘点
| 赌注 | 内容 | 对应章节 | 目前的证据 |
|---|---|---|---|
| 插件化的彻底性 | 没有特权核心;循环本身是实现 AgentFactory 的插件 | 第 1、3 章 | Agent 接口与 agent-loop 分属两包;换循环不需要动其他子系统 |
| 日志即真相源 | 消息从日志派生而非存储;「模型可见 ⟺ 已记录」是运行时不变式 | 第 4、14 章 | 重放、fork、UI、持久化全部从同一事件流派生 |
| 能力接缝三件套 | 可替换能力 = 定义/提供/消费三角,缺一不算 seam | 第 7 章 | e2b 实证:换两个 provider,Bash/PTY/LSP 整体搬家 |
| 默认行为也是插件 | 瀑布的最内层 next() 就是框架默认值 | 第 3、5 章 | pre-step/request/execute 全是 around-middleware 链 |
| 自修改可行且可控 | 模型用 Cordis 原生词汇安装/卸载插件;trust boundary 而非 security boundary | 第 16 章 | 工具族 + 白名单门面 + 审批 + 内存态 |
| 类型系统即协议 | TS 类型生成跨进程 wire 契约与运行期 schema | 第 17 章 | Typert 四件套;编辑器跳转直达 Host 方法 |
这些赌注共享同一个底层信念:可组合性比便利性更重要。每个决策都牺牲了一点「开箱即用的顺滑」(想想第 16 章的 cordis_define 要求模型写返回插件的函数体),换来一点「替换与组合的自由」。这是 dsh 与多数 agent 框架最根本的分歧点。
可迁移的模式
以下模式不依赖 Cordis、不依赖 dsh,可以直接搬进任何 agent 系统:
- 「模型可见 ⟺ 已记录」作为机器检查的不变式(第 4 章):请求与日志派生结果逐字节比对,desync 在发出前 fail——比任何「我们保证记录一切」的承诺都可靠。
- 双层记录:原始流 + 组装结果 + 引用链(第 4 章):chunk 级保重放、message 级保投影,
sourceEventSeqs串起两者——两条消费路径不互相妥协。 - 队列即日志投影(第 3 章):inbox 每条变更先落事件再改内存——重启可恢复、可审计、可证「模型看到了什么」。
- request/spec 显式解析(第 7 章):Consumer 给愿望、Provider 的
resolve()显式填默认与封顶——「默认值从不在 run() 里悄悄 ?? default」。 - 能力三件套与「换插头不动电器」(第 7、8 章):定义/提供/消费独立成包;沙箱是 wrap-argv 接缝而非进程管理——接口越小,复用面越广。
- 失败永远有名字(第 7、9 章):稳定错误码、denial 方言按后端隔离、runner 失败与命令被拦分开归因——「沙箱坏了」与「命令被拦」必须可区分。
- 有类型的取消协议(第 3 章):
AgentCancelCause+AbortSignal.reason+ wake 闩锁——取消从布尔标志升格为可区分意图、可收敛、可恢复的领域概念。 - 进程树是资产(第 7 章):kill 打整棵树、SIGTERM→SIGKILL 升级、PID 复用防护——「助手进程不能比 handle 活得久」。
- 生态翻译层(第 16 章):加载未修改的竞品 hooks.json,把两种 decision 通道归一成一个枚举再映射进自家类型系统——协议兼容是翻译层不是适配器。
- 配置是叠加层(第 2 章):patch 分层 + 整段替换 + 上层压过下层 +
--dump-config把合成结果变成可检查事实。
未尽的代价
一本书只讲亮点是不诚实的。dsh 的赌注也有明确的账单:
- 学习曲线陡峭:理解「没有核心」需要先理解 Cordis 的 Context/Service/effect/waterfall——一个新贡献者的第一周会花在「这棵树怎么长出来的」而不是「加一个工具」。仓库对此的回应是完善的文档体系(架构文档、子系统页、cookbook),但文档不能替代直觉。
- 调试的间接性:一切行为都是事件流与瀑布的组合——「这个工具为什么被拒?」要顺着 pre-execute 瀑布、守卫、审批接缝一层层找。日志可重建性缓解了问题,但没有消除它。
- 「可替换」的税:每个接缝都要维护三件套与词汇、错误码、能力协商——接口本身的成本。对只有一套实现的小系统,这是纯开销。
- pre-release 的代价:仓库明言「THERE WILL BE COMPATIBILITY-BREAKING CHANGES」,
SESSION_FORMAT_VERSION = 0不承诺兼容。这本书基于0.1.0-rc.5,很多细节可能已经漂移——读者应以源码为准。 - 自修改的安全边界:trust boundary 而非 security boundary 意味着动态插件与 bash 同信任级——对多租户或不可信输入的部署,这还不够。它的价值在于「开发者的运行时」,不是「沙箱化的一切」。
pi 教我们「核心可以小」;Prime 教我们「执行可以通用」;dsh 教我们「核心可以不存在」。但它们不是替代关系,而是同一问题域的三个切片:工具调用范式解决「模型怎么用能力」,一切皆程序解决「能力怎么被通用地表达」,一切皆插件解决「系统怎么被无限地重组」。读三本书时,值得记住的是各自的代价:pi 的代价是扩展系统与核心的边界管理,Prime 的代价是解释器把一切拉平后的调试难度,dsh 的代价是把「可替换」本身变成了要维护的资产。
实践应用
- 先问「哪个范式匹配你的问题」:不是所有 agent 都需要插件化——如果你的能力集稳定、部署单一,三件套与瀑布的税可能不值得付。
- 从日志与不变式开始:即使不插件化,「模型可见 ⟺ 已记录」与双层记录也值得任何 agent 系统采用——它们是审计与调试的地基。
- 把「可替换性」当显式需求:只有在确实需要多后端(本地/沙箱/远端)时才做三件套;否则先做单实现,把接缝留成接口。
- 诚实面对失败:dsh 最强的气质是「失败永远有名字」——空响应是可重试的错误、沙箱坏与命令被拦可区分、压缩是日志里的一笔事务。这个气质比任何具体机制都值得带走。
总结
这本书从「一切皆插件」的 README 第一句话出发,追完了启动装配、核心循环、能力接缝、多代理、持久化、扩展生态与界面协议,最后在结语里盘点了赌注、模式与代价。DeepSeek Harness 是一个在 developer preview 阶段就敢于把「没有特权核心」写进架构文档的项目——它的价值不在于每个机制都正确,而在于它证明了一件事:agent harness 的复杂性可以不是一座城堡,而是一片可以无限重组的森林。至于这片森林是否会长成你想要的样子,答案在源码里,也在你的下一次重构里。