SDK + EventListener
For self-hosted CrewAI, or when you want full Python-SDK control over
session naming, tags, and flush timing, use the ants-platform SDK with
the bundled EventListener.
Running CrewAI Enterprise? Use the Native OTel path instead — it's zero-code and produces the same trace shape.
Setup
Install the SDK
pip install ants-platform[crewai]Requires Python >=3.10.
Set environment variables
ANTS_PLATFORM_PUBLIC_KEY=pk-ap-...
ANTS_PLATFORM_SECRET_KEY=sk-ap-...
ANTS_PLATFORM_HOST=https://api.agenticants.aiGet keys from Project Settings → API Keys in the ANTS Platform dashboard.
Register the EventListener at module level in crew.py
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from ants_platform import AntsPlatform
from ants_platform.crewai import EventListener
# Module-level initialisation — runs on import
ants_platform = AntsPlatform(timeout=30)
listener = EventListener(
public_key=ants_platform._public_key,
agent_name="research_crew",
agent_display_name="Research & Blog Crew v1.0",
)
@CrewBase
class ResearchCrew():
agents_config = "config/agents.yaml"
tasks_config = "config/tasks.yaml"
@agent
def researcher(self) -> Agent:
return Agent(config=self.agents_config["researcher"])
@task
def research_task(self) -> Task:
return Task(config=self.tasks_config["research_task"])
@crew
def crew(self) -> Crew:
return Crew(agents=self.agents, tasks=self.tasks, process=Process.sequential)Initialise in crew.py, not main.py. CrewAI's deployment runner imports @CrewBase directly and never executes main.py.
Flush before exit
In main.py (or wherever you call kickoff()):
from my_project.crew import ResearchCrew, ants_platform
def run():
try:
ResearchCrew().crew().kickoff(inputs={"topic": "AI agents"})
finally:
ants_platform.flush()
if __name__ == "__main__":
run()Configuration
EventListener parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
public_key | str | — | Required when deploying to CrewAI's cloud platform to avoid multi-instance auth conflicts. Use ants_platform._public_key. |
agent_name | str | "crew" | Identifier used as the trace name (e.g. "support_crew"). |
agent_display_name | str | None | Human-readable name shown in the UI. |
tags | dict | None | Key-value pairs attached to every trace, e.g. {"env": "production"}. |
AntsPlatform client options
| Parameter | Type | Default | Description |
|---|---|---|---|
secret_key / public_key / host | str | env vars | API credentials. |
timeout | int | 5 | HTTP timeout (seconds). Bump to 30 for slower local setups. |
Deploying to CrewAI's cloud platform
CrewAI's deployment runner bypasses main.py and imports your
@CrewBase class directly. Two rules:
- Initialise in
crew.pyat module level, before the class. - Pass
public_keyexplicitly toEventListener. CrewAI's enterprise telemetry creates its own internal Langfuse client. Without an explicitpublic_key, the SDK detects multiple client instances and disables tracing for safety.
# Correct
ants_platform = AntsPlatform(timeout=30)
listener = EventListener(public_key=ants_platform._public_key, agent_name="my_crew")
# Wrong — will get a disabled client in deployed environments
listener = EventListener(agent_name="my_crew")Set ANTS_PLATFORM_PUBLIC_KEY, ANTS_PLATFORM_SECRET_KEY,
ANTS_PLATFORM_HOST in your CrewAI deployment's Environment Variables.
Push your changes to your Git remote — crewai deploy push builds from
the remote, not your local files.
How it works
EventListener hooks into CrewAI's event bus on instantiation and
translates events into observations:
| CrewAI event | Observation |
|---|---|
CrewKickoffStartedEvent | Root span (trace created) |
AgentExecutionStartedEvent | Agent span (nested under crew) |
LLMCallStartedEvent / Completed | Generation span with token usage and cost |
ToolUsageStartedEvent / Finished | Tool span with arguments and output |
TaskStartedEvent / Completed | Task span |
*FailedEvent / *ErrorEvent | Error attribution (level=ERROR) |
Supported process types
| Type | Support |
|---|---|
Process.sequential | Fully supported. Recommended. |
Process.hierarchical | Not yet supported. |
Next
- Hit an issue? See Troubleshooting.
- Compare with the Native OTel approach for CrewAI Enterprise.