Hook into agent lifecycle
React to events in your agent's execution flow. Add logging, monitoring, reflection, and custom behavior at every step.
6 Event Types
Quick Start
Add event handlers to your agent in 3 simple steps:
Tip: Event handlers receive the agent instance, giving you full access to current_session, messages, trace, and more.
All Event Types
Here's when each event fires and what you can do with it:
after_user_input
Fires once per turn, after user input is added
after_llm
Fires after each LLM response (multiple times per turn)
after_tool
Fires after each successful tool execution
on_error
Fires when tool execution fails or tool not found
Combining Multiple Events
Use multiple event handlers together for comprehensive monitoring and control:
Key Concepts
Event Handler Signature
All event handlers receive the agent instance:
Message Injection Timing
Important: Use after_llm to inject messages after tool execution:
❌ Don't use after_tool: Injecting messages during tool execution breaks the OpenAI message sequence (assistant → tool results)
✅ Use after_llm: Fires after all tool results are added to messages, safe for injection
Error Handling
Event handlers follow fail-fast principle:
Real-World Use Cases
1. Performance Monitoring Dashboard
2. Automatic Context Injection
3. Smart Retry Logic
API Reference
Event Wrapper Functions
after_user_input(func: Callable[[Agent], None]) → EventHandlerWraps a function to fire after user input is added to session.
before_llm(func: Callable[[Agent], None]) → EventHandlerWraps a function to fire before each LLM call.
after_llm(func: Callable[[Agent], None]) → EventHandlerWraps a function to fire after each LLM response.
before_tool(func: Callable[[Agent], None]) → EventHandlerWraps a function to fire before each tool execution.
after_tool(func: Callable[[Agent], None]) → EventHandlerWraps a function to fire after each successful tool execution.
on_error(func: Callable[[Agent], None]) → EventHandlerWraps a function to fire when tool execution fails or tool is not found.
Agent Constructor
Agent(name, tools, on_events: Optional[List[EventHandler]] = None, ...)on_events: List of event handlers wrapped with event type functions
Best Practices
✅ Keep handlers simple: Each event handler should do one thing well. Compose multiple handlers for complex behavior.
✅ Use after_llm for message injection: This is the safe time to inject context after tool execution completes.
✅ Handle exceptions internally: If your event handler can fail, catch exceptions to prevent stopping the agent.
❌ Don't inject during tool execution: Using after_tool to inject messages breaks the tool calling message sequence.
❌ Don't do heavy computation: Event handlers run synchronously and block agent execution. Keep them fast.
