Repository navigation
Conversation
CrewAI emits LLMCallFailedEvent instead of LLMCallCompletedEvent when an LLM call fails. The listener had no handler for it, so the Observer entered in on_llm_started never exited: the LLM span leaked in trace_manager.active_spans, blocked end_trace for the whole trace once the root span closed, and span_observers grew on every failed call. Add an on_llm_failed listener that pops the observer, marks the span ERRORED with the event error via observer.__exit__, and restores the span context the same way on_llm_completed does. Also handle ToolUsageErrorEvent, which CrewAI emits instead of ToolUsageFinishedEvent when a tool raises, by popping the stale metadata entry from tool_observers_stack.
|
@BlueX888 is attempting to deploy a commit to the Confident AI Team on Vercel. A member of the Team first needs to authorize it. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a CrewAI LLM call fails, CrewAI emits
LLMCallFailedEventinstead ofLLMCallCompletedEventand then re-raises (crewai/llms/base_llm.py,_emit_call_failed_event). The CrewAI event listener had no handler for the failed event, so theObserverentered inon_llm_startedwas never exited.Why
on_llm_started(deepeval/integrations/crewai/handler.py:182) stores anObserverinspan_observers, keyed byllm_{id(source)}_{event.call_id}, and callsobserver.__enter__(). Onlyon_llm_completed(deepeval/integrations/crewai/handler.py:242) popped and exited that observer, so on a failed call:trace_manager.active_spansforever (noend_time, no status);Observer.__exit__only callstrace_manager.end_tracewhen no other span of the trace is still active (deepeval/tracing/tracing.py:1333-1341), so once the root span closed, the whole trace stayed inactive_tracesand was never finalized/posted;span_observersentry was never removed and accumulated on every failed call.on_tool_started(deepeval/integrations/crewai/handler.py:327) appends metadata totool_observers_stack, but CrewAI emitsToolUsageErrorEventinstead ofToolUsageFinishedEventwhen a tool raises, so the entry was never popped.Verified on the unpatched tree by emitting
LLMCallStartedEvent+LLMCallFailedEventfor one call and exiting the rootObserver: theLlmSpanremains withend_time=None, the trace remains inactive_traces, andspan_observersstill holds the entry.Changes
deepeval/integrations/crewai/handler.py: add anon_llm_failedlistener that pops the observer, marks the spanERROREDwith the event's error throughobserver.__exit__, and restores the span context the same wayon_llm_completeddoes; add anon_tool_errorlistener that pops the stale metadata entry fromtool_observers_stack.tests/test_integrations/test_crewai/test_crewai_error_events.py: regression tests that emit the started/failed and started/error event pairs throughcrewai_event_busdirectly (no API key required) and assert the span is closed asERROREDwith the error recorded, the trace finalizes once the root span exits, and no observer state leaks.Testing
With
crewai==1.15.22(the handler'scall_id-keyed events match crewai 1.x):pytest tests/test_integrations/test_crewai/test_crewai_error_events.py→ 2 failed:test_llm_call_failed_event_closes_llm_span_and_finalizes_trace—AssertionError: assert 1 == 0(LlmSpan still intrace_manager.active_spansafter the root span exited)test_tool_usage_error_event_clears_pending_tool_metadata—AssertionError: assert not True(metadata still intool_observers_stack)2 passed in 0.02spytest tests/test_integrations/test_crewai/→16 failed, 2 passedbefore and after the fix with an identical failure list; all 16 fail withValueError: OPENAI_API_KEY is requiredbecause they run realcrew.kickoff()calls (the suite notes an OpenAI key is required, e.g.tests/test_integrations/test_crewai/test_sync.py:104), so they cannot run in a keyless environment.black --checkon both changed files:2 files would be left unchanged.ruff checkon both changed files: only the 3 pre-existingF401unused imports inhandler.py, identical tomain.