From c755a81b5e48ee963b67f7c5ed3981981eb038bb Mon Sep 17 00:00:00 2001 From: Fenghuang Date: Wed, 22 Jul 2026 15:06:53 +0900 Subject: [PATCH] fix: normalize an already-empty tools list to None under allowed_tool_types Greptile flagged that filter_tools_by_allowed_types passed an incoming tools: [] through unchanged, while the whole point of the None return is that some strict providers reject empty tool arrays. Empty in -> None out. Co-Authored-By: Claude Fable 5 --- litellm/utils.py | 7 ++++--- tests/test_litellm/test_utils.py | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) 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: