1. 为什么要区分 durable event 与 live event
Session event 是可回放事实;agent/* 是运行时协调。前者必须能落盘并在未来重建,后者可以携带当前 Agent、AbortSignal 等进程内对象。
2. 一次工具轮次的事件表
| 顺序 | 事件/阶段 | 性质 | 用途 |
|---|---|---|---|
| 1 | agent/status running | live | 驱动器状态 |
| 2 | turn/start | durable | 打开轮次 |
| 3 | agent/inbox/claimed | live | 领取输入 |
| 4 | agent/pre-step | waterfall | 改写/拒绝本次输入 |
| 5 | step/start | durable | 打开模型步骤 |
| 6 | user/message | durable surface | 进入模型历史 |
| 7 | system-prompt/assemble | waterfall | 组装 prompt/tools |
| 8 | agent/request | waterfall | 最终模型请求参数 |
| 9 | llm/stream | waterfall | provider stream |
| 10 | assistant/chunk* | durable | 回放/UI fidelity |
| 11 | assistant/message | durable surface | 最终 assistant 锚点 |
| 12 | tool/call | durable surface | 调用意图 |
| 13 | tools/pre-execute | waterfall | 审批/策略 |
| 14 | tools/execute | waterfall | 权威执行 |
| 15 | tools/post-execute | waterfall | 结果规范化 |
| 16 | tool/result | durable surface | 下一 step 可见 |
| 17 | step/end | durable | 关闭步骤 |
| 18 | agent/turn-stopping | serial | 终止检查点 |
| 19 | turn/end | durable | 关闭轮次 |
| 20 | session/flush | awaited | 持久性屏障 |
3. Waterfall 的心智模型
listenerA(value, next) {
value.tags.push('A')
return next(value) // 协作:继续下游
}
listenerB(value, next) {
if (!allowed(value)) return { kind: 'reject' } // 短路
return next(value)
}
listenerC(value, next) {
return next(rewrite(value)) // 替换下游输入
}如果监听器只是观察,却忘了调用 next(),它可能无意中成为权威短路者。因此 DSH 对 waterfall 的教学和组合测试很重视。
4. 取消信号
一整个 turn 应共享同一个显式 AbortSignal,并穿过 pre-step、prompt assembly、model request、stream、tool execute、turn-stopping;下一 turn 使用新 signal。取消是协作式的:不响应 signal 的插件必须自己 settle 后,teardown 才能真正静止。
5. 事件设计判断题
- 需要恢复后仍知道?→ Session event。
- 只是当前进程中的“谁在运行”?→ agent/* live event。
- 多个插件可改写/短路?→ waterfall。
- 所有观察者都要完成但无顺序?→ parallel。
- 终止检查需要顺序?→ serial。
- 只做通知且不应影响结果?→ emit。