Claude Code Agent Loop 研究系列(02)—— Hooks:loop 上的可编程干预点

💡 原文中文,约6600字,阅读约需16分钟。
📝

内容提要

Claude Code的Hooks系统提供26种事件,覆盖会话、工具、压缩等生命周期节点,支持command、prompt、agent、http四种执行方式。Hooks可阻止动作或修改结果,默认同步执行,超时10分钟,失败不影响主流程。权限批准是Hooks的特化,通过PermissionRequest事件实现可编程决策。

🔎

延伸解读

Hooks 的四种执行方式与适用场景

Hooks 支持 command、prompt、agent、http 四种执行方式,覆盖从简单脚本到跨机器策略的不同复杂度。command 适合快速脚本,prompt 让 LLM 做复杂判断,agent 启动完整子代理,http 则用于集中式策略服务。选择时需权衡延迟、成本和外部依赖,例如 http 方式可能引入网络延迟,而 prompt 方式会消耗额外 token。

Block 与 Modify:Hooks 如何影响 Loop

Hooks 不仅能观察,还能通过返回 decision 或 additional_context 影响 loop 行为。PreToolUse 的 block 可阻止工具执行,PostToolUse 的 block 可强制退出,Stop 的 block 可让 loop 继续。additional_context 会以附件形式追加到 tool_result,供 LLM 后续参考。这种设计让用户能在关键节点注入自定义逻辑,但需注意不同事件的 block 语义不同,使用前应查阅文档。

异步与失败处理:Hooks 的可靠性设计

Hooks 默认同步执行,超时 10 分钟,但可配置为 async 实现 fire-and-forget,甚至用 asyncRewake 在后台任务完成后唤醒 LLM。失败时默认 non_blocking,不影响主流程,但明确的 block 决策会生效。这种设计体现了 hooks 作为可选强化而非关键路径的哲学,适合在不影响稳定性的前提下增强功能。

Q&A

Claude Code 的 Hooks 系统支持哪些事件类型?

Claude Code 的 Hooks 系统支持 26 种事件,覆盖会话生命周期(如 SessionStart、SessionEnd)、用户输入(如 UserPromptSubmit)、工具生命周期(如 PreToolUse、PostToolUse)、压缩(如 PreCompact、PostCompact)、子代理(如 SubagentStart、SubagentStop)等。

Claude Code 的 Hooks 有哪几种执行方式?

Hooks 有四种执行方式:command(命令行)、prompt(提示词)、agent(子代理)和 http(HTTP webhook)。command 执行 shell 命令,prompt 调用 LLM 判断,agent 启动完整子代理,http 将事件发送到外部服务。

Hooks 能否阻止工具执行或修改工具结果?

可以。Hooks 可以返回 block 决策来阻止动作,例如 PreToolUse 中 block 会阻止工具执行;也可以返回 additional_context 来修改工具结果,该内容会以附件形式插入到 tool_result 中,供 LLM 后续读取。

Hooks 默认是同步还是异步?超时时间是多少?

Hooks 默认是同步执行,会阻塞 loop 直到 hook 返回。默认超时时间为 10 分钟(TOOL_HOOK_EXECUTION_TIMEOUT_MS)。也可以配置为异步(async: true),此时 hook 启动后立即返回,loop 不等待。

如果 Hook 执行失败,会影响主流程吗?

不会。Hook 出错(如非零退出码、JSON 格式错误)时,loop 会走 non_blocking_error 分支,记录日志并继续执行,用户通常看不到错误。但明确的 block 决策(如 decision: block 或 continue: false)会生效,影响主流程。

权限批准与 Hooks 有什么关系?

权限批准是 Hooks 的一种特化。Hooks 系统通过 PermissionRequest 事件实现可编程的权限决策,用户可以在 settings.json 中注册 PermissionRequest hook,在权限批准时自动执行脚本或逻辑,与用户点击和 classifier 一起参与决策竞争。

Hooks 的 asyncRewake 机制有什么作用?

asyncRewake 允许异步 hook 在后台完成后,通过 exit code 2 结束,从而重新唤醒 LLM,让模型继续处理。例如,一个耗时 5 分钟的代码分析可以异步运行,完成后自动回到对话继续,实现事件驱动的 loop 唤醒。

🏷️

标签

➡️

继续阅读