Hooks 是在 Agent 执行关键节点运行的回调函数,用于拦截、审计、修改或阻止工具调用。可以实现:阻止危险操作、记录审计日志、变换工具输入、要求人工审批、追踪会话生命周期。

核心机制

执行流程:事件触发 → SDK 收集匹配的 Hooks → matcher 过滤 → 回调函数执行 → 返回决策对象。

主要 Hook 事件:

事件触发时机常见用途
PreToolUse工具执行前(可阻止/修改)阻止危险命令
PostToolUse工具执行后审计日志
UserPromptSubmitprompt 提交时注入额外上下文
StopAgent 执行结束保存会话状态
SubagentStart/Stop子 Agent 启动/完成追踪并行任务
PreCompact上下文压缩前归档完整对话
NotificationAgent 状态消息转发到 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}

与其他概念的关联

实践要点

  • Python SDK 不支持 SessionStart/SessionEnd 回调 Hook(只能通过 settings.json 文件配置)
  • 子 Agent 不自动继承父 Agent 的权限,会独立触发权限提示,用 PreToolUse Hook 预批准可避免
  • UserPromptSubmit Hook 中派生子 Agent 可能导致递归循环,需检查 agent_id 防止
  • Hook 超时默认 60 秒,可在 HookMatcher 中设置 timeout 调整
  • systemMessage 字段显示给用户而非模型,需设置 includeHookEvents 才能在消息流中看到