Lifecycle Hooks
Hooks let you observe and gate agent activity as it happens. You register a named
callback against a lifecycle event, the runtime invokes it at that point, and the
callback returns a decision such as { action: "continue" }. Use hooks for
auditing, redaction, logging, or enforcing policy without changing the agent's
prompt.
The lifecycle is symmetric: registerHook adds a callback by name, hookCount
tells you how many are active, and unregisterHook removes one by its name.
Notes:
- A hook callback returns a decision. Return
{ action: "continue" }(Node) /{"action": "continue"}(Python) /&code.HookResponse{Action: "continue"}(Go) to let the agent proceed. - Permanent denials return
blockwith a reason. Temporary denials returnretrywith a reason anddelayMs(Node),delay_ms(Python), orDelayMS(Go). In asendorstreamturn, a denied tool call emits apermission_deniedevent and the model receivesHook denied <tool>: <reason>instead of the tool output. For host-direct calls (session.tool(...)and the typed helpers), the denied result also carrieserror_kind.type = "hook_denied"withretryableandretry_after_ms, so hosts do not need to parse output text. - The path matcher reads the tool's
file_pathargument, falling back topath. - The matcher (
{ pathPattern: '**/.env*' }in Node,{'path_pattern': ...}in Python,HookMatcher{PathPattern: ...}in Go) scopes the hook to events whose path matches the pattern, and{ priority: 100 }orders hooks on the same event (lower values run first). - Callbacks receive the event as their only argument.
- A Node callback that throws, returns an invalid value, or runs past its
timeout (
timeoutMsin the config, default 30,000 ms) counts as a failed hook. On gating events (pre_tool_use,permission_request,pre_compact,pre_prompt,pre_planning,pre_run_control) the action is blocked withRequired hook '<name>' failed: ...; on other events the agent continues. hookCount/hook_count/HookCountreflects the number of currently registered hooks, which is handy in tests to assert that registration and cleanup happened.unregisterHook/unregister_hook/UnregisterHooktakes the name you registered with. Always tear down hooks you no longer need so they do not leak across runs.- Validate the event path you depend on before using a hook as a production gate.