返回《DeepSeek Harness 架构设计指南》

Capability Seam 能力接缝

IT周瑜

dsh 的包目录里有几十个包,lsp、fs、shell、web、workflow、terminal,每个都对应一种能力。这些能力如何被定义、实现和使用,答案是一套统一的三角色结构,项目称之为 capability seam,能力接缝。本章讲清这套结构,它是理解 dsh 包组织的钥匙,也是把这套架构迁移到自己系统时最值得照搬的模式。

一个接缝由三个角色构成。Service Definition,服务定义,声明一个能力的接口,通常是一个挂在 ctx 名字下的服务,比如 ctx.shell。Service Provider,服务提供者,给出这个接口的一个具体实现,比如在本地进程里执行命令的实现,或者在远程沙箱里执行命令的实现。Consumer,使用者,通过接口调用能力,最常见的使用者是面向模型的工具,比如让模型执行 Bash 命令的工具。

三角色听起来只是教科书里的接口与实现分离,dsh 把它做成了强制性的工程纪律。一条接缝必须三个角色齐备才算完整,只有一个角色的包不构成接缝。加一种能力,就要同时设计定义、实现和使用三方。这条规矩防止了两种常见的腐化。一种是接口随着某个使用者的需求随手膨胀,另一种是能力只服务一个特定调用方,名存实亡。

Service Provider Service Definition Consumer 本地执行 bash-local 远程沙箱 bash-sandbox 能力契约 ctx.shell 接口 Bash 工具 tool-bash 终端工具 PTY 终端 实现 实现 调用 调用 换掉左侧任一 Provider,右侧全部 Consumer 同时切换到新实现
图 6-1 定义居中,实现可插拔,使用者只认定义,换实现时全体使用者同时切换

接缝的威力在替换时显现,拿 shell 接缝举例。定义是 ctx.shell,描述执行一条命令需要什么。提供者有两个,一个在本地起进程执行,一个把命令送进远程沙箱执行。使用者也有一排,模型用的 Bash 工具、持久终端工具、语言服务器,都通过同一个接口拿执行能力。把提供者从本地换到沙箱,所有使用者同时切换,一行使用方代码都不用改。

再进一步,fs 文件系统能力和 subprocess 子进程能力共享同一个执行世界。把它们两个的提供者一起指向远程沙箱,Bash、终端、语言服务器就整体搬进了沙箱,没有哪个能力需要单独适配。一次替换搬走一组能力,这是接缝设计预先算好的结果,文档里把这一点当作该模式的核心卖点。

子代理接缝展示了另一种跨度。ctx.subagents 定义了把任务委托给另一个 Agent 的接口,提供者的形态相差悬殊。有的在同一个进程里创建一个子 Agent,有的从当前会话日志分叉出一个副本让子代理带着前文干活,还有的把任务委托给另一个产品里的 Agent,通过外部协议通信。形态差异全部被接口挡住,主 Agent 和委托工具面对的是同一个调用方式。与 shell 接缝只允许一个执行者不同,子代理接缝允许多个提供者同时注册、按名字选用,说明接缝结构本身也可以按需变化。

对使用者来说,接缝把配置问题变成了选型问题。安全要求高的部署选沙箱提供者,本地开发的部署选本地提供者,两者在组合配置里是一行之差。对开发者来说,接缝把贡献代码的门槛降到了最低。想给 dsh 增加一种新的执行后端,只需要实现一个提供者插件,挂上去,不必碰任何现有代码。

接缝在整个仓库里的分布,可以当作一张导览图。执行环境类有 fs、shell、subprocess、terminal、sandbox,文件、命令、进程、持久终端、约束执行各占一条。模型与信息类有 llm、web、skill,模型适配、搜索抓取、技能目录各自成缝。协作与治理类有 subagent、workflow、compaction、settings、credentials、telemetry,从委托、多步工作流到配置凭证与计量。仓库的文档站提供一张自动生成的接缝全景图,由脚本从代码推导,列出每条缝的定义方、全部提供者和全部使用者。图和代码不会脱节,因为图就是代码的投影,这个做法本身也值得抄走。

判断一条接缝设计得好不好,有一个简单的试金石,看它的提供者列表是否跨越了截然不同的世界。shell 的提供者从本地进程走到远程沙箱,subagent 的提供者从进程内走到别家产品,llm 的适配器服务多家模型服务。提供者之间差异越大,接口的含金量越高。反过来,如果所有提供者长得大同小异,这条缝多半是为抽象而抽象。

回过头看第 1 章那个对比图,单体框架的问题在于功能之间没有接缝,替换无从谈起。接缝是插件化真正兑现的地方,没有接缝的插件系统只是把代码拆进了多个仓库。

能力定义好了,第 7 章回到执行周期里那个悬着的问题,模型调用工具时,调用要经过哪几道关口。