Skip to main content
Hook 是 QitOS 中首要的运行时扩展点。它们让你在不修改智能体本身的情况下,观察并对 Engine 内部的每个阶段转换做出反应。本教程覆盖完整的 Hook 生命周期、Hook 接收的上下文对象,以及如何编写步骤级和工具级的 Hook。

Hook 与 Critic 的区别

QitOS 有两种运行在不同层面的扩展机制: 当你需要记录日志、追踪、采集指标或触发外部通知时,使用 Hook。当你需要约束或覆盖智能体行为时,使用 Critic。

Step 1: EngineHook 基类

每个 Hook 都继承自 EngineHook。基类为每个生命周期回调定义了空操作方法,因此你只需覆盖需要的方法。
在一次运行中,完整的回调集合按执行顺序排列如下: 在步骤循环之外触发的额外生命周期回调: 所有空操作方法返回 None。只需覆盖你关心的回调。

Step 2: HookContext 与 ToolHookContext

每个步骤级回调都接收一个 HookContext 数据类,它携带了 Hook 可能需要的所有信息:
工具级回调接收 ToolHookContext,它在 HookContext 基础上扩展了工具特有的字段:
phase 字段来自 RuntimePhase 枚举:

Step 3: 编写自定义日志 Hook

一个常见用例是记录每个阶段转换,以便后续分析。下面是一个 LifecycleRecorderHook,它为每个回调记录时间戳和步骤 ID:
因为 Hook 不能修改流程,所以将 LifecycleRecorderHook 添加到任何运行都是安全的,不会产生副作用。

Step 4: 工具级 Hook

工具级 Hook 围绕单次工具调用触发,让你可以精细地观察智能体调用了哪些工具以及它们的返回值。
三个工具级回调: 使用 on_permission_denied 来监控安全边界,而无需修改权限系统本身。

Step 5: 在 Engine 上注册 Hook

在调用 run() 之前,将 Hook 注册到 Engine 实例上:
你可以注册多个 Hook。它们在每个回调中按注册顺序触发。因为 Hook 仅用于观察,顺序不影响控制流程 — 但它会影响日志输出的顺序,这在调试时很重要。 查看当前已注册的 Hook:
移除某个 Hook:

完整生命周期图

当发生错误恢复时,on_recover 代替该步骤的其余回调触发,Engine 可能根据配置决定重试或中止。

相关指南:Critic

了解 Critic 与 Hook 的区别,以及如何使用 Critic 进行控制流和决策门控。

下一篇教程:多智能体系统

构建包含协调者和工作者智能体的系统,实现任务的并行调度。