Skip to content

fix(llm): keep the litellm fallback on litellm releases before 1.97 - #8724

Closed
pylaterreur wants to merge 2 commits into
crewAIInc:mainfrom
pylaterreur:fix/litellm-optional-custom-tool-call
Closed

pylaterreur wants to merge 2 commits into
crewAIInc:mainfrom
pylaterreur:fix/litellm-optional-custom-tool-call

Conversation

@pylaterreur

@pylaterreur pylaterreur commented Oct 28, 2026 •

Copy link
Copy Markdown

Related issue

Fixes #8723

Summary

_ensure_litellm() imported ChatCompletionDeltaCustomToolCall (added in #8676), but litellm only has it since 1.97.0. With an older litellm the import raised ImportError, 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 its TYPE_CHECKING import 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_type in lib/crewai/tests/test_llm.py: fails on main with the ImportError, passes with this change.

  • Offline (--block-network) on Python 3.12 with the locked dependencies (litellm 1.100.4): tests/test_llm.py and 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-backed LLM with this change and raises the ImportError on main.

  • ruff check, ruff format --check and mypy (strict, repo config) on llm.py pass.

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 ImportError text 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 of ChatCompletionDeltaCustomToolCall (added in litellm 1.97.0); that import had been failing and marking LiteLLM as unavailable, so prefixed fallback models like openai/custom-finetune-model could not be constructed.

The type stays available under TYPE_CHECKING for annotations in _ahandle_streaming_response only. 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-backed LLM still initializes.

Reviewed by Cursor Bugbot for commit 7d44c9f. Bugbot is set up for automated code reviews on this repo. Configure here.

_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

strix-security Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Strix Security Review

Warning

This pull request has 17 commits after the last Strix review (bda22b0). Strix has not reviewed these changes.
Automatic review on push is off for this repository. To review the latest changes, tag @strix-security in a comment, or turn on re-review on push.

✅ 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 summary

No security issues found. The only runtime occurrence of ChatCompletionDeltaCustomToolCall is a local variable annotation in _ahandle_streaming_response (lib/crewai/src/crewai/llm.py:1688), which Python never evaluates (the module also enables from __future__ import annotations), so removing the runtime import and global rebinding cannot raise at import or streaming time and does not touch the tool-call filtering logic, which branches solely on ChatCompletionDeltaToolCall. No other module imports, isinstance-checks, casts or getattrs the removed name, and nothing in the change affects authentication, data flow, or trust boundaries — on older LiteLLM it simply lets the intended fallback load. The added test only monkeypatches module globals and litellm attributes and introduces no production behaviour.

Review 1 on this PR · bda22b0 · requested Oct 28 11:20 UTC when the PR was opened


Reviewed by Strix
Re-run review · Configure security review settings

@pylaterreur

Copy link
Copy Markdown
Author

Related: this is what broke the CrewAI instrumentation tests of alibaba/loongsuite-python (alibaba/loongsuite-python#290).

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7d44c9f. Configure here.

@pylaterreur

Copy link
Copy Markdown
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] LiteLLM fallback is reported as not installed with litellm older than 1.97.0 (since 1.15.31)

1 participant