From dde0e60cccbf25701fbd7249094ff656653ea6aa Mon Sep 17 00:00:00 2001 From: Patrick Decat Date: Tue, 1 Sep 2026 16:08:06 +0200 Subject: [PATCH] fix(bedrock): drop toolSpec.strict for four more Claude Converse ids Bedrock Converse routes Haiku 4.5, Sonnet 4.5/4.6 and Opus 4.6 through the same Anthropic-compatible validator as Opus 4.7/4.8 and Sonnet 4/5, but their cost-map entries were never flagged, so `toolSpec.strict` is still forwarded for them. Forwarding `strict: true` makes the model compile the tool schema into a constrained-decoding grammar, and that grammar rejects ordinary JSON Schema keywords. A tool carrying `maxItems` on an array property then fails the whole request: BedrockException - {"message":"The model returned the following errors: tools.1.custom: For 'array' type, property 'maxItems' is not supported"} Neither field fails on its own, only the pair, which is why this surfaced as a sudden breakage for tool-calling clients (Cline forks, Codex, MCP toolsets) after upgrading across v1.90.0, where forwarding `toolSpec.strict` to Converse was introduced. Reproduced against Bedrock for Haiku 4.5, Sonnet 4.6 and Opus 4.6; Sonnet 4.5 is flagged as the remaining member of the same cohort. Sets `bedrock_converse_supports_strict_tools: false` on all 30 Bedrock entries for those four ids (bare, every region prefix, and the us-gov keys), matching how Opus 4.7/4.8, Sonnet 4 and Sonnet 5 are already flagged, so the fix is data rather than another hardcoded model pattern. Two tests asserted the pre-fix behaviour and are updated: the strict-tools regression suite listed Sonnet 4.5/4.6 and Opus 4.6 as models that keep the field, and test_bedrock_tools_pt_strict_parameter used Sonnet 4.5 as its example of a Claude id that forwards it, which is now Opus 4.5. Fixes #34388 --- ...odel_prices_and_context_window_backup.json | 30 ++++++++++ model_prices_and_context_window.json | 30 ++++++++++ ...edrock_converse_strict_tools_opus_47_48.py | 60 ++++++++++++++++--- ...llm_core_utils_prompt_templates_factory.py | 8 ++- 4 files changed, 117 insertions(+), 11 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 718e6c489fd..3a3ca4c3cfa 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -756,6 +756,7 @@ "prompt_cache_min_tokens": 2048 }, "anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.25e-06, "cache_creation_input_token_cost_above_1hr": 2e-06, "cache_read_input_token_cost": 1e-07, @@ -784,6 +785,7 @@ "output_cost_per_token_batches": 2.5e-06 }, "anthropic.claude-haiku-4-5@20251001": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.25e-06, "cache_creation_input_token_cost_above_1hr": 2e-06, "cache_read_input_token_cost": 1e-07, @@ -1038,6 +1040,7 @@ "prompt_cache_min_tokens": 4096 }, "anthropic.claude-opus-4-6-v1": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 6.25e-06, @@ -1073,6 +1076,7 @@ "prompt_cache_min_tokens": 4096 }, "global.anthropic.claude-opus-4-6-v1": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 6.25e-06, @@ -1108,6 +1112,7 @@ "prompt_cache_min_tokens": 4096 }, "us.anthropic.claude-opus-4-6-v1": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 6.875e-06, @@ -1143,6 +1148,7 @@ "prompt_cache_min_tokens": 4096 }, "eu.anthropic.claude-opus-4-6-v1": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 6.875e-06, @@ -1178,6 +1184,7 @@ "prompt_cache_min_tokens": 4096 }, "au.anthropic.claude-opus-4-6-v1": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 6.875e-06, @@ -2257,6 +2264,7 @@ "prompt_cache_min_tokens": 1024 }, "anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 3.75e-06, @@ -2291,6 +2299,7 @@ "prompt_cache_min_tokens": 1024 }, "global.anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 3.75e-06, @@ -2325,6 +2334,7 @@ "prompt_cache_min_tokens": 1024 }, "us.anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 4.125e-06, @@ -2359,6 +2369,7 @@ "prompt_cache_min_tokens": 1024 }, "eu.anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 4.125e-06, @@ -2393,6 +2404,7 @@ "prompt_cache_min_tokens": 1024 }, "au.anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 4.125e-06, @@ -2427,6 +2439,7 @@ "prompt_cache_min_tokens": 1024 }, "jp.anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 4.125e-06, @@ -2493,6 +2506,7 @@ "prompt_cache_min_tokens": 1024 }, "anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 3.75e-06, "cache_creation_input_token_cost_above_1hr": 6e-06, "cache_read_input_token_cost": 3e-07, @@ -2761,6 +2775,7 @@ "cache_creation_input_token_cost": 3.125e-07 }, "apac.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.375e-06, "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 1.1e-06, @@ -2849,6 +2864,7 @@ "output_cost_per_second": 0.0 }, "au.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.125e-06, "cache_creation_input_token_cost_above_1hr": 6.6e-06, "cache_read_input_token_cost": 3.3e-07, @@ -11652,6 +11668,7 @@ "cache_creation_input_token_cost": 3.75e-07 }, "bedrock/us-gov-east-1/anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.5e-06, "cache_creation_input_token_cost_above_1hr": 7.2e-06, "cache_read_input_token_cost": 3.6e-07, @@ -11836,6 +11853,7 @@ "cache_creation_input_token_cost": 3.75e-07 }, "bedrock/us-gov-west-1/anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.5e-06, "cache_creation_input_token_cost_above_1hr": 7.2e-06, "cache_read_input_token_cost": 3.6e-07, @@ -17632,6 +17650,7 @@ "prompt_cache_min_tokens": 2048 }, "eu.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.375e-06, "cache_creation_input_token_cost_above_1hr": 2.2e-06, "cache_read_input_token_cost": 1.1e-07, @@ -17850,6 +17869,7 @@ "prompt_cache_min_tokens": 1024 }, "eu.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.125e-06, "cache_creation_input_token_cost_above_1hr": 6.6e-06, "cache_read_input_token_cost": 3.3e-07, @@ -24771,6 +24791,7 @@ "mode": "search" }, "global.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 3.75e-06, "cache_creation_input_token_cost_above_1hr": 6e-06, "cache_read_input_token_cost": 3e-07, @@ -24840,6 +24861,7 @@ "prompt_cache_min_tokens": 1024 }, "global.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.25e-06, "cache_creation_input_token_cost_above_1hr": 2e-06, "cache_read_input_token_cost": 1e-07, @@ -29767,6 +29789,7 @@ "output_cost_per_token": 1.8e-08 }, "jp.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.125e-06, "cache_creation_input_token_cost_above_1hr": 6.6e-06, "cache_read_input_token_cost": 3.3e-07, @@ -29804,6 +29827,7 @@ "output_cost_per_token_batches": 8.25e-06 }, "jp.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.375e-06, "cache_creation_input_token_cost_above_1hr": 2.2e-06, "cache_read_input_token_cost": 1.1e-07, @@ -39504,6 +39528,7 @@ "prompt_cache_min_tokens": 2048 }, "us.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.375e-06, "cache_creation_input_token_cost_above_1hr": 2.2e-06, "cache_read_input_token_cost": 1.1e-07, @@ -39663,6 +39688,7 @@ "prompt_cache_min_tokens": 1024 }, "us.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.125e-06, "cache_creation_input_token_cost_above_1hr": 6.6e-06, "cache_read_input_token_cost": 3.3e-07, @@ -39700,6 +39726,7 @@ "output_cost_per_token_batches": 8.25e-06 }, "us-gov.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.5e-06, "cache_creation_input_token_cost_above_1hr": 7.2e-06, "cache_read_input_token_cost": 3.6e-07, @@ -39730,6 +39757,7 @@ "prompt_cache_min_tokens": 1024 }, "au.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.375e-06, "cache_creation_input_token_cost_above_1hr": 2.2e-06, "cache_read_input_token_cost": 1.1e-07, @@ -50840,6 +50868,7 @@ "source": "https://aws.amazon.com/bedrock/pricing/" }, "bedrock/us-gov-east-1/anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.5e-06, "cache_creation_input_token_cost_above_1hr": 2.4e-06, "cache_read_input_token_cost": 1.2e-07, @@ -50866,6 +50895,7 @@ "prompt_cache_min_tokens": 4096 }, "bedrock/us-gov-west-1/anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.5e-06, "cache_creation_input_token_cost_above_1hr": 2.4e-06, "cache_read_input_token_cost": 1.2e-07, diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 718e6c489fd..3a3ca4c3cfa 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -756,6 +756,7 @@ "prompt_cache_min_tokens": 2048 }, "anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.25e-06, "cache_creation_input_token_cost_above_1hr": 2e-06, "cache_read_input_token_cost": 1e-07, @@ -784,6 +785,7 @@ "output_cost_per_token_batches": 2.5e-06 }, "anthropic.claude-haiku-4-5@20251001": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.25e-06, "cache_creation_input_token_cost_above_1hr": 2e-06, "cache_read_input_token_cost": 1e-07, @@ -1038,6 +1040,7 @@ "prompt_cache_min_tokens": 4096 }, "anthropic.claude-opus-4-6-v1": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 6.25e-06, @@ -1073,6 +1076,7 @@ "prompt_cache_min_tokens": 4096 }, "global.anthropic.claude-opus-4-6-v1": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 6.25e-06, @@ -1108,6 +1112,7 @@ "prompt_cache_min_tokens": 4096 }, "us.anthropic.claude-opus-4-6-v1": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 6.875e-06, @@ -1143,6 +1148,7 @@ "prompt_cache_min_tokens": 4096 }, "eu.anthropic.claude-opus-4-6-v1": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 6.875e-06, @@ -1178,6 +1184,7 @@ "prompt_cache_min_tokens": 4096 }, "au.anthropic.claude-opus-4-6-v1": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 6.875e-06, @@ -2257,6 +2264,7 @@ "prompt_cache_min_tokens": 1024 }, "anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 3.75e-06, @@ -2291,6 +2299,7 @@ "prompt_cache_min_tokens": 1024 }, "global.anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 3.75e-06, @@ -2325,6 +2334,7 @@ "prompt_cache_min_tokens": 1024 }, "us.anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 4.125e-06, @@ -2359,6 +2369,7 @@ "prompt_cache_min_tokens": 1024 }, "eu.anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 4.125e-06, @@ -2393,6 +2404,7 @@ "prompt_cache_min_tokens": 1024 }, "au.anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 4.125e-06, @@ -2427,6 +2439,7 @@ "prompt_cache_min_tokens": 1024 }, "jp.anthropic.claude-sonnet-4-6": { + "bedrock_converse_supports_strict_tools": false, "supports_adaptive_thinking": true, "supports_legacy_thinking": true, "cache_creation_input_token_cost": 4.125e-06, @@ -2493,6 +2506,7 @@ "prompt_cache_min_tokens": 1024 }, "anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 3.75e-06, "cache_creation_input_token_cost_above_1hr": 6e-06, "cache_read_input_token_cost": 3e-07, @@ -2761,6 +2775,7 @@ "cache_creation_input_token_cost": 3.125e-07 }, "apac.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.375e-06, "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 1.1e-06, @@ -2849,6 +2864,7 @@ "output_cost_per_second": 0.0 }, "au.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.125e-06, "cache_creation_input_token_cost_above_1hr": 6.6e-06, "cache_read_input_token_cost": 3.3e-07, @@ -11652,6 +11668,7 @@ "cache_creation_input_token_cost": 3.75e-07 }, "bedrock/us-gov-east-1/anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.5e-06, "cache_creation_input_token_cost_above_1hr": 7.2e-06, "cache_read_input_token_cost": 3.6e-07, @@ -11836,6 +11853,7 @@ "cache_creation_input_token_cost": 3.75e-07 }, "bedrock/us-gov-west-1/anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.5e-06, "cache_creation_input_token_cost_above_1hr": 7.2e-06, "cache_read_input_token_cost": 3.6e-07, @@ -17632,6 +17650,7 @@ "prompt_cache_min_tokens": 2048 }, "eu.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.375e-06, "cache_creation_input_token_cost_above_1hr": 2.2e-06, "cache_read_input_token_cost": 1.1e-07, @@ -17850,6 +17869,7 @@ "prompt_cache_min_tokens": 1024 }, "eu.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.125e-06, "cache_creation_input_token_cost_above_1hr": 6.6e-06, "cache_read_input_token_cost": 3.3e-07, @@ -24771,6 +24791,7 @@ "mode": "search" }, "global.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 3.75e-06, "cache_creation_input_token_cost_above_1hr": 6e-06, "cache_read_input_token_cost": 3e-07, @@ -24840,6 +24861,7 @@ "prompt_cache_min_tokens": 1024 }, "global.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.25e-06, "cache_creation_input_token_cost_above_1hr": 2e-06, "cache_read_input_token_cost": 1e-07, @@ -29767,6 +29789,7 @@ "output_cost_per_token": 1.8e-08 }, "jp.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.125e-06, "cache_creation_input_token_cost_above_1hr": 6.6e-06, "cache_read_input_token_cost": 3.3e-07, @@ -29804,6 +29827,7 @@ "output_cost_per_token_batches": 8.25e-06 }, "jp.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.375e-06, "cache_creation_input_token_cost_above_1hr": 2.2e-06, "cache_read_input_token_cost": 1.1e-07, @@ -39504,6 +39528,7 @@ "prompt_cache_min_tokens": 2048 }, "us.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.375e-06, "cache_creation_input_token_cost_above_1hr": 2.2e-06, "cache_read_input_token_cost": 1.1e-07, @@ -39663,6 +39688,7 @@ "prompt_cache_min_tokens": 1024 }, "us.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.125e-06, "cache_creation_input_token_cost_above_1hr": 6.6e-06, "cache_read_input_token_cost": 3.3e-07, @@ -39700,6 +39726,7 @@ "output_cost_per_token_batches": 8.25e-06 }, "us-gov.anthropic.claude-sonnet-4-5-20250929-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 4.5e-06, "cache_creation_input_token_cost_above_1hr": 7.2e-06, "cache_read_input_token_cost": 3.6e-07, @@ -39730,6 +39757,7 @@ "prompt_cache_min_tokens": 1024 }, "au.anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.375e-06, "cache_creation_input_token_cost_above_1hr": 2.2e-06, "cache_read_input_token_cost": 1.1e-07, @@ -50840,6 +50868,7 @@ "source": "https://aws.amazon.com/bedrock/pricing/" }, "bedrock/us-gov-east-1/anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.5e-06, "cache_creation_input_token_cost_above_1hr": 2.4e-06, "cache_read_input_token_cost": 1.2e-07, @@ -50866,6 +50895,7 @@ "prompt_cache_min_tokens": 4096 }, "bedrock/us-gov-west-1/anthropic.claude-haiku-4-5-20251001-v1:0": { + "bedrock_converse_supports_strict_tools": false, "cache_creation_input_token_cost": 1.5e-06, "cache_creation_input_token_cost_above_1hr": 2.4e-06, "cache_read_input_token_cost": 1.2e-07, diff --git a/tests/test_litellm/litellm_core_utils/prompt_templates/test_bedrock_converse_strict_tools_opus_47_48.py b/tests/test_litellm/litellm_core_utils/prompt_templates/test_bedrock_converse_strict_tools_opus_47_48.py index 370ec4b6f60..7834a69632b 100644 --- a/tests/test_litellm/litellm_core_utils/prompt_templates/test_bedrock_converse_strict_tools_opus_47_48.py +++ b/tests/test_litellm/litellm_core_utils/prompt_templates/test_bedrock_converse_strict_tools_opus_47_48.py @@ -5,6 +5,13 @@ Anthropic-compatible validator that rejects ``toolSpec.strict`` even though Anthropic's native API accepts ``strict`` as a top-level tool field. See BerriAI/litellm#31582. +The same validator covers Haiku 4.5, Sonnet 4.5/4.6 and Opus 4.6, which were left +unflagged. Forwarding ``strict: true`` makes it compile the tool schema into a +constrained-decoding grammar, and that grammar rejects ordinary JSON Schema keywords: +a tool carrying ``maxItems`` on an array property comes back as ``For 'array' type, +property 'maxItems' is not supported``. Neither field fails on its own, only the pair. +See BerriAI/litellm#34388. + That per-model gate only covers models whose cost-map entry carries the flag, so a ``strict: false`` that litellm itself synthesized still broke unflagged models. Since ``strict: false`` is the Chat Completions default, it is now dropped for every model @@ -68,12 +75,23 @@ _NON_STRICT_TOOL = [ "bedrock/us.anthropic.claude-sonnet-5", "bedrock/eu.anthropic.claude-sonnet-5", "bedrock/jp.anthropic.claude-sonnet-5", + # Haiku 4.5, Sonnet 4.5/4.6 and Opus 4.6 reject it as well, see #34388 + "anthropic.claude-haiku-4-5-20251001-v1:0", + "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0", + "bedrock/eu.anthropic.claude-haiku-4-5-20251001-v1:0", + "anthropic.claude-sonnet-4-5-20250929-v1:0", + "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "anthropic.claude-sonnet-4-6", + "bedrock/us.anthropic.claude-sonnet-4-6", + "bedrock/eu.anthropic.claude-sonnet-4-6", + "anthropic.claude-opus-4-6-v1", + "bedrock/eu.anthropic.claude-opus-4-6-v1", ], ) def test_bedrock_tools_pt_strict_dropped_for_strict_unsupported_models( model_id: str, ) -> None: - """Opus 4.7/4.8, Sonnet 4 and Sonnet 5 reject toolSpec.strict and additionalProperties.""" + """These Claude ids reject toolSpec.strict and additionalProperties on Converse.""" result = _bedrock_tools_pt(_STRICT_TOOL, model=model_id) tool_spec = result[0]["toolSpec"] assert ( @@ -87,14 +105,12 @@ def test_bedrock_tools_pt_strict_dropped_for_strict_unsupported_models( @pytest.mark.parametrize( "model_id", [ - "anthropic.claude-sonnet-4-5-20250929-v1:0", - "bedrock/us.anthropic.claude-sonnet-4-6", - "bedrock/us.anthropic.claude-opus-4-6", "bedrock/us.anthropic.claude-opus-4-5", + "bedrock/us.anthropic.claude-3-5-sonnet-20241022-v2:0", ], ) def test_bedrock_tools_pt_strict_kept_for_other_anthropic(model_id: str) -> None: - """Sonnet 4.5/4.6 and Opus <=4.6 accept toolSpec.strict — keep forwarding it.""" + """Claude ids with no flag in the cost map keep forwarding toolSpec.strict.""" result = _bedrock_tools_pt(_STRICT_TOOL, model=model_id) assert ( result[0]["toolSpec"]["strict"] is True @@ -177,10 +193,16 @@ def test_bedrock_converse_supports_strict_tools_helper() -> None: bedrock_converse_supports_strict_tools( "anthropic.claude-sonnet-4-5-20250929-v1:0" ) - is True + is False ) assert ( - bedrock_converse_supports_strict_tools("bedrock/us.anthropic.claude-opus-4-6") + bedrock_converse_supports_strict_tools( + "bedrock/eu.anthropic.claude-opus-4-6-v1" + ) + is False + ) + assert ( + bedrock_converse_supports_strict_tools("bedrock/us.anthropic.claude-opus-4-5") is True ) assert bedrock_converse_supports_strict_tools("us.amazon.nova-micro-v1:0") is False @@ -204,8 +226,14 @@ def test_bedrock_converse_supports_strict_tools_helper() -> None: is False ) assert ( - bedrock_converse_supports_strict_tools("bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0") - is True + bedrock_converse_supports_strict_tools( + "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0" + ) + is False + ) + assert ( + bedrock_converse_supports_strict_tools("bedrock/eu.anthropic.claude-sonnet-4-6") + is False ) @@ -227,6 +255,20 @@ def test_bedrock_converse_supports_strict_tools_helper() -> None: "eu.anthropic.claude-sonnet-5", "au.anthropic.claude-sonnet-5", "jp.anthropic.claude-sonnet-5", + "anthropic.claude-haiku-4-5-20251001-v1:0", + "us.anthropic.claude-haiku-4-5-20251001-v1:0", + "eu.anthropic.claude-haiku-4-5-20251001-v1:0", + "apac.anthropic.claude-haiku-4-5-20251001-v1:0", + "bedrock/us-gov-east-1/anthropic.claude-haiku-4-5-20251001-v1:0", + "anthropic.claude-sonnet-4-5-20250929-v1:0", + "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "us-gov.anthropic.claude-sonnet-4-5-20250929-v1:0", + "anthropic.claude-sonnet-4-6", + "us.anthropic.claude-sonnet-4-6", + "eu.anthropic.claude-sonnet-4-6", + "anthropic.claude-opus-4-6-v1", + "us.anthropic.claude-opus-4-6-v1", + "eu.anthropic.claude-opus-4-6-v1", ], ) def test_strict_tools_flag_set_in_model_cost_map(cost_map_key: str) -> None: diff --git a/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py b/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py index 72d26f31c60..8f46970912a 100644 --- a/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py +++ b/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py @@ -982,6 +982,10 @@ def test_bedrock_tools_pt_strict_parameter(): Bedrock requires alongside strict); without forwarding it the model ignores the enum constraint the caller asked for. Every other Bedrock family (Nova, Llama, GPT-OSS) rejects the strict field, so it must only be forwarded for Claude. + + Uses Opus 4.5, since the Claude ids whose cost-map entry sets + ``bedrock_converse_supports_strict_tools: false`` never receive the field. See + test_bedrock_converse_strict_tools_opus_47_48.py for that gate. """ tools_with_strict = [ { @@ -1000,7 +1004,7 @@ def test_bedrock_tools_pt_strict_parameter(): } ] result = _bedrock_tools_pt( - tools_with_strict, model="anthropic.claude-sonnet-4-5-20250929-v1:0" + tools_with_strict, model="anthropic.claude-opus-4-5-20251101-v1:0" ) assert result[0]["toolSpec"]["strict"] is True assert result[0]["toolSpec"]["inputSchema"]["json"]["additionalProperties"] is False @@ -1024,7 +1028,7 @@ def test_bedrock_tools_pt_strict_parameter(): } ] result = _bedrock_tools_pt( - tools_without_strict, model="anthropic.claude-sonnet-4-5-20250929-v1:0" + tools_without_strict, model="anthropic.claude-opus-4-5-20251101-v1:0" ) assert "strict" not in result[0]["toolSpec"] assert "additionalProperties" not in result[0]["toolSpec"]["inputSchema"]["json"]