简评:DeepSeek Harness 是对 AGI 中那个最难的"G"------通用性(Generality)------在 Agent 层面的一次工程化尝试。
参考其项目readme中的内容,在工程角度上不过多评价了,等以后落听了再说。同时参考其文档,在本文内采用"DeepSeek Harness(dsh)"dsh这个简称。
DeepSeek Harness 目前处于 开发者预览 阶段,正在快速迭代。未来将出现破坏兼容性的变更。
本文主要聊下面这句话。
采用一切皆插件 的架构,并由 Cordis 驱动,其设计参见论文 A Programming Paradigm for Spatiotemporal Composability。
背景阅读------Agent可以是什么形态,截止2026年8月
Agent在工程设计角度来讲,普遍的一个共识:这是一个循环工作模式。
- 以Pi Agent项目为例子,不断的就上下文内容和大模型展开对话,直到模型认为不需要额外的function call/tool call/mcp就停下。
其反映了生成式自回归语言大模型在交互方式上是通过上下文------上下文数组的方式来完成交互这一底层事实。对于一个数组,无非能做的就是增,删,改,查。
- 可以参考Anthropic在博客Anthropic. Using Claude Code: session management and 1M context. (2026-04-15)中提及的继续,回退,清除,压缩,子智能体(委派)
- 继续(Continue)
在同一会话中追加下一条消息。这是最自然的推进方式,让模型沿着当前的推理链条继续思考、调用工具或回复用户。适用于连贯无歧义的线性任务流。 - 回退(Rewind)
跳回到会话中的某条历史消息,从此处重新开始。这相当于代码的git reset------当推理走入死胡同、工具调用出错或用户修正了指令时,可以丢弃污染后的后续上下文,从干净节点重试,而无需从零开始。 - 清除(Clear)
开启一个全新会话,但通常携带从上一段对话中提炼出的关键摘要作为系统指令。这是最彻底的上下文重置方式,适用于任务方向发生根本改变、或者会话已冗长到不可压缩时。本质是"遗忘一切,只保留精华"。 - 压缩(Compact)
将当前冗长的会话历史总结为精炼的摘要,并以该摘要替代原始消息,从而大幅释放上下文窗口。压缩不同于清除------它保留了对话的连续性,只是提高了信息密度,让模型能在较长的任务中"记住之前做了什么",而不必背负每一轮原始对话的负担。 - 子智能体(Subagents)
将一块子任务及其所需的最小上下文打包,委派到一个拥有独立干净会话的子智能体中执行,只取回最终结果。这是上下文隔离最彻底的手段:子智能体不会看到主智能体的全部历史,反之亦然。它既是一种上下文管理操作,也是单智能体向多智能体迈进的关键一步。
对于一个生活中的任务,一般会涉及多个上下文交互,这时候我们可以用软件工程的设计模式思想解决,以 Anthropic. Multi-agent coordination patterns: Five approaches and when to use them . (2026-04-10). https://claude.com/blog/multi-agent-coordination-patterns 文章为例子,文章中提及了五种模式覆盖了从最简单到最灵活的多智能体协作形态。选型的原则不是"哪个更高级",而是"哪个刚好能解决当前问题,并在遇到瓶颈时能平滑演进"。
| 多智能体模式 | 经典设计模式 | 工程类比 | 核心思想 |
|---|---|---|---|
| 生成器-验证器 | 策略模式 + 评审闭环 | 双阶段提交、A/B 测试自动判胜 | 将"执行"与"校验"解耦为可插拔组件,通过迭代形成闭环反馈 |
| 编排者-子智能体 | 主从模式 / 聚合器 | API 网关 + 后端微服务 | 中心节点分解任务(Map),分发到工作节点,再汇聚结果(Reduce) |
| 智能体团队 | 对等网络 / Actor 模型 | 去中心化分布式计算 | 每个节点是独立计算单元,异步消息并行,无中央管控 |
| 消息总线 | 发布-订阅 / 中介者模式 | Kafka、RabbitMQ 式企业消息总线 | 引入中间件解耦生产者与消费者,新节点即插即用 |
| 共享状态 | 黑板模式 | 多专家协作的共享知识库 | 所有节点向共享知识源读写,基于彼此发现继续推进 |
| 至此,对于有一定软件工程经验/相关背景知识的读者,顶层设计模式映射和底层数据结构明确的情况下,接下来就是做一个填空题------中间层业务逻辑映射。 |
DSH and General
我们以工程视角来看DSH,如果我们要做通用人工智能下的智能体。由于智能体处于交付模型智能最后一公里的关键位置上。为了适配各种各样的场景和问题,插件这样依赖倒置的思路必然是躲不开的。以插件化的方式来回答如何实现通用性,在工程上------将控制上下文的loop做成高度插件化之后?会发生什么这是目前笔者看到的DSH和Cordis论文尝试回答的内容:
由于通用型的代价,执行过程和执行方式高度依赖外部输入,需要给外部提供"编程能力",通过配置动态调整的能力,从而导致
结构上需要:
- 插件(Plugin) :论文里的 Component(组件) + Fiber(实例)。这就是插件化架构的核心:一个可以独立加载、卸载、升级的功能单元。
- COP/AOP 思想 :这里的 Reactive Coeffects(反应式余效应) ,本质就是 AOP 的"依赖查找"加上 COP 的"按环境激活"。
ctx.get(key)就是 AOP 的 Joint Point(连接点),而依赖满足/不满足就是 COP 的 Layer 激活/停用条件。 - 注册表机制(Registry) :论文中的
Sigma(余效应上下文) +F_gamma(Fiber 注册表)。这就是一个带有类型约束(Type Family)和生命周期状态(Active/Inactive)的 Service Registry(服务注册表)。
- 运行时管理方式 :论文第 4 节的状态机(Inactive -> Reloading -> Active -> Unloading) 。这是管理组件生命周期、处理热替换(HMR)和优雅停机的工程标准实践。
由此产生的结构之间的联动:
- 资源即 Context :定义一个全局的
Context对象,所有的数据库连接、路由、事件监听都挂在这个 Context 下。 - 显式的 Provide/Inject :插件必须声明它
provides什么 Key,以及requires什么 Key。这用于构建依赖图。 - 副作用必须带
undo:插件在启动时执行的每一处修改(ctx.set),都必须返回一个dispose函数。启动函数的返回值必须是一个"所有 dispose 的链表"。 - 惰性激活(Lazy Activation) :当
requires全部满足时,执行启动;当任一requires缺失时(提供者被卸载),执行链表上的所有dispose(逆操作)。 - 版本/命名空间 :工程上避免键冲突,简单使用
Symbol或package-name:key即可,根本不需要论文里的Isolation Realm那么重的数学描述。
正如Spring的IoC + AOP可以解决大部分网页开发问题一样,思路上用COP+AOP结合反应式框架从而尝试探索通用性解决方式。
Cordis论文的讨论章节------有待继续探索的问题
结构自然有其结构性特征,在论文原文(第六章)里给出了这种设计的潜在问题,需要看细节的,请大家参考原文(虽然里边充满了形式化证明),在此拿日常中常见的改名和重名问题举例:
- 接口漂移。 一个提供者可能在版本之间修改与 (k) 关联的接口(添加字段、更改方法签名、改变行为契约),而一个针对早期接口编译的消费者继续声明相同的键 (k)。依赖关系在余效应层面得到满足((k \in \operatorname{dom}(\sigma))),但运行时值不再符合消费者的期望,导致类型错误、方法未找到失败或静默行为分歧 70。
- 键冲突。 两个独立开发的提供者可能使用相同的键名 (k) 来表示完全无关的接口。由于键身份单独建立链接,期望一个提供者接口的消费者将接受另一个提供者的值,而无需任何兼容性检查。与接口漂移(提供者和消费者至少共享共同谱系)不同,键冲突涉及预期类型和实际类型之间完全没有关系,使得由此产生的失败难以预测和诊断。
结束语
希望DSH早日结束开发者预览阶段,到那个时候看看沉淀下来什么。