From f2b399d451c5f094568848bdd01b0965c967bb71 Mon Sep 17 00:00:00 2001 From: lei_lei <96427312+leilei3167@users.noreply.github.com> Date: Sun, 30 Aug 2026 10:49:44 +0800 Subject: [PATCH] fix(websearch): recognize conventional function tool name --- .../websearch_interception/tools.py | 8 ++--- .../test_websearch_tools.py | 34 +++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 tests/test_litellm/integrations/websearch_interception/test_websearch_tools.py diff --git a/litellm/integrations/websearch_interception/tools.py b/litellm/integrations/websearch_interception/tools.py index 97c6c90d2ba..04178d88179 100644 --- a/litellm/integrations/websearch_interception/tools.py +++ b/litellm/integrations/websearch_interception/tools.py @@ -156,12 +156,12 @@ def is_web_search_tool_chat_completion(tool: dict[str, Any]) -> bool: """ Check if a tool is a web search tool for Chat Completions API (strict check). - This is a stricter version that ONLY checks for the exact LiteLLM web search tool name. + This is a stricter version that checks the recognized web search tool names. Use this for Chat Completions API to avoid false positives with user-defined tools. Detects ONLY: - LiteLLM standard: name == "litellm_web_search" (Anthropic format) - - OpenAI format: type == "function" with function.name == "litellm_web_search" + - OpenAI format: type == "function" with function.name == "litellm_web_search" or "web_search" Args: tool: Tool dictionary to check @@ -186,7 +186,7 @@ def is_web_search_tool_chat_completion(tool: dict[str, Any]) -> bool: if tool_type == "function" and "function" in tool: function_def: Final = tool.get("function", {}) function_name: Final = function_def.get("name", "") - if function_name == LITELLM_WEB_SEARCH_TOOL_NAME: + if function_name in (LITELLM_WEB_SEARCH_TOOL_NAME, "web_search"): return True # Check for LiteLLM standard tool (Anthropic format) @@ -270,7 +270,7 @@ def is_web_search_tool(tool: dict[str, Any]) -> bool: if tool_type == "function" and "function" in tool: function_def: Final = tool.get("function", {}) function_name: Final = function_def.get("name", "") - if function_name == LITELLM_WEB_SEARCH_TOOL_NAME: + if function_name in (LITELLM_WEB_SEARCH_TOOL_NAME, "web_search"): return True # Check for LiteLLM standard tool (Anthropic format) diff --git a/tests/test_litellm/integrations/websearch_interception/test_websearch_tools.py b/tests/test_litellm/integrations/websearch_interception/test_websearch_tools.py new file mode 100644 index 00000000000..afba4306272 --- /dev/null +++ b/tests/test_litellm/integrations/websearch_interception/test_websearch_tools.py @@ -0,0 +1,34 @@ +"""Unit tests for web search tool shape detection.""" + +import pytest + +from litellm.integrations.websearch_interception.tools import ( + is_web_search_tool, + is_web_search_tool_chat_completion, +) + + +@pytest.mark.parametrize( + "tool", + [ + {"type": "function", "function": {"name": "litellm_web_search"}}, + {"type": "function", "function": {"name": "web_search"}}, + ], +) +def test_openai_function_web_search_shapes_are_detected(tool): + """Recognize both LiteLLM and conventional web_search function names.""" + assert is_web_search_tool(tool) is True + assert is_web_search_tool_chat_completion(tool) is True + + +@pytest.mark.parametrize( + "tool", + [ + {"type": "function", "function": {"name": "web_search_helper"}}, + {"type": "function", "function": {"name": "search"}}, + ], +) +def test_unrelated_openai_function_tools_are_not_detected(tool): + """Do not classify similarly named user tools as web search.""" + assert is_web_search_tool(tool) is False + assert is_web_search_tool_chat_completion(tool) is False