Skip to main content
Install the integration extra:

observer.kickoff()

Wraps crew.kickoff() for you. Each task is captured as a child span on the trace, with the task description as its input and the raw output as its output.

What gets traced

The root span is stamped span kind agent, and each per-task child span is stamped agent as well - a CrewAI task is an agent turn, not a model call. Token counts are not captured by this integration - the task-level events it listens to don’t carry per-call usage. Per-task timing comes from CrewAI’s event bus (TaskStartedEvent / TaskCompletedEvent / TaskFailedEvent, available on modern CrewAI versions) - observer.kickoff() registers temporary listeners for the duration of the call, keyed by each task’s real id so concurrent tasks (async_execution=True) are timed correctly rather than attributed to whichever task started most recently.
On older CrewAI versions that predate the event bus, kickoff() falls back to splitting the total latency evenly across tasks instead - still useful for task order, just not exact per-task duration on those versions.

observer.observe() context manager

Use this instead of kickoff() when you need to call crew.kickoff() yourself, for example to catch exceptions before they reach AgentX, or to run additional logic between kickoff and reading the result:
Unlike kickoff(), the observe() context manager doesn’t create per-task child spans - you get a single span for the whole run. Record individual tool calls yourself with span.add_tool_call(...) if you need that detail.

AgentXCrewObserver reference

observe() parameters

observe() returns a _TraceSpan, which you use as a context manager. Inside the with block, assign span.output before exiting to set the trace output. Because you hold the span itself, span.trace_id is available - pass sync=True to send synchronously so it is populated once the block exits, e.g. to link the trace to an evaluation result.
Call tracer.flush() before your process exits in scripts or one-shot jobs. In long-running servers it is not required: traces drain automatically in the background.