What is BaseEventListener?
BaseEventListener lets you subscribe to typed CrewAI lifecycle events — crew kickoff, tool start/finish, LLM stream chunks, guardrail failures, and more — without mutating agent prompts. Implementations override on_event(self, event) and are registered with crewai_event_bus.subscribe(MyListener()), then fan out to structured logs, metrics, or streaming transports such as SSE. Because listeners run on the hot path of execution, keep per-event work tiny: push payloads onto an asyncio.Queue, batch them to your observability vendor, or increment counters synchronously and defer I/O to worker threads.
Listeners complement hooks: hooks can change behavior (block a tool), while listeners should be read-only observers unless you deeply understand re-entrancy risks. Multiple listeners compose; ordering is not a guarantee you should rely on for correctness. Prefer filtering inside the listener by event type or agent fingerprint so high-volume streams like LLMStreamChunkEvent do not overwhelm downstream systems.
When upgrading CrewAI, re-run integration tests against your listener — new event types appear regularly and default handler signatures can shift. Defensive isinstance checks keep old listeners running across minor bumps without silent drops.
When to Use
Custom telemetry, audit logs, cost dashboards, or bridging CrewAI events to your existing observability stack.
Use Cases
- • Custom tracing
- • Slack alerts on failures
- • Token streaming to a web UI
Key Features
- ✓ Subscribes to typed events
- ✓ Composable with built-in listeners
- ✓ Non-invasive by default
When NOT to Use
When first-party tracing already covers your needs or when you should use hooks to enforce policy.
Notes
Thread safety
Events may arrive from worker threads. Use thread-safe counters or push to a queue processed by a single consumer instead of mutating shared Python structures without locks.
Backpressure
High-frequency events such as stream chunks can saturate a naive logging pipeline. Sample, aggregate per second, or filter to critical types before hitting network exporters.
Test isolation
The bus is global. In pytest, clear subscriptions between tests if your CrewAI version exposes a supported API, or isolate tests in subprocesses so listener leakage cannot cross cases.
Import
from crewai.events import BaseEventListener
Code Examples
Count tool events
from crewai.events import BaseEventListener, crewai_event_bus
class ToolCounter(BaseEventListener):
def __init__(self):
super().__init__()
self.count = 0
def on_event(self, event):
name = type(event).__name__
if name.startswith('ToolUsage'):
self.count += 1
crewai_event_bus.subscribe(ToolCounter())
Structured logging
import logging
from crewai.events import BaseEventListener, crewai_event_bus
log = logging.getLogger('crewai.events')
class AuditListener(BaseEventListener):
def on_event(self, event):
log.info('event=%s', type(event).__name__)
crewai_event_bus.subscribe(AuditListener())
Forward token usage metrics
from crewai.events import BaseEventListener, crewai_event_bus
class TokenExporter(BaseEventListener):
def on_event(self, event):
usage = getattr(event, 'usage', None)
if usage is not None:
# push usage.total_tokens to your metrics backend here
pass
crewai_event_bus.subscribe(TokenExporter())
Common Mistakes
❌ Doing heavy I/O on the event thread
✅ Push events to a queue and process out-of-band.
❌ Assuming listener invocation order defines business logic
✅ Encode ordering in Flow or Task.context, not in event handlers.
BaseEventListener FAQ
What is BaseEventListener in CrewAI?
Subclass-this base for custom event listeners that hook into the global crewai_event_bus. BaseEventListener lets you subscribe to typed CrewAI lifecycle events — crew kickoff, tool start/finish, LLM stream chunks, guardrail failures, and more — without mutating agent prompts. Implementations override on_event(self, event) and are registered with crewai_event_bus.subscribe(MyListener()), then fan out to structured logs, metrics, or streaming transports such as SSE. Because listeners run on the hot path of execution, keep per-event work tiny: push payloads onto an a…
Which package defines the CrewAI class BaseEventListener?
DevShelfHub maps BaseEventListener to Python module crewai.events (package path crewai.events in this reference). Pin your installed crewai version and match imports to the snippet on this page.
When should I use BaseEventListener?
Custom telemetry, audit logs, cost dashboards, or bridging CrewAI events to your existing observability stack.
When should I avoid using BaseEventListener?
When first-party tracing already covers your needs or when you should use hooks to enforce policy.
How do I import BaseEventListener in Python?
from crewai.events import BaseEventListener
Where can I explore more CrewAI API reference pages?
Open the CrewAI API reference index on DevShelfHub to search 58 classes, 30 methods, and 16 decorators, each with runnable examples, parameters, common mistakes, and cross-links.