Docs
Integrations
CrewAI
SDK + EventListener

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

Get 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

ParameterTypeDefaultDescription
public_keystrRequired when deploying to CrewAI's cloud platform to avoid multi-instance auth conflicts. Use ants_platform._public_key.
agent_namestr"crew"Identifier used as the trace name (e.g. "support_crew").
agent_display_namestrNoneHuman-readable name shown in the UI.
tagsdictNoneKey-value pairs attached to every trace, e.g. {"env": "production"}.

AntsPlatform client options

ParameterTypeDefaultDescription
secret_key / public_key / hoststrenv varsAPI credentials.
timeoutint5HTTP 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:

  1. Initialise in crew.py at module level, before the class.
  2. Pass public_key explicitly to EventListener. CrewAI's enterprise telemetry creates its own internal Langfuse client. Without an explicit public_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 eventObservation
CrewKickoffStartedEventRoot span (trace created)
AgentExecutionStartedEventAgent span (nested under crew)
LLMCallStartedEvent / CompletedGeneration span with token usage and cost
ToolUsageStartedEvent / FinishedTool span with arguments and output
TaskStartedEvent / CompletedTask span
*FailedEvent / *ErrorEventError attribution (level=ERROR)

Supported process types

TypeSupport
Process.sequentialFully supported. Recommended.
Process.hierarchicalNot yet supported.

Next