diff --git a/litellm/main.py b/litellm/main.py index 2ace46a16fb8..96f1d2aded92 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -5343,6 +5343,15 @@ def completion( # type: ignore else: optional_params["reasoning_effort"] = {"summary": rs_val} + # get_litellm_params() above is not passed **kwargs, so + # OPTIONAL_KWARGS_KEYS (e.g. AWS SigV4 aws_region_name / + # aws_access_key_id / aws_secret_access_key) never made it into + # litellm_params. Merge them in on the bridge path so the downstream + # responses() call can sign Bedrock Mantle requests with real creds. + for _param, _value in _supplemental_provider_params.items(): + if litellm_params.get(_param) is None: + litellm_params[_param] = _value + return responses_api_bridge.completion( # pyright: ignore[reportReturnType] # bridge returns a coroutine on the acompletion path; awaited by the async caller model=model, messages=messages, diff --git a/tests/test_litellm/completion_extras/test_responses_bridge_provider_propagation.py b/tests/test_litellm/completion_extras/test_responses_bridge_provider_propagation.py index 8036c72679e8..30b9fbc589d8 100644 --- a/tests/test_litellm/completion_extras/test_responses_bridge_provider_propagation.py +++ b/tests/test_litellm/completion_extras/test_responses_bridge_provider_propagation.py @@ -151,3 +151,45 @@ async def _fake_aresponses(**kwargs): except Exception: pass assert _fake_aresponses.kwargs.get("aws_region_name") == "us-east-2" + + +def test_completion_forwards_aws_creds_into_bridge_litellm_params(): + """Regression test for https://github.com/BerriAI/litellm/issues/32336 - + litellm.completion() dropped aws_region_name / aws_access_key_id / + aws_secret_access_key before dispatching the chat->responses bridge for + bedrock_mantle gpt-5.* (Responses-only) models, so SigV4 signed with empty + creds and Bedrock Mantle rejected the request. + + get_litellm_params() only extracts OPTIONAL_KWARGS_KEYS from its own + **kwargs, which completion() does not forward; the fix merges the + supplemental provider params back into litellm_params. This pins that the + AWS credentials survive into the litellm_params the bridge receives — the + handler-level tests above only cover forwarding once the params are already + present. + """ + import litellm + + captured = {} + + def _fake_bridge_completion(**kwargs): + captured.update(kwargs) + return MagicMock(spec=[]) + + with patch( + "litellm.completion_extras.responses_api_bridge.completion", + _fake_bridge_completion, + ): + litellm.completion( + model="bedrock_mantle/openai.gpt-5.4", + messages=[{"role": "user", "content": "hi"}], + api_base="https://bedrock-mantle.us-east-2.api.aws/v1", + aws_region_name="us-east-2", + aws_access_key_id="AKIAEXAMPLE", + aws_secret_access_key="secretexample", + ) + + assert captured, "responses_api_bridge.completion was never called" + litellm_params = captured.get("litellm_params") or {} + assert litellm_params.get("aws_region_name") == "us-east-2" + assert litellm_params.get("aws_access_key_id") == "AKIAEXAMPLE" + assert litellm_params.get("aws_secret_access_key") == "secretexample"