DS DevShelfHub Projects · AI tools
Tutorials / CrewAI / Reference / Classes / BaseEventListener
Class events

BaseEventListener: Reference Guide

By DevShelfHub

Subclass-this base for custom event listeners that hook into the global crewai_event_bus.

See the CrewAI API reference index, CrewAI introduction, and core concepts for surrounding context.

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

python
from crewai.events import BaseEventListener

Code Examples

Count tool events

python
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

python
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

python
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.