权限、日志、指标和输入增强如果全写进 Agent Loop,循环很快会充满条件分支。Hooks 把横切逻辑挂到稳定的生命周期节点,让主循环继续只负责模型调用、工具分发和消息回传。
四个生命周期节点
| Hook | 触发位置 | 典型用途 |
|---|---|---|
UserPromptSubmit | 用户输入进入循环 | 记录;可作为输入扩展点 |
PreToolUse | handler 执行前 | 权限、参数策略、阻断 |
PostToolUse | handler 返回后 | 日志、指标、大输出提醒 |
Stop | 本轮没有工具调用 | 审计、完成判断、继续执行 |
s03 的权限判断可注册为 PreToolUse,让当前和未来工具走同一个拦截点。
这里的四类事件只是课程中的最小抽象,不是 Claude Code 产品的完整 Hooks API。当前示例的 UserPromptSubmit callback 只打印记录,CLI 也没有使用返回值改写用户输入;“补充上下文”是可扩展方向,不是这份代码已经实现的行为。
返回值必须有明确语义
课程按注册顺序调用 callback,第一个非空结果会短路:
PreToolUse的非空结果阻止工具并作为结果返回;Stop的非空结果注入对话并继续;UserPromptSubmit和PostToolUse当前主要用于观察,其返回值不控制流程。
教学约定足够简洁,生产系统则应为每类事件定义稳定类型,避免一个字符串同时承担修改、拒绝和继续提示。
顺序本身就是行为
短路意味着注册顺序影响结果。可靠系统通常会区分:全部执行的观察者、按序更新的变换器、任一拒绝即可阻断的守卫,以及按优先级决定结束或继续的 Stop 决策器。
这些顺序应成为显式契约和测试,而不是依赖导入顺序。
异常不能悄悄改变安全策略
权限 Hook 抛异常后若默认继续,会形成 fail-open。安全守卫应默认拒绝并记录错误;日志类 Hook 可以隔离失败,避免遥测故障拖垮 Agent。
Hook 还应有超时和重入边界。阻塞 callback 会阻塞模型循环;Hook 内再次触发同类事件可能递归。
Hooks 提供扩展点,但与宿主同进程的 callback 通常拥有同等代码权限,不能隔离不可信插件,也不能替代权限系统。
建议覆盖的测试
- 四类 Hook 在正确生命周期触发;
PreToolUse阻止后 handler 未执行;Stop注入消息后循环继续;- 注册顺序和短路行为稳定;
- 安全 Hook 异常不会放行;
- 观察 Hook 失败不破坏工具协议。
小结
Hooks 让权限、审计、提示增强和停止判断接入同一循环。可靠 Hook 系统需要明确事件类型、执行顺序、短路语义、异常策略与可信边界。