diff --git a/litellm/utils.py b/litellm/utils.py index d9bffd9b92a..252018214d4 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -7447,11 +7447,12 @@ def filter_tools_by_allowed_types( allowed_tool_types: ["function"] A tool without a ``type`` key is treated as ``function`` (matching OpenAI - defaults). Returns None when no tools survive so an empty ``tools: []`` - array is not sent upstream (some providers reject that too). + defaults). Returns None when no tools survive — including when the incoming + list is already empty — so an empty ``tools: []`` array is never sent + upstream (some providers reject that too). """ if not tools: - return tools + return None filtered = [ t for t in tools diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index baaf421bc0f..7dcce9d7189 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -4908,7 +4908,8 @@ def test_filter_tools_by_allowed_types_wider_allowlist_and_empty_result() -> Non ) assert filter_tools_by_allowed_types(tools=None, allowed_tool_types=["function"]) is None - assert filter_tools_by_allowed_types(tools=[], allowed_tool_types=["function"]) == [] + # an already-empty list is normalized to None too — some providers reject tools: [] + assert filter_tools_by_allowed_types(tools=[], allowed_tool_types=["function"]) is None def test_reconcile_tool_choice_after_tool_filtering() -> None: