From fc186f5613d7fd14301d5e89c19793711f786e3b Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 20:02:31 +0000 Subject: [PATCH 1/4] fix(bedrock): clamp maxTokens to the 16-token minimum for OpenAI GPT models on Converse Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../bedrock/chat/converse_transformation.py | 13 ++++++++++- .../chat/test_converse_transformation.py | 22 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/litellm/llms/bedrock/chat/converse_transformation.py b/litellm/llms/bedrock/chat/converse_transformation.py index 1a4f27e2ddd..4ef42664b9f 100644 --- a/litellm/llms/bedrock/chat/converse_transformation.py +++ b/litellm/llms/bedrock/chat/converse_transformation.py @@ -107,6 +107,7 @@ BEDROCK_COMPUTER_USE_TOOLS: Final = [ "bash_", "text_editor_", ] +BEDROCK_OPENAI_GPT_MIN_MAX_TOKENS: Final = 16 # Beta header patterns that are not supported by Bedrock Converse API # These will be filtered out to prevent errors @@ -377,6 +378,12 @@ class AmazonConverseConfig(BaseConfig): def _is_openai_gpt_reasoning_model(model: str) -> bool: return re.search(r"openai\.gpt-\d", model) is not None + @staticmethod + def _enforce_min_max_tokens(max_tokens: object) -> object: + if isinstance(max_tokens, int) and max_tokens < BEDROCK_OPENAI_GPT_MIN_MAX_TOKENS: + return BEDROCK_OPENAI_GPT_MIN_MAX_TOKENS + return max_tokens + def _is_nova_2_model(self, model: str) -> bool: """ Check if the model is a Nova 2 model that supports reasoningConfig. @@ -999,7 +1006,11 @@ class AmazonConverseConfig(BaseConfig): is_thinking_enabled=is_thinking_enabled, ) if param == "max_tokens" or param == "max_completion_tokens": - optional_params["maxTokens"] = value + optional_params["maxTokens"] = ( + self._enforce_min_max_tokens(cast(object, value)) + if self._is_openai_gpt_reasoning_model(model) + else value + ) if param == "stream": optional_params["stream"] = value if param == "stop": diff --git a/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py b/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py index 96c78c1cf75..f05b6ae97fe 100644 --- a/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py +++ b/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py @@ -457,6 +457,28 @@ def test_reasoning_with_forced_tool_choice_switches_to_auto(): assert optional_params["tool_choice"] == {"auto": {}} +@pytest.mark.parametrize( + "model, param, value, expected_max_tokens", + [ + ("us.openai.gpt-6-astra", "max_tokens", 1, 16), + ("us.openai.gpt-6-astra", "max_completion_tokens", 1, 16), + ("us.openai.gpt-6-astra", "max_tokens", 64, 64), + ("anthropic.claude-sonnet-4-5-20250929-v1:0", "max_tokens", 1, 1), + ], +) +def test_map_openai_params_enforces_minimum_max_tokens_for_openai_gpt_reasoning_models( + model: str, param: str, value: int, expected_max_tokens: int +): + optional_params = AmazonConverseConfig().map_openai_params( + non_default_params={param: value}, + optional_params={}, + model=model, + drop_params=False, + ) + + assert optional_params["maxTokens"] == expected_max_tokens + + @pytest.mark.parametrize( "model", [ From 3673327fc4251d55a9719a78461dd211c3d7595d Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 20:28:06 +0000 Subject: [PATCH 2/4] fix(bedrock): avoid unchecked cast in token clamp Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/llms/bedrock/chat/converse_transformation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litellm/llms/bedrock/chat/converse_transformation.py b/litellm/llms/bedrock/chat/converse_transformation.py index 4ef42664b9f..2b1d9619743 100644 --- a/litellm/llms/bedrock/chat/converse_transformation.py +++ b/litellm/llms/bedrock/chat/converse_transformation.py @@ -1007,8 +1007,8 @@ class AmazonConverseConfig(BaseConfig): ) if param == "max_tokens" or param == "max_completion_tokens": optional_params["maxTokens"] = ( - self._enforce_min_max_tokens(cast(object, value)) - if self._is_openai_gpt_reasoning_model(model) + self._enforce_min_max_tokens(value) + if self._is_openai_gpt_reasoning_model(model) and isinstance(value, int) else value ) if param == "stream": From 665327249da9ec65b95df75b2cebb472fc9462ce Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 22:06:09 +0000 Subject: [PATCH 3/4] fix(bedrock): extend maxTokens minimum clamp to xAI Grok models on Converse Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/llms/bedrock/chat/converse_transformation.py | 12 ++++++++---- .../bedrock/chat/test_converse_transformation.py | 5 ++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/litellm/llms/bedrock/chat/converse_transformation.py b/litellm/llms/bedrock/chat/converse_transformation.py index 2b1d9619743..801ec571376 100644 --- a/litellm/llms/bedrock/chat/converse_transformation.py +++ b/litellm/llms/bedrock/chat/converse_transformation.py @@ -107,7 +107,7 @@ BEDROCK_COMPUTER_USE_TOOLS: Final = [ "bash_", "text_editor_", ] -BEDROCK_OPENAI_GPT_MIN_MAX_TOKENS: Final = 16 +BEDROCK_OPENAI_COMPAT_MIN_MAX_TOKENS: Final = 16 # Beta header patterns that are not supported by Bedrock Converse API # These will be filtered out to prevent errors @@ -378,10 +378,14 @@ class AmazonConverseConfig(BaseConfig): def _is_openai_gpt_reasoning_model(model: str) -> bool: return re.search(r"openai\.gpt-\d", model) is not None + @staticmethod + def _requires_min_max_tokens(model: str) -> bool: + return re.search(r"openai\.gpt-\d|xai\.grok-", model) is not None + @staticmethod def _enforce_min_max_tokens(max_tokens: object) -> object: - if isinstance(max_tokens, int) and max_tokens < BEDROCK_OPENAI_GPT_MIN_MAX_TOKENS: - return BEDROCK_OPENAI_GPT_MIN_MAX_TOKENS + if isinstance(max_tokens, int) and max_tokens < BEDROCK_OPENAI_COMPAT_MIN_MAX_TOKENS: + return BEDROCK_OPENAI_COMPAT_MIN_MAX_TOKENS return max_tokens def _is_nova_2_model(self, model: str) -> bool: @@ -1008,7 +1012,7 @@ class AmazonConverseConfig(BaseConfig): if param == "max_tokens" or param == "max_completion_tokens": optional_params["maxTokens"] = ( self._enforce_min_max_tokens(value) - if self._is_openai_gpt_reasoning_model(model) and isinstance(value, int) + if self._requires_min_max_tokens(model) and isinstance(value, int) else value ) if param == "stream": diff --git a/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py b/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py index f05b6ae97fe..9d8bf786829 100644 --- a/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py +++ b/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py @@ -463,10 +463,13 @@ def test_reasoning_with_forced_tool_choice_switches_to_auto(): ("us.openai.gpt-6-astra", "max_tokens", 1, 16), ("us.openai.gpt-6-astra", "max_completion_tokens", 1, 16), ("us.openai.gpt-6-astra", "max_tokens", 64, 64), + ("us.xai.grok-4.6", "max_tokens", 1, 16), + ("global.xai.grok-4.6", "max_completion_tokens", 1, 16), + ("us.xai.grok-4.6", "max_tokens", 32, 32), ("anthropic.claude-sonnet-4-5-20250929-v1:0", "max_tokens", 1, 1), ], ) -def test_map_openai_params_enforces_minimum_max_tokens_for_openai_gpt_reasoning_models( +def test_map_openai_params_enforces_minimum_max_tokens_for_openai_compat_models( model: str, param: str, value: int, expected_max_tokens: int ): optional_params = AmazonConverseConfig().map_openai_params( From 12120fe59bd9dd36486fa683f84b06fb91bd9c9f Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Fri, 18 Sep 2026 17:11:29 -0700 Subject: [PATCH 4/4] refactor(bedrock): inline maxTokens clamp and cover inference-profile ARNs in tests --- litellm/llms/bedrock/chat/converse_transformation.py | 10 ++-------- .../llms/bedrock/chat/test_converse_transformation.py | 3 +++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/litellm/llms/bedrock/chat/converse_transformation.py b/litellm/llms/bedrock/chat/converse_transformation.py index 801ec571376..176819c0dab 100644 --- a/litellm/llms/bedrock/chat/converse_transformation.py +++ b/litellm/llms/bedrock/chat/converse_transformation.py @@ -382,12 +382,6 @@ class AmazonConverseConfig(BaseConfig): def _requires_min_max_tokens(model: str) -> bool: return re.search(r"openai\.gpt-\d|xai\.grok-", model) is not None - @staticmethod - def _enforce_min_max_tokens(max_tokens: object) -> object: - if isinstance(max_tokens, int) and max_tokens < BEDROCK_OPENAI_COMPAT_MIN_MAX_TOKENS: - return BEDROCK_OPENAI_COMPAT_MIN_MAX_TOKENS - return max_tokens - def _is_nova_2_model(self, model: str) -> bool: """ Check if the model is a Nova 2 model that supports reasoningConfig. @@ -1011,8 +1005,8 @@ class AmazonConverseConfig(BaseConfig): ) if param == "max_tokens" or param == "max_completion_tokens": optional_params["maxTokens"] = ( - self._enforce_min_max_tokens(value) - if self._requires_min_max_tokens(model) and isinstance(value, int) + max(value, BEDROCK_OPENAI_COMPAT_MIN_MAX_TOKENS) + if isinstance(value, int) and self._requires_min_max_tokens(model) else value ) if param == "stream": diff --git a/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py b/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py index 9d8bf786829..086a7e59f56 100644 --- a/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py +++ b/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py @@ -467,6 +467,9 @@ def test_reasoning_with_forced_tool_choice_switches_to_auto(): ("global.xai.grok-4.6", "max_completion_tokens", 1, 16), ("us.xai.grok-4.6", "max_tokens", 32, 32), ("anthropic.claude-sonnet-4-5-20250929-v1:0", "max_tokens", 1, 1), + ("arn:aws:bedrock:us-east-1:123456789012:inference-profile/us.openai.gpt-6-astra", "max_tokens", 1, 16), + ("arn:aws:bedrock:us-east-1:123456789012:inference-profile/global.xai.grok-4.6", "max_tokens", 1, 16), + ("arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/abc123xyz", "max_tokens", 1, 1), ], ) def test_map_openai_params_enforces_minimum_max_tokens_for_openai_compat_models(