ByteNoteByteNote
DeepSeek Harness 事件矩阵:谁派发,谁监听
字

字节笔记本

2026年10月6日 · 约 6 分钟读完

DeepSeek Harness 事件矩阵:谁派发,谁监听

API中转
¥120

DeepSeek 开源的 agent 框架 DeepSeek Harness(仓库 deepseek-ai/deepseek-harness,MIT 协议,目前约 24.4 万星)把「一切皆插件」写进架构原则,插件之间几乎全靠事件协作。它的 docs 目录里有一份写给贡献者的参考文档:事件生产方与消费方矩阵。这份文档由仓库脚本解析 TypeScript 源码自动生成,把每个框架自有事件的声明位置、派发方、监听方列成一张大表。读这张表,等于拿到了整个框架的线路图。

DeepSeek Harness 事件矩阵:从工具执行到会话广播的接线图

56 个事件,一张多对多的表

矩阵收录了 56 个 harness 自有事件,命名统一采用「域名/事件名」的形式:agent/、session/、tools/、workflow/、fs/、llm/、subagent/ 等前缀标明事件属于哪个子系统。事件之间是多对多关系:一个事件可以有二十多个监听方,一个包也可能既派发自己的事件、又监听别人的事件,这种密集的关系数据用表格呈现,比画一张巨大的关系图更好查。每个事件都标注了声明位置,精确到源码文件与行号,例如 agent/created 声明在 packages/core/agent/src/runtime-types.ts,从矩阵出发就能直接跳到类型定义。

文档还有一个容易被忽略的细节:监听方一栏同样覆盖有意绕过 ctx.emit 的内含派发位置,subagent 的生命周期封装被特别点名。也就是说,个别事件实际从封装代码里发出、不走标准派发口,矩阵也把它们收了进来,保证这张表是完整的。

四种派发模式,各有分工

每个事件都标有派发模式:56 个事件里 emit 占 41 个,waterfall 占 13 个,serial 与 parallel 各 1 个。分布本身就说明了设计意图:凡是需要拦截、改写或裁决的场合一律用 waterfall,比如每步执行前的 agent/pre-step,工具执行前后的 tools/pre-execute、tools/execute、tools/post-execute,文件写入意图 fs/write-intent 与 fs/edit-intent,审批请求 approval/request,模型流式输出 llm/stream,以及系统提示词组装 system-prompt/assemble。广播事实则用 emit,例如 agent/created、session/created。仅有的 serial 事件是 agent/turn-stopping,监听方是 Claude Code 与 Codex 两套 hooks;仅有的 parallel 事件是 session/flush,由持久化与遥测两个包并行消费。

DeepSeek Harness 事件矩阵的四种派发模式示意

谁在广播,谁在围观

派发侧,agent-loop 是最大的事件源,矩阵里 11 个事件由它派发,其中 10 个带 agent/ 前缀;core/agent 负责剩下的 agent/created 与 agent/disposed;tools、workflow 与 cordis-host-runner 各派发 6 个。

监听侧,session/event 是全表最大的交汇点:会话中发生的每件事都会广播成这个事件,23 个包在听,持久化、上下文压缩、遥测、会话标题、token 计量全挂在这条总线上。其次是 session/created 的 16 个监听方,以及 agent/pre-step 的 13 个监听方。

矩阵里还有 7 个事件在仓库内部没有监听方,例如 skills/change、tools/change、workflow/log、workflow/phase,它们在核心仓库内发出后无人接收。另外有些监听方不带包链接,比如 apiproxy、server、gateway、webserver,它们属于应用层装配代码,不在 packages/ 目录里。

表外的四个 internal 字符串

矩阵第二节单独列出了源码里出现、但没有声明为 harness 事件的 4 个 internal 字符串。其中 internal/dispatch 的监听方多达 22 个包,横跨 commands、compaction、sandbox-policy、terminal-bash 等,可以视为框架内部的底层分发通道;internal/plugin、internal/service、internal/status 的监听方分别只有 3 个、2 个和 1 个。这一节值得单独看:表内 56 个事件是公开扩展点,表外的 internal 字符串是内部实现细节,两者的边界就是插件可以放心依赖的稳定边界。

扩展作者怎么用这张表

对插件作者来说,这张表就是接线手册。想在每一步执行前注入动态上下文,挂 agent/pre-step,现有的 time-context、tmux-context、plan-mode 就是参考实现;想在工具执行前后加守卫或审计,对应 tools/pre-execute 与 tools/post-execute;想对会话事实做后续处理,监听 session/event;想观察子代理,则看 subagent/start 与 subagent/end。每个事件都给出了声明文件与行号,从矩阵跳到类型定义,再跳到派发方与监听方的源码,一条链走完,这个框架的扩展方式也就清楚了。

相关文章

分享: