Hooks 是在 Agent 执行关键节点运行的回调函数,用于拦截、审计、修改或阻止工具调用。可以实现:阻止危险操作、记录审计日志、变换工具输入、要求人工审批、追踪会话生命周期。
核心机制
执行流程:事件触发 → SDK 收集匹配的 Hooks → matcher 过滤 → 回调函数执行 → 返回决策对象。
主要 Hook 事件:
| 事件 | 触发时机 | 常见用途 |
|---|---|---|
PreToolUse | 工具执行前(可阻止/修改) | 阻止危险命令 |
PostToolUse | 工具执行后 | 审计日志 |
UserPromptSubmit | prompt 提交时 | 注入额外上下文 |
Stop | Agent 执行结束 | 保存会话状态 |
SubagentStart/Stop | 子 Agent 启动/完成 | 追踪并行任务 |
PreCompact | 上下文压缩前 | 归档完整对话 |
Notification | Agent 状态消息 | 转发到 Slack |
回调返回值:
{}- 允许操作继续hookSpecificOutput.permissionDecision: "deny"- 阻止操作hookSpecificOutput.permissionDecision: "allow"+updatedInput- 修改输入后允许hookSpecificOutput.additionalContext- 向 Claude 注入额外上下文(PostToolUse)
优先级:deny > defer > ask > allow,任一 Hook 返回 deny 则操作被阻止。
关键细节
from claude_agent_sdk import ClaudeAgentOptions, HookMatcher
async def protect_env_files(input_data, tool_use_id, context):
file_path = input_data["tool_input"].get("file_path", "")
if file_path.endswith(".env"):
return {
"hookSpecificOutput": {
"hookEventName": input_data["hook_event_name"],
"permissionDecision": "deny",
"permissionDecisionReason": "Cannot modify .env files",
}
}
return {}
options = ClaudeAgentOptions(
hooks={
"PreToolUse": [
HookMatcher(matcher="Write|Edit", hooks=[protect_env_files])
]
}
)Matcher 规则:
- matcher 是正则表达式,匹配工具名(不是文件路径)
- MCP 工具格式:
mcp__<server>__<action>,可用^mcp__匹配所有 MCP 工具 - 不设 matcher 则匹配所有工具
异步 Hook(不阻塞 Agent):
return {"async_": True, "asyncTimeout": 30000}与其他概念的关联
- permissions - 权限控制体系(Hooks 是权限评估的第一步)
- agent-loop - Hooks 在循环中的位置
- subagents - SubagentStart/Stop Hooks
- claude-code-features - 文件系统 Hooks(settings.json)
实践要点
- Python SDK 不支持
SessionStart/SessionEnd回调 Hook(只能通过 settings.json 文件配置) - 子 Agent 不自动继承父 Agent 的权限,会独立触发权限提示,用 PreToolUse Hook 预批准可避免
UserPromptSubmitHook 中派生子 Agent 可能导致递归循环,需检查 agent_id 防止- Hook 超时默认 60 秒,可在 HookMatcher 中设置
timeout调整 systemMessage字段显示给用户而非模型,需设置includeHookEvents才能在消息流中看到