Quick Start
How It Works
Execution order for a model call:- All
before_modelhooks run in registration order wrap_model_callmiddleware chain wraps the actual LLM call- The real LLM call executes
- All
after_modelhooks run in reverse registration order
before_tool, wrap_tool_call, and after_tool.
| Decorator | Receives | Returns | Use for |
|---|---|---|---|
@before_model | ModelRequest | ModelRequest | Inject context, modify messages |
@after_model | ModelResponse | ModelResponse | Log, transform, or redact output |
@wrap_model_call | (ModelRequest, call_next) | ModelResponse | Retry, caching, circuit-breaking |
@before_tool | ToolRequest | ToolRequest | Validate arguments, add auth |
@after_tool | ToolResponse | ToolResponse | Sanitize results, log usage |
@wrap_tool_call | (ToolRequest, call_next) | ToolResponse | Retry flaky tools, mock in tests |
Configuration Options
Pass middleware as a flat list toAgent(hooks=[...]). Mix decorator types freely.
Middleware API Reference
TypeScript middleware configuration
Hooks Rust Reference
Rust hooks configuration
Common Patterns
Inject a system prompt on every call:Best Practices
Always return the request/response object
Always return the request/response object
Every
before_* and after_* hook must return the (possibly modified) object. Returning None breaks the chain and raises a runtime error.Use wrap_* for retry and circuit-breaking
Use wrap_* for retry and circuit-breaking
wrap_model_call and wrap_tool_call give you full control over whether call_next is called — perfect for retries, timeouts, and feature flags. before_*/after_* hooks cannot short-circuit the call.Keep hooks stateless or use thread-local state
Keep hooks stateless or use thread-local state
Agents can run concurrently. Avoid mutable global state in hooks. If you need per-request state, use
request.context.metadata or Python’s contextvars.Zero overhead when hooks are empty
Zero overhead when hooks are empty
The middleware manager checks for registered hooks before executing any code. When
hooks=[] (the default), the fast path skips all hook processing entirely.Related
Hooks
Event-based hooks for agent lifecycle events
Callbacks
UI-focused callbacks for display and streaming events

