
字节笔记本
2026年10月6日 · 约 5 分钟读完
DeepSeek Harness 的运行时不变量机制
在一个插件化的 Agent 框架里,能力被拆进许多独立的包,包与包之间靠事件流和共享状态协作。随之出现一个老问题:某个包声称成立的行为,运行时如何证明它真的还成立?DeepSeek Harness 给出的答案是运行时不变量(runtime invariant)机制:每个包自己声明并安装检查,违规按包名归属,注册、执行、失败、清理全链路由一个专门的注册服务管理。

它在框架里的位置
这套机制是框架的支撑组件之一,不在 Agent 主循环的关键路径上。它通过上下文对象暴露为 ctx.invariants 注册服务,职责只有四件事:决定哪些包参与检查、预留包名、管理子 fiber 的生命周期、把失败归属到包。
框架里的每个工作区包都发布一个 ./invariant 伴随插件,把自己的检查注册到服务里,注册名就是该包完整的 npm 包名,发布与注册都是强制项。检查的内容也有明确约定:只允许断言权威事件流或者可变数据上的事实,禁止断言某个服务是否存在、某个方法是否存在。原因不难理解,接口形状的检查只能证明接线没断,证明不了行为正确,而后者才是运行时不变量真正想守住的。
选择机制:正则过滤,启动即定型
服务插件上有三个配置字段。enabled 是全局开关,默认开启;package_allowlist 和 package_blocklist 是大小写敏感的 JavaScript 正则源数组,白名单为空表示放行所有包。
一个包被选中需要同时满足三个条件:服务开启;白名单为空,或者至少有一个模式匹配它的完整包名;没有任何黑名单模式命中。黑名单命中优先于白名单命中,这是唯一需要记住的优先级规则。
所有条目都用 new RegExp(source) 编译。匹配默认非锚定,想匹配完整包名要自己补上 ^ 和 $,/pattern/flags 这种带斜杠的写法不会被解析。校验在服务启动时一步到位:空白条目、首尾带空白的条目、重复条目、非法正则,一律直接抛错而不是静默跳过。反过来,一个合法的模式当前匹配不到任何包是允许的,这样后续加载和热更新才能保持确定性。过滤器一旦定型,在服务整个生命周期内不再变化。
安装器与失败归属
InvariantInstaller 是一个函数,接收子上下文和一个 fail 上报器,可以同步执行,也可以返回 Promise;函数对象上的 inject 字段声明这个子 fiber 可以访问哪些服务。被启用的安装器运行在专属的子 Cordis fiber 里,同步或异步执行完成之后,这次注册才算成功。
fail(message) 用来上报违规。它抛出的 InvariantError 继承自标准 Error,带稳定的 INVARIANT 错误码、所属包名,以及 invariant violated by "" 这样的前缀消息。好处很直接:违规可以精确归属到具体的包,而注册服务本身不需要导入任何产品包,依赖方向保持干净。
注册语义:名字预留与原子释放
ctx.invariants.register(packageName, installer) 按完整 npm 包名预留一个活跃注册,返回一个作用域化的 disposer。两个细节值得展开。
第一,即使过滤器让某个安装器处于不活跃状态,名字预留依然生效。两个插件不可能在过滤规则的眼皮底下静默抢占同一个包名;重复的名字、空白的名字、含空格的名字都会直接抛错。
第二,安装器失败时,子 fiber 被销毁、名字预留被释放,这两步是原子的。注册出来的检查 fiber 归服务所有,而 disposer 属于伴随插件一侧的 fiber;卸载任何一侧,监听器、trace 状态和名字预留都会被清理,所以伴随插件可以重载后再次注册同名检查,不留任何残留状态。
// 按完整 npm 包名注册一个安装器;名字即使被过滤也会预留,
// 启用的安装器在子 fiber 中执行,失败时销毁该 fiber 并释放预留。
register(packageName: string, installer: InvariantInstaller): () => void伴随契约:断言不许造假
发布与注册是穷尽的,但断言本身刻意不做合成。只有当包确实拥有可观察的事件或可变数据关系时,才安装真正的检查;没有可检查的东西,就导出一个空安装器,并且前导注释必须以 No runtime invariant: 开头,具体解释这个包为什么没有可检查的内容。

光靠约定守不住质量,框架配套了一条机械校验命令 pnpm run verify-package-invariants。它会拒绝生成出来的标记、没有解释的空安装器、忽略 fail 参数的非空安装器、注册名不对的安装器,以及导出、发布、依赖、打包接线不完整的情况。
写在最后
这套设计里有两个可以搬到任何插件系统的想法。一是用名字预留把谁负责什么变成运行时事实,而不是散落在文档里的口头约定;二是把失败归属到包,错误信息自带责任人和稳定错误码,排查时不用猜。对正在给自己的 Agent 框架加可观测性和自检能力的团队来说,这是一份可以直接借鉴的样本。



