Agent 事件
Agent 事件不仅回答「发生了什么」,也能在副作用发生前决定「这件事是否应该发生」。每个 Agent 的 EventBus 都支持观察和同步干预。
| 类型 | 用途 | 获取方式 | 能干预吗 |
|---|---|---|---|
AgentEvent |
协调与干预当前执行 | agent.events.on(...) |
能:修改字段或设置 decision |
StreamEvent |
向调用方交付输出 | 迭代 agent.run() 的流 |
能:关闭流即结束 Run |
TapeEntry |
保存历史记录 | 查询 Tape | 不能:正常记录只追加 |
三者不会自动互相转换:流式输出不会自行落盘,Tape 条目不会回灌进正在执行的 Step。只有被 TapeContext 选中的条目,才会成为后续模型输入。
emit() 按注册顺序逐个调用匹配的处理器,并等待 async 处理器完成后再继续。需要记住四条规则:
- 注册到基类的处理器也会收到子类事件。
- 返回值会被忽略;干预执行要修改事件字段或设置
decision。 - 异常会传播给发布方,可能导致整个 Run 失败。
- 每次调用处理器前都会检查
event.stopped,为True时停止本次派发。
决策先于副作用
Section titled “决策先于副作用”调用前事件暴露可替换的请求和 decision。一次工具调用有四种结果:
| 操作 | 原工具执行吗 | 交给模型的结果 |
|---|---|---|
不设置 decision |
是 | 实际结果 |
替换 event.call |
是,用新调用 | 实际结果 |
deny(message) |
否 | 工具错误 |
replace(result) |
否 | 指定结果 |
被拒绝或替换的调用仍会发出 ToolCallFinished,完成后的观察逻辑不会漏记。模型调用也遵循同样的调用前干预模型,例如 LLMCallDecision.finish(text) 可以跳过供应商直接产生文本。
与 App Hooks 的分工
Section titled “与 App Hooks 的分工”Agent 事件介入核心循环中的模型、工具、Step 与 Run;App hooks 面向 Turn 阶段、工具供给、存储和渠道等应用生命周期,并承担插件分发。应用拦截 hooks 可以通过适配器接入同一组 Agent 事件,但两者的参数返回方式与异常策略不同,详见 Hooks 参考。具体写法分别见 SDK:事件与应用插件:拦截调用。