第 7 章
Hook 系统
生命周期事件 — 在关键时刻插入自定义逻辑
🎯
像门口的安检系统
想象一栋大厦的大门有安检:每个人进门前要刷卡(PreToolUse),出门后要登记(PostToolUse)。这个安检系统不是大厦的核心功能,但它能在关键时刻做检查、记录、甚至拦截。Hook 系统就是 Agent 的安检系统 —— 在每个工具「进出」的时候,自动执行你设定的逻辑。
什么是 Hook?
Hook(钩子)是一种编程模式:在程序执行到特定时刻时,自动触发预设的操作。
在 OpenHarness 中,Hook 系统提供了 4 个时机:
• SESSION_START:会话开始时触发
• SESSION_END:会话结束时触发
• PRE_TOOL_USE:工具执行之前触发
• POST_TOOL_USE:工具执行之后触发
其中 PRE_TOOL_USE 和 POST_TOOL_USE 是最常用的,它们让你能在每次工具执行的前后插入自定义逻辑。
Hook 能做什么?
Hook 的常见用途包括:
📝 日志记录
记录每次工具调用的参数和结果,用于审计和调试。
🛡️ 额外安全检查
比如检查 Bash 命令是否包含危险操作,在权限系统之上增加一层防护。
🔄 自动格式化
在文件写入后自动运行代码格式化工具。
📊 统计分析
统计工具使用频率、执行时间等数据。
🚫 拦截操作
PreToolUse Hook 可以阻止工具执行,比如在工作时间外禁止部署操作。
Hook 的执行流程
openharness/hooks/executor.py
1async def execute_tool_with_hooks(tool_call, context):2 # 第 1 步:执行 PreToolUse 钩子3 pre_result = await run_hooks("pre_tool_use", {4 "tool_name": tool_call.name,5 "tool_params": tool_call.params,6 })78 # 如果钩子要求阻止,直接返回9 if pre_result.should_block:10 return ToolResult("操作被 Hook 阻止", is_error=True)1112 # 第 2 步:权限检查(在 Hook 之后)13 permission = await check_permission(tool_call)14 if not permission.allowed:15 return ToolResult("权限不足", is_error=True)1617 # 第 3 步:真正执行工具18 result = await tool.execute(tool_call.params)1920 # 第 4 步:执行 PostToolUse 钩子21 await run_hooks("post_tool_use", {22 "tool_name": tool_call.name,23 "result": result,24 })2526 return result
每次工具调用时,Hook 的执行顺序是这样的:
四种 Hook 类型
OpenHarness 支持四种不同类型的 Hook 实现:
1. Command Hook(命令钩子)
执行一个 Shell 命令。最简单直接的方式。
2. HTTP Hook
发送一个 HTTP 请求到指定 URL。适合与外部服务集成。
3. Prompt Hook
让 Agent 自己处理一段提示词。适合复杂的判断逻辑。
4. Agent Hook
启动一个完整的子 Agent 来处理。适合需要多步推理的场景。
大多数情况下,Command Hook 就足够了。
配置 Hook 的方式
settings.json
1{2 "hooks": {3 "pre_tool_use": [4 {5 "type": "command",6 "command": "echo '即将执行工具: $TOOL_NAME'",7 "match_tools": ["Bash"]8 }9 ],10 "post_tool_use": [11 {12 "type": "command",13 "command": "echo '工具执行完成: $TOOL_NAME'"14 }15 ]16 }17}
Hook 在 settings.json 中配置:
📌 关键要点
Hook 让 Harness 可观测、可扩展
Hook 系统的核心价值是:在不修改引擎代码的情况下,在关键时刻插入自定义逻辑。这使得 OpenHarness 不仅是一个工具,更是一个可观测、可扩展的平台。
🧠 检验理解
PreToolUse Hook 最主要的特殊能力是什么?