diff --git a/litellm/integrations/websearch_interception/handler.py b/litellm/integrations/websearch_interception/handler.py index 943a2bb4f36..5d36b760afb 100644 --- a/litellm/integrations/websearch_interception/handler.py +++ b/litellm/integrations/websearch_interception/handler.py @@ -413,6 +413,13 @@ async def _execute_agentic_loop( if k != 'max_tokens' } + # Remove internal websearch interception flags from kwargs before follow-up request + # These flags are used internally and should not be passed to the LLM provider + kwargs_for_followup = { + k: v for k, v in kwargs.items() + if not k.startswith('_websearch_interception') + } + # Get model from logging_obj.model_call_details["agentic_loop_params"] # This preserves the full model name with provider prefix (e.g., "bedrock/invoke/...") full_model_name = model @@ -428,7 +435,7 @@ async def _execute_agentic_loop( messages=follow_up_messages, model=full_model_name, **optional_params_without_max_tokens, - **kwargs, + **kwargs_for_followup, ) verbose_logger.debug( f"WebSearchInterception: Follow-up request completed, response type: {type(final_response)}" diff --git a/tests/test_litellm/integrations/websearch_interception/test_websearch_interception_handler.py b/tests/test_litellm/integrations/websearch_interception/test_websearch_interception_handler.py index 8ac53315aa0..5abecb46c99 100644 --- a/tests/test_litellm/integrations/websearch_interception/test_websearch_interception_handler.py +++ b/tests/test_litellm/integrations/websearch_interception/test_websearch_interception_handler.py @@ -67,3 +67,36 @@ async def test_async_should_run_agentic_loop(): assert should_run is False assert tools_dict == {} + + +@pytest.mark.asyncio +async def test_internal_flags_filtered_from_followup_kwargs(): + """Test that internal _websearch_interception flags are filtered from follow-up request kwargs. + + Regression test for bug where _websearch_interception_converted_stream was passed + to the follow-up LLM request, causing "Extra inputs are not permitted" errors + from providers like Bedrock that use strict parameter validation. + """ + logger = WebSearchInterceptionLogger(enabled_providers=["bedrock"]) + + # Simulate kwargs that would be passed during agentic loop execution + kwargs_with_internal_flags = { + "_websearch_interception_converted_stream": True, + "_websearch_interception_other_flag": "test", + "temperature": 0.7, + "max_tokens": 1024, + } + + # Apply the same filtering logic used in _execute_agentic_loop + kwargs_for_followup = { + k: v for k, v in kwargs_with_internal_flags.items() + if not k.startswith('_websearch_interception') + } + + # Verify internal flags are filtered out + assert "_websearch_interception_converted_stream" not in kwargs_for_followup + assert "_websearch_interception_other_flag" not in kwargs_for_followup + + # Verify regular kwargs are preserved + assert kwargs_for_followup["temperature"] == 0.7 + assert kwargs_for_followup["max_tokens"] == 1024