traceloop / traceloop/openllmetry

πŸ› Bug Report: CrewAI: LLM.call wrap never fires on crewai >= 1.x native providers, so no LLM span is emitted

Open
#4,453 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
7.4k
Forks
1.1k
Avg merge
8d 14h
Merged PRs (30d)
2

Description

Which component is this bug for?

All Packages

πŸ“œ Description

Component: CrewAI Instrumentation β€” not in the dropdown, so "All Packages."

_instrument wraps crewai.llm LLM.call (instrumentation.py#L93-L94), but on crewai 1.15.18 that wrap can never be reached on the native-provider path, so wrap_llm_call never runs β€” no {model}.llm span, and the duration histogram in _record_duration never records.

crewai.llm.LLM.__new__ is a factory that routes to native provider classes rather than returning an LLM:

def __new__(cls, model: str, is_litellm: bool = False, **kwargs) -> LLM:
    """Factory method that routes to native SDK or falls back to LiteLLM."""

The resulting object is not in LLM's hierarchy at all:

>>> a = Agent(role='r', goal='g', backstory='b')
>>> type(a.llm)
crewai.llms.providers.openai.completion.OpenAICompletion
>>> isinstance(a.llm, crewai.llm.LLM)
False
>>> [c.__name__ for c in OpenAICompletion.__mro__]
['OpenAICompletion', 'BaseLLM', 'BaseModel', 'ABC', 'object']

So patching crewai.llm.LLM.call patches a class the agent never instantiates.

πŸ‘Ÿ Reproduction steps
  1. pip install crewai==1.15.18 traceloop-sdk==0.62.3 opentelemetry-instrumentation-crewai==0.62.3
  2. Traceloop.init(...), build a crew with a default Agent (no explicit LLM), run Crew.kickoff().
  3. Inventory the exported span names.
πŸ‘ Expected behavior

A {model}.llm span per LLM call, as wrap_llm_call is written to produce, plus the gen_ai.client.operation.duration recording.

πŸ‘Ž Actual Behavior with Screenshots

No {model}.llm span. Full inventory from a real run:

   3  openai.chat
   1  Support Responder.agent
   1  <task description>.task
   1  crewai.workflow
πŸ€– Python Version

3.12.3

πŸ“ƒ Provide any additional context for the Bug.

Scope: I verified the native OpenAI provider route only. LLM.__new__ also has a LiteLLM fallback (is_litellm=True), and I haven't checked whether that path yields a real crewai.llm.LLM instance where the existing wrap would still fire. So this may be "dead for native providers" rather than "dead everywhere" β€” worth confirming on your side.

On the fix: BaseLLM is the common ancestor and does define call, but OpenAICompletion overrides it, so wrapping BaseLLM.call wouldn't intercept either. The right seam is probably the provider classes, or whatever single funnel exists upstream of them β€” you'll know that better than I do. Happy to send a PR once you've picked one.

Related: #4452 covers the missing tool-execution span in the same package. (The one I previously opened)

πŸ‘€ Have you spent some time to check if this bug has been raised before?
  • I checked and didn't find similar issue
Are you willing to submit PR?

Yes I am willing to submit a PR!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up β€” it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/opentelemetry-instrumentation-crewai/opentelemetry/instrumentation/crewai/instrumentation.py at the _instrument wrapper, then inspect crewai.llm.LLM.new, BaseLLM.call, and OpenAICompletion.call. Reproduce with crewai==1.15.18 and inventory the exported spans. Done means native-provider LLM calls emit a {model}.llm span and record gen_ai.client.operation.duration without regressing the LiteLLM path.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
observability
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.