随笔
#Cordis#DeepSeek Harness#插件系统#可逆 effect#Agent 运行时

Cordis 的时空可组合机制:以 DeepSeek Harness 为例解析插件化 Agent 运行时

本文以 DeepSeek Harness 作为贯穿案例,解析 Cordis 元框架如何通过共享 context、插件、可逆 effects、reactive coeffects、服务注册、事件和配置组合实现空间与时间组合。文章区分了 Cordis 通用机制、Harness 已实现内容和合理推断,并通过对比表格与 Mermaid 流程图展示一次代码任务中数据与状态的流动,以及可逆 effect 在卸载、热更新、错误恢复中的价值。

从一次代码任务说起

假设你正在使用一个编码 Agent 修复仓库中的失败测试。你发出指令,Agent 读取文件、运行测试、修改代码、再次运行测试,直到通过。这个过程中,模型只是生成意图,真正执行动作的是 harness——围绕模型构建的运行时。如果 harness 是单体式的,工具执行、会话状态和推理循环都挤在同一个进程里,那么一次容器重启就会丢失整个会话,更换模型需要重启所有内容,水平扩展也会因为每个实例持有过多状态而受阻。

Cordis 是一个元框架,它不直接提供 Agent 能力,而是提供一种组织运行时的方式:通过插件、共享 context、可逆 effects 和 reactive coeffects,把系统拆成可替换、可组合的部件。DeepSeek Harness 正是基于 Cordis 构建的 Agent 运行时,它把模型适配器、工具注册表、会话日志、agent loop、审批/沙箱、遥测等都组织成可替换插件。本文以 Harness 中加载一个工具插件并执行一次代码任务为贯穿场景,解释 Cordis 的时空可组合机制,并区分哪些是 Cordis 通用机制、哪些是 Harness 已实现、哪些是基于架构的推断。

空间组合:共享 context 与插件树

空间组合解决的是“系统由哪些部件构成、它们如何连接”的问题。传统依赖注入或事件总线也做组合,但 Cordis 的组合单元是插件,插件之间不直接互相 import,而是通过共享的 context 协作。

在 Cordis 中,context 是一个贯穿整个运行时的对象,它承载服务注册表、配置、事件总线、coeffects 等。插件在启动时被加载,并可以访问 context 来注册自己的服务、订阅事件、提供配置。插件之间不直接调用,而是通过 context 间接交互。例如,一个工具插件会注册一个工具服务到 context,agent loop 插件通过 context 获取该服务并调用。

DeepSeek Harness 的插件树在启动时由 profile、bundle 和 patch 构造。profile 定义了一组插件的集合,bundle 是插件的打包单元,patch 则是对已有配置的覆盖或修改。启动时,Harness 根据 profile 加载相应的 bundle,应用 patch,最终构造出运行时插件树。这个树中的每个节点都是一个插件实例,它们共享同一个 context。

这种组合方式与普通插件系统的区别在于:普通插件系统往往只提供“加载”和“调用”,而 Cordis 的插件通过 context 可以访问系统的其他部分,从而实现更灵活的组合。例如,工具插件可以通过 context 获取遥测服务,自动上报执行指标,而不需要显式依赖遥测插件。

时间组合:可逆 effects 与 reactive coeffects

时间组合解决的是“状态如何随时间变化、如何回滚”的问题。传统 Agent 框架中,工具执行会产生副作用,比如修改文件、发送请求,这些副作用通常是不可逆的。如果后续步骤失败,很难恢复到之前的状态。

Cordis 引入了可逆 effects 的概念。一个 effect 是一个描述“做什么”的对象,它包含一个执行函数和一个撤销函数。当插件执行一个 effect 时,系统会记录它;如果需要回滚,系统会调用撤销函数。这样,状态变化可以被追踪和逆转。

reactive coeffects 则是“对变化的反应”。当 context 中的某个状态变化时,coeffects 会触发相应的回调。例如,当工具执行完成时,coeffects 可以自动更新会话日志。

在 DeepSeek Harness 中,可逆 effects 用于管理工具执行和状态修改。例如,一个编辑文件的工具执行时,会先记录原文件内容,执行修改后,如果后续步骤失败,可以撤销修改。这种机制使得错误恢复成为可能:当 agent loop 检测到异常时,可以回滚到上一个一致状态。

一次代码任务的完整流程

下面以“修复失败测试”为例,描述数据与状态在 Harness 中的流动。

  1. 用户输入:用户通过 CLI 发送指令“修复失败的测试”。
  2. session event:Harness 将用户输入作为 session event 追加到会话日志。
  3. 构建上下文:agent loop 从会话日志中取出相关事件,构建模型请求的上下文,包括系统提示词、工具 schema 等。
  4. 模型请求:调用模型,传入上下文。
  5. 模型响应:模型返回一个工具调用意图,例如“运行测试”。
  6. 工具执行:agent loop 解析工具调用,通过工具注册表找到对应工具,执行它(在沙箱中)。
  7. 结果回写:工具执行结果作为 tool result 追加到会话日志。
  8. 下一步请求:agent loop 再次构建上下文(包含新的结果),调用模型,直到没有工具调用为止。

在这个过程中,会话日志是模型可见上下文的唯一来源。它记录了所有事件,包括用户消息、模型响应、工具调用和结果。如果 harness 重启,可以从会话日志恢复现场。

下面用 Mermaid 流程图展示这一流程:

flowchart TD
    A[用户输入] --> B[追加 session event]
    B --> C[构建上下文]
    C --> D[调用模型]
    D --> E{有工具调用?}
    E -- 是 --> F[执行工具]
    F --> G[追加 tool result]
    G --> C
    E -- 否 --> H[结束]

可逆 effect 如何影响状态与恢复

可逆 effect 在 Harness 中的具体体现是:每个工具执行都包装成一个 effect,记录执行前状态。当发生错误或用户取消时,可以撤销已执行的效果。例如,如果 agent 修改了多个文件后,在运行测试时发现失败,可以回滚所有文件修改,恢复到初始状态。

这种机制对错误恢复至关重要。传统框架中,一旦工具执行失败,会话可能处于不一致状态,难以继续。而可逆 effect 允许系统回滚到一致状态,然后重试或终止。

配置覆盖也是通过 patch 实现的。在启动时,patch 可以修改插件的配置,例如更改模型提供商的 API 端点。这种覆盖是可逆的,因为 patch 本身也是 effect,可以撤销。

unload 是 Cordis 的一个特性,允许在运行时卸载插件。当卸载一个插件时,它的所有 effects 会被撤销,服务会从 context 中移除。这实现了热更新:你可以替换一个插件而不重启整个系统。

与普通插件系统、DI/事件总线、无可逆 effect 框架的对比

下表对比了 Cordis 与普通插件系统、传统 DI/事件总线、无可逆 effect 的 Agent 框架在几个关键维度上的差异:

维度Cordis普通插件系统传统 DI/事件总线无可逆 effect 的 Agent 框架
组合方式插件通过共享 context 协作插件直接依赖或通过接口组件通过容器注入依赖模块直接调用
卸载支持,可撤销 effects通常不支持不支持不支持
热更新支持,可替换插件有限支持不支持不支持
可测试性高,可 mock context
失败恢复可回滚到一致状态
适用条件需要频繁演进的复杂系统简单插件化依赖管理清晰短生命周期任务

这个表格说明,Cordis 在组合灵活性和恢复能力上更强,但代价是学习曲线和实现复杂度。对于快速原型,普通插件系统可能足够;对于长期运行的生产系统,Cordis 的可逆 effects 和热更新能力更有价值。

边界与反例:什么情况下 Cordis 的机制不适用

Cordis 的机制并非万能。首先,可逆 effects 要求副作用是可撤销的。对于外部 API 调用,撤销可能意味着发送补偿请求,但并非所有 API 都支持。例如,发送邮件后无法撤回。因此,对于不可逆的副作用,可逆 effects 只能记录,不能真正回滚。

其次,共享 context 可能导致隐式耦合。插件通过 context 交互,如果 context 结构不稳定,插件之间的依赖关系会变得模糊,增加维护难度。

第三,热更新虽然强大,但需要插件实现良好的生命周期管理。如果插件持有外部资源(如数据库连接),卸载时未正确释放,会导致资源泄漏。

最后,Cordis 的抽象层较多,对于简单任务可能过于复杂。一个简单的 CLI Agent 可能不需要可逆 effects,直接调用工具即可。

结论

Cordis 通过共享 context、插件、可逆 effects 和 reactive coeffects,实现了空间和时间上的可组合性。DeepSeek Harness 利用这些机制,将模型适配器、工具、会话日志等组织成可替换插件,使得系统可以灵活演进、可靠恢复。然而,这些能力需要付出实现复杂度和学习成本。对于需要长期运行、频繁更新、高可靠性的 Agent 系统,Cordis 的机制提供了显著优势;对于简单场景,传统方法可能更合适。

资料来源

  1. 为什么你的智能体控制架构应该是无状态的:在生产环境中实现大脑与双手的解耦
  2. Agent Engineering 101|01|Agent Harness
  3. Agent Harness 不应该是一个框架,而应该是一堆可替换的 Worker | SOTA Sync
  4. docs/01-architecture.md
  5. Build Harness · 从 0 到 1 构建 Agent 与 Harness · Learn- Agent