Skip to main content
https://storage.googleapis.com/arize-phoenix-assets/assets/images/phoenix-docs-images/gc.ico

Google Colab

tutorials/python/llm/tracing/crewai/crewai-tracing.ipynb at main · Arize-ai/tutorials

GitHub
CrewAI is a framework for orchestrating role-playing, autonomous AI agents. By leveraging OpenInference, you can trace CrewAI operations and the underlying LLM calls, sending the data to Arize for observability. This involves instrumenting CrewAI itself and the library it uses for LLM interactions. The correct LLM instrumentor depends on your CrewAI version.
CrewAI 1.0+ changed how LLM calls are routed. Starting with CrewAI 1.0 (GA October 2025), the framework routes LLM calls to native provider SDKs (OpenAI, Anthropic, etc.) based on the model string prefix. LiteLLM is only used as a fallback for providers without native support. This means the LLM-level instrumentor you install must match the provider CrewAI is actually calling. This page covers both CrewAI 1.0+ and 0.x instrumentation.

Launch Arize

To get started, sign up for a free Arize account and get your Space ID and API Key.

Install

pip install crewai crewai-tools

pip install openinference-instrumentation-crewai

# Install the instrumentor matching your LLM provider (see "Which instrumentor do I need?" below)
pip install openinference-instrumentation-openai

pip install arize-otel
The example above uses openinference-instrumentation-openai, which covers most default configurations. If your agents use anthropic/ prefixed models, install openinference-instrumentation-anthropic instead. For providers that fall back to LiteLLM (Groq, Together, etc.), use openinference-instrumentation-litellm.

API Key Setup

Your CrewAI agents will likely require API keys for the LLMs and tools they use. Configure these as environment variables. The example below uses OpenAI and SerperDevTool.
export OPENAI_API_KEY='YOUR_OPENAI_API_KEY'
export SERPER_API_KEY='YOUR_SERPER_API_KEY'

Which Instrumentor Do I Need?

CrewAI 1.0+ routes LLM calls to different provider SDKs based on your model string. Match your instrumentor to the provider CrewAI is calling:
Model stringProvider SDK usedInstrumentor package
openai/gpt-4o, gpt-4o, or no prefixOpenAI (native)openinference-instrumentation-openai
anthropic/claude-sonnet-4-6Anthropic (native)openinference-instrumentation-anthropic
Groq, Together, or other unsupported providersLiteLLM (fallback)openinference-instrumentation-litellm
The CrewAI instrumentor (openinference-instrumentation-crewai) is always required regardless of provider. It captures Crew, Agent, and Task spans.

Setup Tracing

Import order matters. All OpenInference instrumentors use monkeypatching to wrap library internals. If CrewAI or the underlying LLM library is imported before .instrument() is called, the patches are applied to stale references and spans will be silently dropped. Always complete all instrumentation setup before importing crewai.
# Step 1: Register the tracer provider (sets the global TracerProvider)
from arize.otel import register

register(
    space_id="YOUR_SPACE_ID",
    api_key="YOUR_API_KEY",
    project_name="my-crewai-app"
)

# Step 2: Instrument BEFORE any crewai imports
from openinference.instrumentation.crewai import CrewAIInstrumentor
from openinference.instrumentation.openai import OpenAIInstrumentor

CrewAIInstrumentor().instrument()
OpenAIInstrumentor().instrument()

# Step 3: Now safe to import crewai
from crewai import Agent, Crew, Task, LLM
The tracer_provider= kwarg on each .instrument() call is optional when register() has already set the global TracerProvider. Omitting it is cleaner and avoids bugs where different instrumentors accidentally receive different provider instances.

Run CrewAI Example

Define your agents and tasks, then kick off the crew. This example assumes instrumentation has already been configured in the Setup Tracing step above.
from crewai import Agent, Task, Crew, LLM
from crewai_tools import SerperDevTool

search_tool = SerperDevTool()

llm = LLM(model="openai/gpt-4o")

researcher = Agent(
  role='Senior Research Analyst',
  goal='Uncover cutting-edge developments in AI and data science',
  backstory="""You work at a leading tech think tank.
  Your expertise lies in identifying emerging trends.
  You have a knack for dissecting complex data and presenting actionable insights.""",
  verbose=True,
  allow_delegation=False,
  tools=[search_tool],
  llm=llm,
)

writer = Agent(
  role='Tech Content Strategist',
  goal='Craft compelling content on tech advancements',
  backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles.
  You transform complex concepts into compelling narratives.""",
  verbose=True,
  allow_delegation=True,
  llm=llm,
)

task1 = Task(
  description="""Conduct a comprehensive analysis of the latest advancements in AI in 2025.
  Identify key trends, breakthrough technologies, and potential industry impacts.""",
  expected_output="Full analysis report in bullet points",
  agent=researcher
)

task2 = Task(
  description="""Using the insights provided, develop an engaging blog
  post that highlights the most significant AI advancements.
  Your post should be informative yet accessible, catering to a tech-savvy audience.
  Make it sound cool, avoid complex words so it doesn't sound like AI.""",
  expected_output="Full blog post of at least 4 paragraphs",
  agent=writer
)

crew = Crew(
  agents=[researcher, writer],
  tasks=[task1, task2],
  verbose=False,
)

print("Kicking off the crew...")
result = crew.kickoff()

print("######################")
print("CrewAI run completed. Result:")
print(result)
print("######################")
print("Check Arize for traces.")

Observe

Traces from CrewAI operations (Crew, Agent, and Task spans) and the underlying LLM calls will be streamed to your Arize account. This provides a comprehensive view of your multi-agent system.

Troubleshooting

I see Crew/Agent/Task spans but no LLM spans

This is the most common issue with CrewAI 1.0+. It means the LLM instrumentor does not match the provider CrewAI is routing to. For example, if your model string is openai/gpt-4o, CrewAI calls the native OpenAI SDK directly and never touches LiteLLM — so openinference-instrumentation-litellm will see nothing. Fix: Check your model string prefix and install the matching instrumentor (see Which Instrumentor Do I Need? above).

Spans are missing entirely (no Crew spans, no LLM spans)

This is almost always an import-order problem. Both the CrewAI instrumentor (which uses wrapt to wrap class methods) and LLM-level instrumentors (which use setattr to replace module-level functions) must run before the target library is imported. Fix: Make sure all .instrument() calls execute before any from crewai import ... line. A common anti-pattern: if your instrumentation lives in a separate module (e.g., tracing.py), make sure it is imported and executed before any module that imports crewai. For example, this breaks:
# main.py — BROKEN: crewai is imported before tracing runs
from crew import my_crew        # this file imports crewai at the top
from tracing import setup       # too late — crewai already imported

if __name__ == "__main__":
    setup()
    my_crew.kickoff()
# main.py — FIXED: tracing runs first
from tracing import setup
setup()

from crew import my_crew        # crewai imported after instrumentation

if __name__ == "__main__":
    my_crew.kickoff()

Version check errors with new CrewAI releases

If you are using a release candidate or very new CrewAI version and the instrumentor fails a dependency check, pass skip_dep_check=True:
CrewAIInstrumentor().instrument(skip_dep_check=True)

Resources

CrewAI Documentation

CrewAI LLM Provider Routing

CrewAI LiteLLM Removal Guide

OpenInference CrewAI Instrumentation

SerperDevTool (Example Tool)