Hooks
Middleware provides two styles of hooks to intercept agent execution:Node-style hooks
Run sequentially at specific execution points.
Wrap-style hooks
Run around each model or tool call.
Node-style hooks
Run sequentially at specific execution points. Use for logging, validation, and state updates. Available hooks:before_agent- Before agent starts (once per invocation)before_model- Before each model callafter_model- After each model responseafter_agent- After agent completes (once per invocation)
- Decorator
- Class
Wrap-style hooks
Intercept execution and control when the handler is called. Use for retries, caching, and transformation. You decide if the handler is called zero times (short-circuit), once (normal flow), or multiple times (retry logic). Available hooks:wrap_model_call- Around each model callwrap_tool_call- Around each tool call
- Decorator
- Class
Create middleware
You can create middleware in two ways:Decorator-based middleware
Quick and simple for single-hook middleware. Use decorators to wrap individual functions.
Class-based middleware
More powerful for complex middleware with multiple hooks or configuration.
Decorator-based middleware
Quick and simple for single-hook middleware. Use decorators to wrap individual functions. Available decorators: Node-style:@before_agent- Runs before agent starts (once per invocation)@before_model- Runs before each model call@after_model- Runs after each model response@after_agent- Runs after agent completes (once per invocation)
@wrap_model_call- Wraps each model call with custom logic@wrap_tool_call- Wraps each tool call with custom logic
@dynamic_prompt- Generates dynamic system prompts
- Single hook needed
- No complex configuration
- Quick prototyping
Class-based middleware
More powerful for complex middleware with multiple hooks or configuration. Use classes when you need to define both sync and async implementations for the same hook, or when you want to combine multiple hooks in a single middleware. Example:- Defining both sync and async implementations for the same hook
- Multiple hooks needed in a single middleware
- Complex configuration required (e.g., configurable thresholds, custom models)
- Reuse across projects with init-time configuration
Custom state schema
Middleware can extend the agent’s state with custom properties.- Decorator
- Class
Execution order
When using multiple middleware, understand how they execute:Execution flow
Execution flow
Before hooks run in order:
middleware1.before_agent()middleware2.before_agent()middleware3.before_agent()
middleware1.before_model()middleware2.before_model()middleware3.before_model()
middleware1.wrap_model_call()→middleware2.wrap_model_call()→middleware3.wrap_model_call()→ model
middleware3.after_model()middleware2.after_model()middleware1.after_model()
middleware3.after_agent()middleware2.after_agent()middleware1.after_agent()
before_*hooks: First to lastafter_*hooks: Last to first (reverse)wrap_*hooks: Nested (first middleware wraps all others)
Agent jumps
To exit early from middleware, return a dictionary withjump_to:
Available jump targets:
'end': Jump to the end of the agent execution (or the firstafter_agenthook)'tools': Jump to the tools node'model': Jump to the model node (or the firstbefore_modelhook)
- Decorator
- Class
Best practices
- Keep middleware focused - each should do one thing well
- Handle errors gracefully - don’t let middleware errors crash the agent
- Use appropriate hook types:
- Node-style for sequential logic (logging, validation)
- Wrap-style for control flow (retry, fallback, caching)
- Clearly document any custom state properties
- Unit test middleware independently before integrating
- Consider execution order - place critical middleware first in the list
- Use built-in middleware when possible
Examples
Dynamic model selection
- Decorator
- Class
Tool call monitoring
- Decorator
- Class
Dynamically selecting tools
Select relevant tools at runtime to improve performance and accuracy. Benefits:- Shorter prompts - Reduce complexity by exposing only relevant tools
- Better accuracy - Models choose correctly from fewer options
- Permission control - Dynamically filter tools based on user access
- Decorator
- Class