Python SDK 参考:Hook 类型
Agent SDK Python 的 HookEvent、HookCallback、HookContext、HookMatcher、各事件的 HookInput 类型(PreToolUse、PostToolUse、Stop、PermissionRequest 等)、HookJSONOutput 同步与异步输出,以及完整使用示例。
本页是 Python Agent SDK 参考的第四部分:ClaudeAgentOptions.hooks 用到的类型。用 hooks 的指南和常见模式见「Agent SDK:Hooks」。
HookEvent
支持的 hook 事件类型。
HookEvent = Literal[
"PreToolUse", # 工具执行之前调用
"PostToolUse", # 工具执行之后调用
"PostToolUseFailure", # 工具执行失败时调用
"UserPromptSubmit", # 用户提交提示时调用
"Stop", # 停止执行时调用
"SubagentStop", # 子智能体停止时调用
"PreCompact", # 消息压缩之前调用
"Notification", # 通知事件时调用
"SubagentStart", # 子智能体启动时调用
"PermissionRequest", # 需要权限决定时调用
]TypeScript SDK 支持 Python 里尚不可用的额外 hook 事件(每个 SDK 的支持情况见 hook 可用性表)。
HookCallback、HookContext、HookMatcher
hook 回调函数的类型定义:
HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]参数:input 是按 hook_event_name 区分的强类型 hook 输入(见 HookInput);tool_use_id 是可选的工具使用标识(用于与工具相关的 hooks);context 是带附加信息的 hook 上下文。返回 HookJSONOutput。
class HookContext(TypedDict):
signal: Any | None # 未来:中止信号支持把 hooks 匹配到特定事件或工具的配置:
@dataclass
class HookMatcher:
matcher: str | None = (
None # 要匹配的工具名或模式(例如 "Bash"、"Write|Edit")
)
hooks: list[HookCallback] = field(
default_factory=list
) # 要执行的回调列表
timeout: float | None = (
None # 超时秒数。省略时适用每事件的默认值:
# 多数事件 600,UserPromptSubmit 30
)HookInput 与 BaseHookInput
所有 hook 输入类型的联合类型,实际类型取决于 hook_event_name 字段:
HookInput = (
PreToolUseHookInput
| PostToolUseHookInput
| PostToolUseFailureHookInput
| UserPromptSubmitHookInput
| StopHookInput
| SubagentStopHookInput
| PreCompactHookInput
| NotificationHookInput
| SubagentStartHookInput
| PermissionRequestHookInput
)所有 hook 输入类型里都有的基础字段:
class BaseHookInput(TypedDict):
session_id: str
transcript_path: str
cwd: str
permission_mode: NotRequired[str]| 字段 | 类型 | 说明 |
|---|---|---|
session_id | str | 当前会话标识 |
transcript_path | str | 会话记录文件的路径 |
cwd | str | 当前工作目录 |
permission_mode | str(可选) | 当前权限模式 |
各事件的输入类型
PreToolUseHookInput:PreToolUse 事件的输入数据。
class PreToolUseHookInput(BaseHookInput):
hook_event_name: Literal["PreToolUse"]
tool_name: str
tool_input: dict[str, Any]
tool_use_id: str
agent_id: NotRequired[str]
agent_type: NotRequired[str]hook_event_name 总是 "PreToolUse";tool_name 是即将执行的工具名;tool_input 是工具的输入参数;tool_use_id 是这次工具使用的唯一标识;agent_id 和 agent_type(可选)是 hook 在子智能体内触发时存在的子智能体标识和类型。
PostToolUseHookInput:PostToolUse 事件的输入数据。
class PostToolUseHookInput(BaseHookInput):
hook_event_name: Literal["PostToolUse"]
tool_name: str
tool_input: dict[str, Any]
tool_response: Any
tool_use_id: str
agent_id: NotRequired[str]
agent_type: NotRequired[str]tool_name 是已执行的工具名,tool_input 是使用的输入参数,tool_response 是工具执行的响应,其余字段同上。
PostToolUseFailureHookInput:PostToolUseFailure 事件的输入数据,在工具执行失败时调用。
class PostToolUseFailureHookInput(BaseHookInput):
hook_event_name: Literal["PostToolUseFailure"]
tool_name: str
tool_input: dict[str, Any]
tool_use_id: str
error: str
is_interrupt: NotRequired[bool]
agent_id: NotRequired[str]
agent_type: NotRequired[str]error 是失败执行的错误消息;is_interrupt(可选)在失败以中止而不是工具报告的错误的形式到达 Claude Code 时为 True(用 interrupt() 取消运行中的工具不会触发这个 hook,工具结果里改为携带中断消息)。
UserPromptSubmitHookInput、StopHookInput、SubagentStopHookInput
class UserPromptSubmitHookInput(BaseHookInput):
hook_event_name: Literal["UserPromptSubmit"]
prompt: str
class StopHookInput(BaseHookInput):
hook_event_name: Literal["Stop"]
stop_hook_active: bool
class SubagentStopHookInput(BaseHookInput):
hook_event_name: Literal["SubagentStop"]
stop_hook_active: bool
agent_id: str
agent_transcript_path: str
agent_type: strprompt 是用户提交的提示;stop_hook_active 表示停止 hook 是否处于活动状态;agent_id 是子智能体的唯一标识,agent_transcript_path 是子智能体记录文件的路径,agent_type 是子智能体的类型。
PreCompactHookInput、NotificationHookInput、SubagentStartHookInput、PermissionRequestHookInput
class PreCompactHookInput(BaseHookInput):
hook_event_name: Literal["PreCompact"]
trigger: Literal["manual", "auto"]
custom_instructions: str | None
class NotificationHookInput(BaseHookInput):
hook_event_name: Literal["Notification"]
message: str
title: NotRequired[str]
notification_type: str
class SubagentStartHookInput(BaseHookInput):
hook_event_name: Literal["SubagentStart"]
agent_id: str
agent_type: str
class PermissionRequestHookInput(BaseHookInput):
hook_event_name: Literal["PermissionRequest"]
tool_name: str
tool_input: dict[str, Any]
permission_suggestions: NotRequired[list[Any]]
agent_id: NotRequired[str]
agent_type: NotRequired[str]trigger 是什么触发了压缩,custom_instructions 是压缩的自定义说明;message、title(可选)和 notification_type 是通知的内容、标题和类型;PermissionRequestHookInput 让 hooks 能以编程方式处理权限决定,permission_suggestions(可选)是来自 CLI 的建议权限更新。
HookJSONOutput
hook 回调返回值的联合类型。
HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutputSyncHookJSONOutput
带控制和决定字段的同步 hook 输出。
class SyncHookJSONOutput(TypedDict):
# 控制字段
continue_: NotRequired[bool] # 是否继续(默认:True)
suppressOutput: NotRequired[bool] # 从记录里隐藏 stdout
stopReason: NotRequired[str] # continue 为 False 时的消息
# 决定字段
decision: NotRequired[Literal["block"]]
systemMessage: NotRequired[str] # 给用户的警告消息
reason: NotRequired[str] # 给 Claude 的反馈
# hook 专属输出
hookSpecificOutput: NotRequired[HookSpecificOutput]在 Python 代码里用 continue_(带下划线),发给 CLI 时它会被自动转换成 continue。
HookSpecificOutput
事件专属 TypedDict 输出类型的判别联合,hookEventName 字段决定哪些字段有效(每个 hook 事件可用字段的完整细节见「用 hooks 控制执行」)。
class PreToolUseHookSpecificOutput(TypedDict):
hookEventName: Literal["PreToolUse"]
permissionDecision: NotRequired[Literal["allow", "deny", "ask", "defer"]]
permissionDecisionReason: NotRequired[str]
updatedInput: NotRequired[dict[str, Any]]
additionalContext: NotRequired[str]
class PostToolUseHookSpecificOutput(TypedDict):
hookEventName: Literal["PostToolUse"]
additionalContext: NotRequired[str]
updatedToolOutput: NotRequired[Any]
updatedMCPToolOutput: NotRequired[Any] # 已弃用:改用对所有工具都有效的 updatedToolOutput
class PostToolUseFailureHookSpecificOutput(TypedDict):
hookEventName: Literal["PostToolUseFailure"]
additionalContext: NotRequired[str]
class UserPromptSubmitHookSpecificOutput(TypedDict):
hookEventName: Literal["UserPromptSubmit"]
additionalContext: NotRequired[str]
class NotificationHookSpecificOutput(TypedDict):
hookEventName: Literal["Notification"]
additionalContext: NotRequired[str]
class SubagentStartHookSpecificOutput(TypedDict):
hookEventName: Literal["SubagentStart"]
additionalContext: NotRequired[str]
class PermissionRequestHookSpecificOutput(TypedDict):
hookEventName: Literal["PermissionRequest"]
decision: dict[str, Any]
HookSpecificOutput = (
PreToolUseHookSpecificOutput
| PostToolUseHookSpecificOutput
| PostToolUseFailureHookSpecificOutput
| UserPromptSubmitHookSpecificOutput
| NotificationHookSpecificOutput
| SubagentStartHookSpecificOutput
| PermissionRequestHookSpecificOutput
)AsyncHookJSONOutput
推迟 hook 执行的异步 hook 输出。
class AsyncHookJSONOutput(TypedDict):
async_: Literal[True] # 设为 True 以推迟执行
asyncTimeout: NotRequired[int] # 超时毫秒数在 Python 代码里用 async_(带下划线),发给 CLI 时它会被自动转换成 async。
hook 使用示例
这个例子注册两个 hooks:一个阻止 rm -rf / 这类危险的 Bash 命令,另一个记录所有工具使用以供审计。安全 hook 只在 Bash 命令上运行(通过 matcher),日志 hook 在所有工具上运行。
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, HookContext
from typing import Any
async def validate_bash_command(
input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
"""验证并可能阻止危险的 bash 命令。"""
if input_data["tool_name"] == "Bash":
command = input_data["tool_input"].get("command", "")
if "rm -rf /" in command:
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Dangerous command blocked",
}
}
return {}
async def log_tool_use(
input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
"""记录所有工具使用以供审计。"""
print(f"Tool used: {input_data.get('tool_name')}")
return {}
options = ClaudeAgentOptions(
hooks={
"PreToolUse": [
HookMatcher(
matcher="Bash", hooks=[validate_bash_command], timeout=120
), # 验证用 2 分钟
HookMatcher(
hooks=[log_tool_use]
), # 适用于所有工具(用每事件的默认超时)
],
"PostToolUse": [HookMatcher(hooks=[log_tool_use])],
}
)
async def main():
async for message in query(prompt="Analyze this codebase", options=options):
print(message)
asyncio.run(main())