Hooks

Hooks register lifecycle callbacks inside a session. The registration lifecycle is registerHook(), hookCount(), and unregisterHook().

Events

Supported event types are:

Text
pre_tool_use
post_tool_use
generate_start
generate_end
session_start
session_end
skill_load
skill_unload
pre_prompt
post_response
on_error

Registration Example

TypeScript
session.registerHook(
'release-publish-observer',
'pre_tool_use',
{ tool: 'bash', commandPattern: 'npm publish|twine upload|cargo publish' },
{ priority: 50, timeoutMs: 1000 },
() => ({ action: 'continue' }),
);

A handler may return { action: 'continue' }, { action: 'skip' }, { action: 'block', reason }, { action: 'retry', reason, delayMs }, or null/undefined to continue. Validate the specific event path you depend on before using a hook as a production gate.

Denial Feedback

Use block when retrying the same invocation cannot succeed without changing the request, arguments, or policy context. Use retry for a temporary condition and include both a reason and suggested delay:

TypeScript
() => ({
action: 'retry',
reason: 'The policy backend is temporarily unavailable.',
delayMs: 1000,
});

Python callbacks use delay_ms; Go callbacks return &code.HookResponse{Action: "retry", Reason: "...", DelayMS: 1000}. The current invocation is denied rather than automatically scheduled. The model receives the explanation and explicit retry guidance, while direct SDK callers receive a structured tool error:

JSON
{
"type": "hook_denied",
"reason": "The policy backend is temporarily unavailable.",
"retryable": true,
"retry_after_ms": 1000
}

A block response uses the same error type with retryable: false and retry_after_ms: null. Rust callers that need the retry explanation can use HookEngine::fire_outcome(); the existing fire() API retains its legacy HookResult projection.

Propagation

Delegation and automatic subagent fan-out use the task tool. When a product depends on hook behavior across delegated runs, cover that product path with an integration test.

Management

TypeScript
console.log(session.hookCount());
session.unregisterHook('release-publish-observer');