TL;DR
-
Cordis 是一个元框架——用来构建框架的框架——核心能力是一套可逆插件系统:组件可以在运行时挂载、卸载、热重载,移除时所有副作用都会被干净地回滚。
-
它的设计被系统化在一篇论文 A Programming Paradigm for Spatiotemporal Composability 里,把动态组合拆成两个维度:时间可组合性(彻底还原某组件的副作用)与空间可组合性(声明并响应式地管理组件间依赖)。
-
Cordis 作为开源聊天机器人框架 Koishi 的底座已有四年,如今又成为 **DeepSeek Harness(dsh)**的插件内核——在这里"万物皆插件":模型适配器、工具注册表、会话日志、Agent 主循环,全部是可替换组件。
-
让它成立的三套机制:ctx.effect(可逆副作用)、生命周期事件(ready / dispose / fork,保证干净拆除)、以及用于依赖排序的服务系统。
-
这对 Agent 基础设施之所以重要,是因为它让自我演化的运行时变安全了:一个能修改自身运行时的 Agent,只有当这些修改可逆时才值得拥有。
1. 为什么 Agent 需要一个插件内核
插件系统并不新鲜。从 IDE 到浏览器,几乎所有主流应用都自带插件系统,"不重启宿主就能热加载模块"的想法也已经存在几十年。所以当 DeepSeek 宣布其开源 agent harness 建立在"万物皆插件"之上时,开发者的第一反应可以理解:这和文本编辑器或 CI 工具里的插件架构有什么不同?
区别在于:Agent 运行时把插件系统推向了它们从未被设计去应对的方向。Agent 主循环不是一个挂着扩展的静态宿主——它是一套要在多个步骤之间管理状态、持有上下文、调用工具的系统,而且最重要的是,它可能在运行中途被要求修改自身行为。当系统里的某个组件被移除或替换时,所有下游依赖它的东西要么适应,要么优雅地失败。文本编辑器可以容忍某个插件留下悬空引用;一个已经承诺了多步计划的 Agent 做不到。
这正是 Cordis 要弥合的缺口。它不把插件管理当作一项便利功能,而是把组合本身当作要正式解决的问题。它背后的论文从一个观察出发:现代软件——插件系统、自我演化的 agent harness——越来越需要动态组合,但动态组合的形式化基础却一直欠发达。Cordis 就是这个基础;理解它,是理解 DeepSeek 为什么选它当 Agent 运行时底层(而不是从头写一个传统插件管理器)的最快路径。
2. 时空可组合性,拆开讲
论文标题——A Programming Paradigm for Spatiotemporal Composability——听起来吓人,但它里面的两个词,对应的是每个动态系统都会遇到的两个具体问题。
时间可组合性,指在组件被移除时能否彻底还原它的副作用。插件被卸载时,它注册的一切——事件监听器、工具定义、内存分配、命令处理器——都必须随它消失,让系统回到"这个插件从未被加载过"的状态。大多数框架能移除插件的代码;极少能保证它的副作用被完全撤销——这就是常规系统反复重载会慢慢累积泄漏的原因。
空间可组合性,指能否声明并响应式地管理组件间依赖。当插件 A 提供插件 B 要用的服务时,系统必须保证:B 只在 A 就绪后加载、在 A 停止前卸载、若 A 失败则 B 永不启动。更微妙的是,当上下文变化时——某个服务被替换、某个依赖发生转移——每个受影响的组件都必须被通知,并按照它声明的契约做出响应。
Cordis 把经典的 effect 与 coeffect 概念提升为运行时机制,从而对两者做了形式化。每一个上下文变换都带一个由运行时追踪的逆(revertible effect,可逆效应);每一次上下文变更都按组件的 coeffect 规格去通知它们(reactive coeffect,响应式余效应)。两个上下文被统一成单一 context 类型,这本身就成为一种编程范式——由此出发,组件与一套动态组合演算,让该性质从单个组件扩展到一整套交错组件的系统。
实际的收益是路径无关性:一个 Cordis 应用的最终状态只取决于启用了哪些插件,而不取决于它们的加载或卸载顺序。这个性质正是热模块替换安全的前提,也正是一个 Agent 运行时要在不损坏自身状态的前提下自我重组时所需要的那同一个性质。
3. 三大机制
Cordis 通过三个相互配合的机制来实现这套范式,它们都经由一个共享的上下文对象 ctx 暴露。
**ctx.effect——可逆副作用。**这是时间可组合性的核心。插件注册副作用时调用 ctx.effect(),并把清理函数——也就是那个"逆"——作为返回值交给它。运行时存下这个逆,并在插件卸载时执行。任何需要清理的东西——连接、内存、已注册的 handler、订阅——都放进 effect 里,Cordis 保证在拆除时按注册的逆序执行。这和 C++ 的 RAII、Rust 的 Drop trait 是同一个思想,只是从语言层面提升到了运行时层面,让即使是不同团队写的插件也能干净卸载。
**生命周期事件。**Cordis 暴露三个面向用户的生命周期事件,外加系统内部事件。ready 在生命周期启动时触发(若上下文已激活则立即触发);dispose 在上下文被卸载时触发,牵动整条清理链;fork 在每次插件加载时触发,它本身也是一个插件函数——所以一个可复用插件可以派生子上下文,每个子上下文都有自己的生命周期。内部事件(internal/runtime、internal/fork、internal/service、internal/update)负责簿记:跟踪插件状态、服务变更与配置更新。
**服务管理。**服务系统处理空间可组合性。插件通过 inject 属性声明依赖,Cordis 负责解析依赖图:插件 B 只在插件 A 提供了它所需的服务后才加载,在 A 停止之前卸载,若 A 失败则永不激活。依赖按服务名表达,这给了运行时在任意加载/卸载顺序下保证安全拆除所需的排序信息。
这三套机制合在一起意味着:Cordis 开发者几乎不需要操心清理顺序、依赖竞态或重载泄漏——框架把这些保证揽到了自己身上。代价是纪律:每个插件都必须显式声明自己的 effect 与依赖,这是一份有分量的契约,但它在 Agent 生存的环境里恰恰回报最高。
还有一个值得一提的配置层,因为它正是让不写插件代码的人也能用上这套框架的关键。Cordis 自带一个声明式组件加载器,支持配置对账与热模块替换:插件在配置里声明,而不是命令式地接线;配置一变,加载器就把"声明状态"与"运行状态"做 diff,只对变化的插件执行挂载、卸载或更新。DeepSeek Harness 文档里"在配置中选择、替换或扩展任意能力"的说法,背后的机制就是它——配置文件不是贴在静态系统上的一块设置面板,而是通向动态组合引擎本身的接口。
事件模型也值得再补一句,因为它是 Cordis 各项保证可以被审计的地方。每一次插件生命周期转换——创建了 fork、启动了 runtime、替换了服务值、更新了配置——都会发出一个带类型的内部事件。这意味着操作者可以精确观察到系统做了什么、按什么顺序、为什么。对 Agent 运行时来说,这种可审计性不是锦上添花:如果一个 Agent 重组了自身、结果出错了,事件日志正是让你还原整个序列、判断该不该回滚这次变更的依据。可逆性只有在你能说清"到底回滚了什么"时才有用。
4. 从 Koishi 到 DeepSeek Harness
Cordis 不是为 DeepSeek 而生的。它作为 Koishi的底座已经在生产环境跑了四年。Koishi 是开发者 shigma 创建的开源跨平台聊天机器人框架,名字取自东方 Project 系列里的一个角色,项目靠着构建跑在 Discord、Telegram 等平台上的聊天 Agent 累积了大约 6,000 个 GitHub star。Koishi 之所以能成为 Cordis 的合格试验场,恰恰是因为它拥有 Agent 运行时需要的东西:插件注册命令与服务、开发期热重载,以及停用后必须自己收拾干净。
Koishi 跑在 Cordis v3 上。2026 年 8 月 13 日 DeepSeek Harness 发布开发者预览版时,底层是 Cordis v4——同一天,Cordis 团队发表了驱动 v4 重设计的那篇正式论文。这个时间点不是偶然:v4 对可逆副作用与响应式余效应的明确聚焦,正是 agent harness 需要的机器;而这篇论文让更广的工程社区读懂了这台机器。两者的关联被直接写进了 DeepSeek Harness 的架构文档(点名 Cordis 是底层框架)和 GitHub 仓库(把论文作为设计出处链接)。至于 DeepSeek Harness 本身在执行层具体做什么,可参看我们的 DeepSeek Harness 解析。
四年的来历有一个务实的理由:Cordis 不是 DeepSeek 押注的一个概念验证。它是经过实战检验的软件,有成熟的插件生态、真实的社区和一份正式的规格。当你把一个内核经受住四年真实插件更迭考验的 harness 作为地基时,"万物皆插件"这句话,比那些上周才发布的框架说出来要有分量得多。
5. 万物皆插件
DeepSeek Harness(dsh)把 Cordis 的哲学贯彻到了字面层面。harness 里每一项能力都是一个插件:模型适配器、工具注册表、会话日志、沙箱、存储层、Agent 主循环,甚至 UI。harness 本身只是一个薄内核,负责挂载、卸载和追踪依赖;Agent 的真实能力全部活在它之上的插件里。
架构文档讲清了各部件如何映射到 Cordis 的 context 上。会话子系统拥有只追加的 SessionEvent 日志与内存存储,通过 ctx.sessions 暴露;系统提示子系统负责 prompt 分段与工具 schema 的组装,走 ctx.systemPrompt;工具子系统在 ctx.tools 下提供有作用域的工具注册表与带守卫的执行管线;Agent 子系统通过 ctx.agents 暴露 Agent 接口、实时注册表与 agent 事件,默认驱动在 ctx.agentLoop 上实现该接口;LLM 层贡献消息与流词汇表,以及在 ctx.llm 的适配器接缝。
插件针对这些 context 键注册能力,一切都走 Cordis 的服务与事件模型。实际效果是:想换模型后端、替换沙箱、或加一个自定义工具?在配置里挂一个插件即可——不需要 fork 源码,也不存在需要打补丁的"特权核心"。DeepSeek 开箱自带四个预设档位:Standard(完整编码 Agent,含文件系统、shell、网页搜索、子 Agent 与 plan 模式)、Code(模型生成的代码编排多轮工具调用)、Minimal(只有 bash 和一个文件编辑器——DeepSeek 自己官方模型基准测试用的就是这份配置),以及 Creator(用于带运行时检视与预设编写指导来构建自定义预设)。
这与"主循环、工具、UI 焊死在一起"的一体化 Agent 工具相比,姿态截然不同。这也是 DeepSeek 自己的基准数字可复现的原因:给 V4 Pro 打分的 harness,就是这份带插件配置的开源代码本身——这一点写在 V4 Pro 0813 的发布说明里。基准与已发布代码之间的这层关联,详见我们的 DeepSeek V4 Pro 0813 分析。
6. 这对 Agent 生态意味着什么
对一个正在评估 Agent 基础设施的开发者来说,基于 Cordis 的设计改变了"开源"在 harness 语境下的含义。开放许可证让代码可以被检查;插件内核让它可以被改造。想要不同的沙箱、自定义工具、不同的模型后端,或一个贴合你产品的 UI?挂一个插件就行,而不是维护一个 fork。插件生态会成为护城河——DeepSeek 已经通过给 GitHub 加上 dsh-plugin 话题来提升可发现性、并为该 harness 建起 Discord 社区,表明了这份意图。
还有一个值得点名的二阶效应。让 Cordis 擅长插件管理的同一个性质——可逆性——正是让 Agent 运行时可以安全地自我修改的性质。一个能重组自身技术栈、任务中途加工具、或演化自身工作流的 Agent,只有当每一项变更都能被干净回滚时才值得信任。Cordis 的可逆效应,就是把"自我修改运行时的 Agent"从研究圈的好奇之物,变成站得住的工程范式的那个机制。
与同一周那些封闭式 Agent 产品对比,也会很有启发性。DeepSeek 开源基于可逆插件内核的 harness 的同一周,xAI 发布了 Grok Bot——一个 Agent 环境是"由厂商控制的持久云电脑"的产品。两者都是对"Agent 基础设施往哪走"的押注,而它们的哲学几乎不可能差得更远:一个给你内核和插件,另一个给你 Teammate 和电脑。封闭产品那一侧的拆解,见我们的 Grok Bot 解析。
结语
Cordis 很容易被低估,因为它不做任何花哨的事——它只是管理插件生命周期、依赖排序和清理。但这三件事,恰恰是 Agent 运行时在尝试自我演化时最容易崩的地方。"组件可以被移除、其副作用全部还原,依赖对每一次上下文变更都正确响应"这一形式化保证,正是让动态组合安全到足以在其上构建自修改 Agent 的前提。
DeepSeek 选择把 harness 建在一个有四岁年龄的插件内核上、而不是一个专用一体化系统,这本身就是关于 Agent 生态走向的表态。最终胜出的 harness,不会是内置工具最多的那个——而是插件生态让"组合出你需要的工具"成本最低的那个。Cordis 给了 DeepSeek 这一点,也给了每个在 dsh 上构建的开发者同样的杠杆。无论你是要贡献一个插件、评估某个 harness,还是只想弄明白为什么"万物皆插件"不止是一句口号,那个可逆内核,都是最值得理解的部分。
常见问题
Cordis 是 DeepSeek 的产品吗?
什么是元框架?
"时空可组合性"是什么意思?
Cordis 如何清理插件的副作用?
DeepSeek Harness 的四种预设模式是什么?
为什么可逆性对 AI Agent 尤其重要?
https://floatboat.ai/zh/blog/cordis-plugin-framework
