DeepSeek Harness:Cordis 如何让插件可卸载、可依赖、可重组

Cordis 如何让插件可卸载、可依赖、可重组

01-lifecycle-cover

把一个工具塞进注册表并不难。真正麻烦的是它离开以后发生什么。

假设一个 Workspace 插件注册了文件服务、监听器、Prompt 片段和一个定时任务。用户切换项目时,插件被卸载:监听器有没有解除?Prompt 片段会不会重复?依赖文件服务的工具应该立即消失,还是继续拿着已经失效的引用?如果配置热更新再次装载同一个插件,系统里会不会留下两份副作用?

这才是 DeepSeek Harness 选择 Cordis 的关键。首篇文章讨论的是“为什么连 Agent Core 都进入插件图”,本篇只回答下一层问题:当插件、服务和依赖会在运行期间出现与消失时,Cordis 用什么机制维持边界?

我的结论是:Cordis 的价值不在于再发明一套依赖注入,而在于把服务依赖和副作用回收都纳入 Context 生命周期。它让“装上能力”和“完整撤销能力”成为同一份插件合同的两面;代价是团队必须把依赖、事件模式、disposer 和最终组合图当作一等工程对象。

普通注册表只回答“有什么”,生命周期还要回答“何时有效”

02-registry-vs-lifecycle

最简单的插件系统通常有一个 Map:插件启动时注册工具,主程序按名称查找,进程退出时操作系统回收全部资源。这种模式在静态、小规模应用里完全够用。

但 Agent Runtime 的能力边界经常不是静态的:

  • 某个 Agent 或 Workspace 只在自己的作用域里拥有一组工具;
  • 文件、Shell、模型或 Web Provider 可能随配置和部署环境变化;
  • Prompt 片段、工具 Schema 和事件监听器要随插件一起装卸;
  • 热更新或产品 Patch 会重建一部分组合,而不是重启整个宿主。

这时,registry.set() 只能说明某个对象现在存在,不能说明谁创建了它、谁依赖它、何时失效、销毁时需要撤销哪些动作。把这些问题散落在每个插件的启动和停止函数里,会让清理顺序与依赖顺序逐渐变成隐含知识。

Cordis 试图把这种隐含知识显式化。固定版本的 DeepSeek Harness Cordis Primer 将机制压缩成五个概念:Plugin、Context、inject、typed events 和 reversible effects。它们不是五个并列名词,而是一条生命周期链。

Context:服务仓库,也是插件作用域

03-context-inject-evidence

Cordis 的 Context 首先是服务仓库。服务占用稳定的 ctx.<key>,例如 ctx.toolsctx.llmctx.sessions;消费者通过 key 使用能力,而不是直接导入某个具体实现。

但如果只看到“按 key 取服务”,就会把 Context 误解成普通容器。它还限定插件运行的作用域:插件在这个 Context 中注册服务、事件和其他副作用,这些动作可以随着作用域销毁而回收。

这让一个能力至少有两个坐标:

  1. 空间坐标:它在哪个 Context 中可见,哪些消费者能访问;
  2. 时间坐标:它从何时开始有效,随哪个插件或子作用域一起结束。

DeepSeek Harness 的固定架构文档因此强调,模型适配器、工具注册表、Session Log、Agent Loop 都是共享 Context 中的插件贡献。所谓“没有特权核心”,并不是核心不存在,而是核心能力也要遵守相同的作用域和生命周期规则。

inject:把启动顺序改写成依赖条件

04-provider-change-loop

普通启动脚本喜欢写成固定顺序:先数据库,再工具,再 Agent Loop。顺序一旦变化,消费者可能在 Provider 尚未就绪时启动;为了修补问题,代码里又会出现更多等待、重试和条件分支。

Cordis 让插件通过 inject 声明所需服务。固定 Primer 的表述很明确:声明了必需服务的插件要等这些服务存在后才激活。于是,装载条件来自服务需求,而不是开发者手工维护的一串启动序号。

可以把它理解为:

Provider 出现
  -> 所需 service 可用
  -> 满足 inject 的 Consumer 激活
  -> Consumer 注册自己的 effects

Provider / 上层作用域消失
  -> Consumer 生命周期结束
  -> Consumer effects 回收

这个变化很重要。Provider/Consumer 不再只是静态架构图上的箭头,而是能影响插件何时存在的运行条件。

但“声明依赖”不等于“动态变化天然安全”。多个 Provider 同时变化时的顺序、消费者持有的外部资源、正在执行的请求以及失败恢复,都仍需要实现和测试。Cordis 提供的是协调语义,不是可靠性证明。

effect:注册动作必须带着撤销方法

05-effect-events-evidence

插件最常见的泄漏不是内存本身,而是忘记撤销注册:事件监听器仍在接收消息,Prompt 片段被重复拼接,工具 Schema 留在目录里,定时任务继续运行。

Cordis Primer 的实践规则是:每个注册都应有 disposer。插件可以通过 ctx.effect() 返回清理函数,也可以使用已经处理清理的 Cordis helper。若清理顺序重要,相关工作应放在同一个 effect 中,让销毁按预期次序展开。

因此,effect 不是“执行一次函数”的花哨名字,而是一份双向合同:

mount:   注册服务 / 监听事件 / 增加 Prompt / 启动资源
dispose: 撤销服务 / 解除监听 / 移除 Prompt / 释放资源

这也是“Everything is a Plugin”能够进入 Agent Core 的必要条件。如果 Agent Loop、Session 或工具目录只能装载、不能撤销,那么动态组合最终仍会退化为“一次启动、永久存在”的静态宿主。

这里同样不能过度推断。框架要求 disposer,不代表所有插件都写对了;本篇没有系统级反复装卸、故障注入或长时间资源监测,不能把可逆 effect 写成“已经验证无泄漏”。

typed events:事件模式本身也是接口合同

06-event-dispatch-contract

插件解耦以后,大量协调会通过事件完成。固定 Primer 区分 emitwaterfallparallelserial 四种 dispatch mode;它们是否等待、是否有返回值、按什么方式传播,都属于事件公开合同。

尤其容易误用的是 waterfall。它不是简单的“按顺序通知所有监听器”,而是 around-middleware:监听器收到 next(),可以委托给后续监听器,也可以直接返回并短路。只想观察或补充信息的监听器必须继续委托;拥有单一决策权的策略监听器才适合截断。

这意味着,事件名相同远远不够。替换一个 Provider 或策略插件时,还要保证:

  • 监听器知道自己是观察、包装、并行处理还是顺序决策;
  • 应当委托的 waterfall 不会误短路;
  • 返回值、错误和副作用顺序与消费者预期一致;
  • 卸载时监听器会随 effect 一起解除。

所以事件模式不是实现细节,而是能力契约的一部分。

一条完整 seam 需要三个角色

07-capability-seam-evidence

DeepSeek Harness 的固定架构把可替换能力接缝拆成三个角色:

  1. Service Definition:声明稳定接口与 Context key;
  2. Provider:提供具体实现;
  3. Consumer:使用能力,常见形态是面向模型的 Tool 或上层 Runtime 组件。

例如,文件系统接缝不能只看 ctx.fs 的类型。还要看本地、远端或 Sandbox Provider 怎样实现它,以及文件工具、LSP、Shell 等消费者依赖哪些错误、安全和路径语义。

官方生成的 Capability Seams 图列出了大量服务与包之间的登记关系。这张图适合回答“谁声明、谁提供、谁直接消费”,却不能单独回答“替换后是否兼容”。一个新 Provider 即使通过类型检查,也可能在流式事件、错误分类、权限策略或资源释放上破坏消费者假设。

因此,判断 seam 是否成立,至少要检查四层:接口能否对上、事件模式是否一致、生命周期能否回收、行为语义是否兼容。前三项是结构条件,第四项仍需要契约测试和真实运行证据。

Context、inject、effect 如何形成生命周期图

08-complete-lifecycle-map

把前面的机制合在一起,可以得到一张比“插件列表”更有用的检查图:

Context 创建作用域
  -> Provider 插件挂载
  -> service 出现在 ctx.<key>
  -> inject 条件满足
  -> Consumer 插件激活
  -> effect 注册事件 / Prompt / Tool / 子资源
  -> typed events 按合同协调运行
  -> 配置变化、Provider 消失或作用域销毁
  -> Consumer 停止并回收 effects
  -> Provider effects 回收
  -> Context 释放

这张图的关键不在箭头多,而在每个正向动作都应该找到反向路径:谁让它出现,什么条件让它有效,谁负责撤销,撤销后消费者如何停止。

如果团队无法回答这些问题,所谓动态插件化就只完成了“装上”,没有完成“生命周期”。

什么时候值得做成 seam

不是每个函数都需要 Provider。把所有细节都抽象成 Context service,会把调用链变成庞大的组合图,增加调试、配置和迁移成本。

一个能力值得成为 seam,通常至少满足一项:

  • 不同部署需要替换实现,例如本地与远端文件系统;
  • 能力需要独立装卸或只在局部 Agent/Workspace 生效;
  • 多个消费者需要共享稳定边界,但不能依赖具体包;
  • 生命周期、权限或资源所有权需要由单独 Provider 管理;
  • 测试需要装配更小的能力图或故障 Provider。

反过来,如果实现固定、调用者单一、生命周期与宿主完全相同,普通函数、显式对象或构造器注入可能更清楚。抽象的价值来自真实变化,不来自“插件化”这个标签。

团队采用前的生命周期检查表

09-seven-point-checklist

检查对象必须回答的问题当前公开证据能证明什么
Context能力在哪个作用域可见,谁拥有它固定文档给出服务仓库与作用域模型
injectConsumer 依赖哪些 service,缺失时何时停止固定 Primer 给出声明依赖与等待激活语义
effect每项注册的 disposer 在哪里,清理顺序怎样固定 Primer 要求 disposer 与可逆注册
eventdispatch mode、委托、短路和返回值是什么固定文档给出四种事件模式及 waterfall 规则
seam定义、Provider、Consumer 是否齐全固定架构和生成能力图可以核对角色关系
行为兼容错误、流式、安全与资源语义是否一致不能靠能力图证明,需要契约测试
系统可靠性反复装卸、并发变化、长时间运行是否稳定当前未验证,需要故障注入和资源监测

这张表是本篇唯一主要产物。它刻意把“源码已经设计出来的机制”和“采用者还必须验证的行为”分开,避免从架构图直接跳到生产结论。

结论

Cordis 让 DeepSeek Harness 的插件不只是“可以注册”,而是拥有明确的存在范围、依赖条件和回收路径。Context 提供作用域,inject 表达激活条件,effect 把注册与撤销绑定,typed events 规定协调方式,Service Definition、Provider、Consumer 则组成完整能力接缝。

这套机制确实让 Agent Core 更容易被拆开和重组,但没有消灭复杂度。复杂度从手写启动顺序和核心分支,转移到了依赖图、事件合同、disposer、配置与诊断。对于多产品、多部署、局部能力和动态生命周期,这种转移可能值得;对于固定、简单的应用,普通依赖注入仍可能更便宜。

现阶段最准确的评价不是“Cordis 已经证明了动态 Agent Runtime 更可靠”,而是:它给出了一套可以被源码检查、也必须被故障测试的生命周期合同。

参考资料

  1. DeepSeek Harness 固定 Commit Cordis Primer:https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/cordis-primer.md
  2. DeepSeek Harness 固定 Commit 架构文档:https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/architecture.md
  3. DeepSeek Harness 固定 Commit Capability Seams:https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/capability-seams.md
  4. Cordis 官方仓库:https://github.com/cordiverse/cordis
  5. DeepSeek Harness Python SDK(动态版本边界):https://pypi.org/project/deepseek-harness-sdk/

证据与推导边界

  • Context、inject、typed events、effect/disposer:固定 Commit 官方文档事实。
  • Service Definition、Provider、Consumer:固定架构与生成能力图事实。
  • “复杂度转移到组合、契约和诊断”:基于上述机制的作者工程分析。
  • seam 适用条件与生命周期检查表:作者建议,不是 DeepSeek 官方采用承诺。
  • 反复装卸、并发变化、资源泄漏、真实模型 E2E 与生产稳定性:尚未验证,不作结论。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

武子康

谢谢你的喜欢 我们一起无限进步

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值