Repository navigation
fix(llm): keep the litellm fallback on litellm releases before 1.97 - #8724
pylaterreur wants to merge 2 commits into
Conversation
_ensure_litellm() imported ChatCompletionDeltaCustomToolCall, which litellm added in 1.97.0. With an older litellm that import raised ImportError, so crewAI reported LiteLLM as not installed and every model that needs the fallback failed to build. The name is only used in a local variable annotation, which Python never evaluates, so import it for type checking only. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GwUvhmzgfkiZ6vo4uGyesN
Strix Security ReviewWarning This pull request has 17 commits after the last Strix review ( ✅ No open security findings. PR summary: The PR makes the LiteLLM fallback in `lib/crewai/src/crewai/llm.py` tolerate LiteLLM releases older than 1.97: it drops the runtime import and module-level binding of `ChatCompletionDeltaCustomToolCall` (kept only under `TYPE_CHECKING`) and adds a regression test in `lib/crewai/tests/test_llm.py`. Review summaryNo security issues found. The only runtime occurrence of Review 1 on this PR · Reviewed by Strix |
|
Related: this is what broke the CrewAI instrumentation tests of alibaba/loongsuite-python (alibaba/loongsuite-python#290). |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7d44c9f. Configure here.
| global litellm, Choices, LiteLLMDelta, Message, ModelResponseBase | ||
| global ModelResponseStream, LiteLLMStreamingChoices, get_supported_openai_params | ||
| global ChatCompletionDeltaCustomToolCall, ChatCompletionDeltaToolCall, Function | ||
| global ChatCompletionDeltaToolCall, Function |
There was a problem hiding this comment.
Compat test still expects dropped name
Medium Severity
Dropping the module-level ChatCompletionDeltaCustomToolCall binding and its global rebind means crewai.llm no longer exposes that attribute. test_litellm_import_compat.py still monkeypatches and asserts it, so that test raises AttributeError instead of covering older LiteLLM imports.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 7d44c9f. Configure here.
|
Closing: #8777 (merged 2026-10-29) fixes the same problem, with the same cause (the class is only used in a local variable annotation), and its compat test conflicts with this PR. 🤖 Generated with Claude Code |


Related issue
Fixes #8723
Summary
_ensure_litellm()importedChatCompletionDeltaCustomToolCall(added in #8676), but litellm only has it since 1.97.0. With an older litellm the import raisedImportError, so crewAI reported LiteLLM as not installed, and every model that needs the fallback (e.g.openai/qwen-turbo) failed to build. The name is only used in a local variable annotation in_ahandle_streaming_response, which Python never evaluates. This PR keeps itsTYPE_CHECKINGimport and drops the runtime import and the global rebinding.Verification
Tests added or updated for the changed behavior
Relevant tests and quality checks pass locally
New test
test_litellm_fallback_loads_without_custom_tool_call_delta_typeinlib/crewai/tests/test_llm.py: fails onmainwith theImportError, passes with this change.Offline (
--block-network) on Python 3.12 with the locked dependencies (litellm 1.100.4):tests/test_llm.pyand the other LiteLLM-related tests (test_llm_streaming_finish_reason.py,test_llm_overlay.py,test_llm_litellm_usage_events.py,utilities/test_create_llm_like.py,events/test_llm_finish_reason_response_id.py,llms/litellm/,llms/test_tool_call_streaming.py): 239 passed, 12 skipped.main: the same, except that the new test fails.With litellm 1.95.0 and 1.96.0,
LLM(model="openai/qwen-turbo")builds a LiteLLM-backedLLMwith this change and raises theImportErroronmain.ruff check,ruff format --checkandmypy(strict, repo config) onllm.pypass.Additional context
The error raised when the fallback can't load still says that LiteLLM is "not installed" even when importing it failed for another reason. Including the
ImportErrortext would make cases like this one easier to diagnose; that is left for a follow-up.AI-assisted (Claude Code), per CONTRIBUTING.md (
llm-generated).🤖 Generated with Claude Code
https://claude.ai/code/session_01GwUvhmzgfkiZ6vo4uGyesN
Note
Low Risk
Narrow compatibility fix in lazy LiteLLM loading with a regression test; no change to completion or streaming behavior beyond restoring fallback on older litellm versions.
Overview
Fixes LiteLLM fallback initialization when litellm < 1.97.0 is installed.
_ensure_litellm()no longer requires a runtime import ofChatCompletionDeltaCustomToolCall(added in litellm 1.97.0); that import had been failing and marking LiteLLM as unavailable, so prefixed fallback models likeopenai/custom-finetune-modelcould not be constructed.The type stays available under
TYPE_CHECKINGfor annotations in_ahandle_streaming_responseonly. Runtime loading of that symbol is optional when present.Adds
test_litellm_fallback_loads_without_custom_tool_call_delta_type, which simulates older litellm by removing the symbol and asserting the LiteLLM-backedLLMstill initializes.Reviewed by Cursor Bugbot for commit 7d44c9f. Bugbot is set up for automated code reviews on this repo. Configure here.