Quick Start
Simple Usage
Register a hook with Hook return values:
add_hook and any agent picks it up automatically:Noneor no return → AllowFalse→ Deny"reason"→ Deny with custom message
Which Hook Point Should I Use?
Pick the lifecycle event that matches what you want to observe or block.How It Works
Available Hook Events
| Event | When It Fires |
|---|---|
before_tool | Before any tool executes |
after_tool | After a tool returns a result |
before_tool_definitions | After tool list assembled, before sent to LLM — shape what the model sees |
before_agent | Before the agent starts a turn |
after_agent | After the agent completes a turn |
before_llm | Before an LLM API call |
after_llm | After an LLM API response |
on_error | When any error occurs |
on_retry | Before a retry attempt — fires on both sync and async LLM paths (post-PR #2386) |
session_start | When a session begins |
session_end | When a session ends |
on_retry is emitted once per retryable error, just before the back-off sleep. It runs whether the LLM call is agent.chat(...) (sync) or await agent.achat(...) (async). Sync-registered callbacks on the async path are run in a thread executor — they cannot block the event loop.
Two lookalike fields. Function-style hooks return
HookResult and set modified_input to rewrite the payload. Shell-command hooks parse into HookOutput and use modified_data for the same purpose. When you write a hook in Python, always use HookResult(decision="allow", modified_input={...}) — the internal Agent code reads .modified_input on hook results.Configuration Options
HooksConfig SDK Reference
Full parameter reference for HooksConfig
| Option | Type | Default | Description |
|---|---|---|---|
on_step | Callable | None | None | Called on each agent step |
on_tool_call | Callable | None | None | Called before each tool execution |
middleware | List | [] | Middleware list applied to all events |
Common Patterns
Security Filtering
Audit Logging
Tool Matching with HookRegistry
Best Practices
Keep hooks lightweight
Keep hooks lightweight
Hooks run synchronously before/after each operation. Avoid network calls or heavy computation inside hook functions — use async queues for heavy processing.
Return None to allow, string to deny
Return None to allow, string to deny
The simplest hook contract: return nothing (or
None) to allow, return a string with a reason to block. This keeps hooks readable.Use add_hook for global rules, HooksConfig for per-agent rules
Use add_hook for global rules, HooksConfig for per-agent rules
add_hook registers hooks globally — all agents in the process obey them. Use HooksConfig when you need different rules per agent.Set _strict_hooks=True in tests
Set _strict_hooks=True in tests
By default, hook exceptions are logged as warnings and execution continues. Set
agent._strict_hooks = True in tests so hook failures surface immediately as errors.Related
Guardrails
Validate agent output quality with automatic retry
Callbacks
Observe agent events for UI and logging purposes

