From bc98c67028235aafd893e607bbe3d09a02ae663b Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Tue, 11 Aug 2026 02:46:27 +0000 Subject: [PATCH 1/3] fix(bedrock): send tool-search beta header for Haiku 4.5 on Invoke /v1/messages Bedrock InvokeModel rejects tool_search_tool_* tool types unless the request body carries the tool-search-tool-2025-10-19 beta. The model allowlist gating that beta omitted Haiku 4.5 (and Opus 4.7, supported since launch per live verification), so every tool-search request on those models got a Bedrock 400. Add both to the allowlist and re-enable the e2e compat cell that caught it. --- .../anthropic_claude3_transformation.py | 29 ++++++----- .../tool_search/test_bedrock_invoke.py | 4 -- .../test_anthropic_claude3_transformation.py | 49 +++++++++++++++++++ 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py index fad7e7558c2f..9a6fdf780906 100644 --- a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py +++ b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py @@ -372,8 +372,9 @@ def _supports_tool_search_on_bedrock(self, model: str) -> bool: """ Check if the model supports tool search on Bedrock. - On Amazon Bedrock, server-side tool search is supported on Claude Opus 4.5 - and Claude Sonnet 4.5 with the tool-search-tool-2025-10-19 beta header. + On Amazon Bedrock, server-side tool search is supported on Claude + Opus 4.5/4.6/4.7, Sonnet 4.5/4.6, and Haiku 4.5 with the + tool-search-tool-2025-10-19 beta header. Ref: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool @@ -407,10 +408,17 @@ def _supports_tool_search_on_bedrock(self, model: str) -> bool: "sonnet_4.6", "sonnet-4-6", "sonnet_4_6", - # NOTE: Opus 4.7 on Bedrock does not support server-side tool search - # as of launch (2026-04-16). Bedrock rejects the tool type with: - # "tool type 'tool_search_tool_..._20251119' is not supported for this model". - # Re-add the opus-4.7 patterns here once AWS announces support. + # Opus 4.7 (unsupported at its 2026-04-16 launch; verified live + # 2026-08-11 that Bedrock now accepts the beta on it) + "opus-4.7", + "opus_4.7", + "opus-4-7", + "opus_4_7", + # Haiku 4.5 + "haiku-4.5", + "haiku_4.5", + "haiku-4-5", + "haiku_4_5", ] return any(pattern in model_lower for pattern in supported_patterns) @@ -426,11 +434,10 @@ def _get_tool_search_beta_header_for_bedrock( """ Adjust tool search beta header for Bedrock. - Bedrock requires a different beta header for tool search on Opus 4 models - when tool search is used without programmatic tool calling or input examples. - - Note: On Amazon Bedrock, server-side tool search is only supported on Claude Opus 4 - with the `tool-search-tool-2025-10-19` beta header. + Bedrock requires a different beta header for tool search than the + Anthropic API when tool search is used without programmatic tool + calling or input examples: `tool-search-tool-2025-10-19`, and only on + the models listed in `_supports_tool_search_on_bedrock`. Ref: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool diff --git a/tests/e2e/claude_code/tool_search/test_bedrock_invoke.py b/tests/e2e/claude_code/tool_search/test_bedrock_invoke.py index 12f8909e3e8f..c4735c78f0ca 100644 --- a/tests/e2e/claude_code/tool_search/test_bedrock_invoke.py +++ b/tests/e2e/claude_code/tool_search/test_bedrock_invoke.py @@ -59,10 +59,6 @@ ] -@pytest.mark.skip( - reason="product bug LIT-4522: Bedrock Invoke /v1/messages does not normalize " - "tool_search_tool_regex_20251119; re-enable when messages path matches chat path" -) @pytest.mark.covers("llm.messages.bedrock_invoke.tool_search.nonstream.works") def test_tool_search_bedrock_invoke(compat_result): """Probe `/v1/messages` with a `tool_search_tool_regex_20251119` diff --git a/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py b/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py index 2d1a5bc4c2a8..67409cc6cd07 100644 --- a/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py +++ b/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py @@ -2474,6 +2474,55 @@ def test_filter_and_transform_beta_headers_passes_context_management_for_bedrock assert out_converse == [] +@pytest.mark.parametrize( + "model", + [ + "us.anthropic.claude-haiku-4-5-20251001-v1:0", + "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "us.anthropic.claude-opus-4-7", + ], +) +def test_bedrock_messages_tool_search_adds_beta_header(local_beta_headers_config, model): + """ + LIT-4522: Bedrock InvokeModel only admits ``tool_search_tool_*`` tool types + when the request body carries the ``tool-search-tool-2025-10-19`` beta; + without it Bedrock 400s with "Input tag 'tool_search_tool_regex_20251119' + ... does not match any of the expected tags". The allowlist in + ``_supports_tool_search_on_bedrock`` previously omitted Haiku 4.5 and + Opus 4.7, so the beta was silently dropped for those models and every + tool-search request failed. Verified live 2026-08-11: Bedrock returns 200 + with ``server_tool_use`` for all three models once the beta is sent. + """ + from litellm.types.router import GenericLiteLLMParams + + cfg = AmazonAnthropicClaudeMessagesConfig() + messages = [{"role": "user", "content": [{"type": "text", "text": "Hi"}]}] + optional_params = { + "max_tokens": 64, + "tools": [ + {"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"}, + { + "name": "add_numbers", + "description": "Add two integers", + "input_schema": { + "type": "object", + "properties": {"a": {"type": "integer"}, "b": {"type": "integer"}}, + "required": ["a", "b"], + }, + }, + ], + } + + result = cfg.transform_anthropic_messages_request( + model=model, + messages=messages, + anthropic_messages_optional_request_params=optional_params, + litellm_params=GenericLiteLLMParams(), + headers={}, + ) + + assert "tool-search-tool-2025-10-19" in (result.get("anthropic_beta") or []) + def test_bedrock_messages_thinking_shape_follows_exact_bedrock_entry_flag( local_model_cost_map, monkeypatch From 7d4488d2e8a9b9c497be95dc5af7cfe547fb72cc Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Tue, 11 Aug 2026 10:06:04 +0000 Subject: [PATCH 2/3] refactor(bedrock): read tool search support from the model map Record supports_tool_search on the Bedrock Claude entries in both cost map files and have _supports_tool_search_on_bedrock read it first via the provider-resolved capability lookup, keeping the name patterns as a fallback for ARNs and ids the map cannot resolve. Threads the flag through ModelInfoBase and drops a dated remark from the pattern list --- .../anthropic_claude3_transformation.py | 14 +++--- ...odel_prices_and_context_window_backup.json | 43 +++++++++++++++++++ litellm/types/utils.py | 1 + litellm/utils.py | 1 + model_prices_and_context_window.json | 43 +++++++++++++++++++ .../test_anthropic_claude3_transformation.py | 36 ++++++++++++++++ 6 files changed, 132 insertions(+), 6 deletions(-) diff --git a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py index 9a6fdf780906..8d039d95bb19 100644 --- a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py +++ b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py @@ -372,9 +372,9 @@ def _supports_tool_search_on_bedrock(self, model: str) -> bool: """ Check if the model supports tool search on Bedrock. - On Amazon Bedrock, server-side tool search is supported on Claude - Opus 4.5/4.6/4.7, Sonnet 4.5/4.6, and Haiku 4.5 with the - tool-search-tool-2025-10-19 beta header. + The model map's ``supports_tool_search`` flag is authoritative when + ``model`` resolves to an entry that sets it; the name patterns below + cover ids the map cannot resolve (ARNs, unlisted regional variants). Ref: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool @@ -384,9 +384,12 @@ def _supports_tool_search_on_bedrock(self, model: str) -> bool: Returns: True if the model supports tool search on Bedrock """ + catalog: Final = AnthropicModelInfo._get_provider_resolved_capability(model, "supports_tool_search", "bedrock") + if catalog is not None: + return catalog + model_lower: Final = model.lower() - # Supported models for tool search on Bedrock supported_patterns: Final = [ # Opus 4.5 "opus-4.5", @@ -408,8 +411,7 @@ def _supports_tool_search_on_bedrock(self, model: str) -> bool: "sonnet_4.6", "sonnet-4-6", "sonnet_4_6", - # Opus 4.7 (unsupported at its 2026-04-16 launch; verified live - # 2026-08-11 that Bedrock now accepts the beta on it) + # Opus 4.7 "opus-4.7", "opus_4.7", "opus-4-7", diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 951c114b0a9d..c8b34927e7d4 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -730,6 +730,7 @@ "cache_read_input_token_cost": 1e-07, "input_cost_per_token": 1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -755,6 +756,7 @@ "cache_read_input_token_cost": 1e-07, "input_cost_per_token": 1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -973,6 +975,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -1005,6 +1008,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1038,6 +1042,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1071,6 +1076,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1104,6 +1110,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1137,6 +1144,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1171,6 +1179,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1222,6 +1231,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1258,6 +1268,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1294,6 +1305,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1330,6 +1342,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1946,6 +1959,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -2203,6 +2217,7 @@ "cache_read_input_token_cost": 3e-07, "input_cost_per_token": 3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2235,6 +2250,7 @@ "cache_read_input_token_cost": 3e-07, "input_cost_per_token": 3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2267,6 +2283,7 @@ "cache_read_input_token_cost": 3.3e-07, "input_cost_per_token": 3.3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2299,6 +2316,7 @@ "cache_read_input_token_cost": 3.3e-07, "input_cost_per_token": 3.3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2331,6 +2349,7 @@ "cache_read_input_token_cost": 3.3e-07, "input_cost_per_token": 3.3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2363,6 +2382,7 @@ "cache_read_input_token_cost": 3.3e-07, "input_cost_per_token": 3.3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2430,6 +2450,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.2e-05, "cache_read_input_token_cost_above_200k_tokens": 6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2686,6 +2707,7 @@ "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 1.1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2775,6 +2797,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.32e-05, "cache_read_input_token_cost_above_200k_tokens": 6.6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -10826,6 +10849,7 @@ "cache_read_input_token_cost": 3.6e-07, "input_cost_per_token": 3.6e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 8192, "max_tokens": 8192, @@ -10850,6 +10874,7 @@ "cache_read_input_token_cost": 3.6e-07, "input_cost_per_token": 3.6e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 8192, "max_tokens": 8192, @@ -11005,6 +11030,7 @@ "cache_read_input_token_cost": 3.6e-07, "input_cost_per_token": 3.6e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 8192, "max_tokens": 8192, @@ -11029,6 +11055,7 @@ "cache_read_input_token_cost": 3.6e-07, "input_cost_per_token": 3.6e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 8192, "max_tokens": 8192, @@ -11811,6 +11838,7 @@ "cache_creation_input_token_cost_above_200k_tokens": 7.5e-06, "cache_read_input_token_cost_above_200k_tokens": 6e-07, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -15998,6 +16026,7 @@ "input_cost_per_token": 1.1e-06, "deprecation_date": "2026-10-15", "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -16213,6 +16242,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.32e-05, "cache_read_input_token_cost_above_200k_tokens": 6.6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -22031,6 +22061,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.2e-05, "cache_read_input_token_cost_above_200k_tokens": 6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -22091,6 +22122,7 @@ "cache_read_input_token_cost": 1e-07, "input_cost_per_token": 1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -26534,6 +26566,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.32e-05, "cache_read_input_token_cost_above_200k_tokens": 6.6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -26563,6 +26596,7 @@ "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 1.1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35259,6 +35293,7 @@ "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 1.1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35417,6 +35452,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.32e-05, "cache_read_input_token_cost_above_200k_tokens": 6.6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35451,6 +35487,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.44e-05, "cache_read_input_token_cost_above_200k_tokens": 7.2e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35475,6 +35512,7 @@ "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 1.1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35525,6 +35563,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35556,6 +35595,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35586,6 +35626,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -45975,6 +46016,7 @@ "cache_read_input_token_cost": 1.2e-07, "input_cost_per_token": 1.2e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -46000,6 +46042,7 @@ "cache_read_input_token_cost": 1.2e-07, "input_cost_per_token": 1.2e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 74311d59d8e2..d0d65c1a6149 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -152,6 +152,7 @@ class ProviderSpecificModelInfo(TypedDict, total=False): supports_web_search: bool | None supports_reasoning: bool | None supports_adaptive_thinking: bool | None + supports_tool_search: bool | None supports_mid_conversation_system: bool | None supports_url_context: bool | None supports_none_reasoning_effort: bool | None diff --git a/litellm/utils.py b/litellm/utils.py index 87937c99a0c9..d534a2e505ba 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -5679,6 +5679,7 @@ def _get_model_info_helper( supports_url_context=_model_info.get("supports_url_context", None), supports_reasoning=_model_info.get("supports_reasoning", None), supports_adaptive_thinking=_model_info.get("supports_adaptive_thinking", None), + supports_tool_search=_model_info.get("supports_tool_search", None), supports_mid_conversation_system=_model_info.get("supports_mid_conversation_system", None), supports_none_reasoning_effort=_model_info.get("supports_none_reasoning_effort", None), supports_minimal_reasoning_effort=_model_info.get("supports_minimal_reasoning_effort", None), diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 951c114b0a9d..c8b34927e7d4 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -730,6 +730,7 @@ "cache_read_input_token_cost": 1e-07, "input_cost_per_token": 1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -755,6 +756,7 @@ "cache_read_input_token_cost": 1e-07, "input_cost_per_token": 1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -973,6 +975,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -1005,6 +1008,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1038,6 +1042,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1071,6 +1076,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1104,6 +1110,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1137,6 +1144,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1171,6 +1179,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1222,6 +1231,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1258,6 +1268,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1294,6 +1305,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1330,6 +1342,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -1946,6 +1959,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 128000, "max_tokens": 128000, @@ -2203,6 +2217,7 @@ "cache_read_input_token_cost": 3e-07, "input_cost_per_token": 3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2235,6 +2250,7 @@ "cache_read_input_token_cost": 3e-07, "input_cost_per_token": 3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2267,6 +2283,7 @@ "cache_read_input_token_cost": 3.3e-07, "input_cost_per_token": 3.3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2299,6 +2316,7 @@ "cache_read_input_token_cost": 3.3e-07, "input_cost_per_token": 3.3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2331,6 +2349,7 @@ "cache_read_input_token_cost": 3.3e-07, "input_cost_per_token": 3.3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2363,6 +2382,7 @@ "cache_read_input_token_cost": 3.3e-07, "input_cost_per_token": 3.3e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 1000000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2430,6 +2450,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.2e-05, "cache_read_input_token_cost_above_200k_tokens": 6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2686,6 +2707,7 @@ "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 1.1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -2775,6 +2797,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.32e-05, "cache_read_input_token_cost_above_200k_tokens": 6.6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -10826,6 +10849,7 @@ "cache_read_input_token_cost": 3.6e-07, "input_cost_per_token": 3.6e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 8192, "max_tokens": 8192, @@ -10850,6 +10874,7 @@ "cache_read_input_token_cost": 3.6e-07, "input_cost_per_token": 3.6e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 8192, "max_tokens": 8192, @@ -11005,6 +11030,7 @@ "cache_read_input_token_cost": 3.6e-07, "input_cost_per_token": 3.6e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 8192, "max_tokens": 8192, @@ -11029,6 +11055,7 @@ "cache_read_input_token_cost": 3.6e-07, "input_cost_per_token": 3.6e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 8192, "max_tokens": 8192, @@ -11811,6 +11838,7 @@ "cache_creation_input_token_cost_above_200k_tokens": 7.5e-06, "cache_read_input_token_cost_above_200k_tokens": 6e-07, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -15998,6 +16026,7 @@ "input_cost_per_token": 1.1e-06, "deprecation_date": "2026-10-15", "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -16213,6 +16242,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.32e-05, "cache_read_input_token_cost_above_200k_tokens": 6.6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -22031,6 +22061,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.2e-05, "cache_read_input_token_cost_above_200k_tokens": 6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -22091,6 +22122,7 @@ "cache_read_input_token_cost": 1e-07, "input_cost_per_token": 1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -26534,6 +26566,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.32e-05, "cache_read_input_token_cost_above_200k_tokens": 6.6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -26563,6 +26596,7 @@ "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 1.1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35259,6 +35293,7 @@ "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 1.1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35417,6 +35452,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.32e-05, "cache_read_input_token_cost_above_200k_tokens": 6.6e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35451,6 +35487,7 @@ "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.44e-05, "cache_read_input_token_cost_above_200k_tokens": 7.2e-07, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35475,6 +35512,7 @@ "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 1.1e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35525,6 +35563,7 @@ "cache_read_input_token_cost": 5.5e-07, "input_cost_per_token": 5.5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35556,6 +35595,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -35586,6 +35626,7 @@ "cache_read_input_token_cost": 5e-07, "input_cost_per_token": 5e-06, "litellm_provider": "bedrock_converse", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -45975,6 +46016,7 @@ "cache_read_input_token_cost": 1.2e-07, "input_cost_per_token": 1.2e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, @@ -46000,6 +46042,7 @@ "cache_read_input_token_cost": 1.2e-07, "input_cost_per_token": 1.2e-06, "litellm_provider": "bedrock", + "supports_tool_search": true, "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, diff --git a/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py b/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py index 67409cc6cd07..02bd3535c0a6 100644 --- a/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py +++ b/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py @@ -2524,6 +2524,42 @@ def test_bedrock_messages_tool_search_adds_beta_header(local_beta_headers_config assert "tool-search-tool-2025-10-19" in (result.get("anthropic_beta") or []) +def test_bedrock_messages_tool_search_model_map_flag_is_authoritative(local_model_cost_map, monkeypatch): + """``supports_tool_search`` lives in the model map; the name patterns in + ``_supports_tool_search_on_bedrock`` are only a fallback for ids the map + cannot resolve. Flipping the mapped entry's flag to ``False`` must win even + though the model name still matches the ``haiku-4-5`` pattern.""" + import litellm + from litellm.llms.anthropic.common_utils import AnthropicModelInfo + + model = "us.anthropic.claude-haiku-4-5-20251001-v1:0" + cfg = AmazonAnthropicClaudeMessagesConfig() + + assert AnthropicModelInfo._get_provider_resolved_capability(model, "supports_tool_search", "bedrock") is True + assert cfg._supports_tool_search_on_bedrock(model) is True + + monkeypatch.setitem(litellm.model_cost[model], "supports_tool_search", False) + litellm.get_model_info.cache_clear() + + assert cfg._supports_tool_search_on_bedrock(model) is False + + +@pytest.mark.parametrize( + "model, expected", + [ + pytest.param("us.anthropic.claude-opus-4-6-v99:9", True, id="unmapped_id_falls_back_to_patterns"), + pytest.param("anthropic.claude-3-5-sonnet-20240620-v1:0", False, id="mapped_entry_without_flag_no_pattern"), + ], +) +def test_bedrock_messages_tool_search_pattern_fallback(local_model_cost_map, model, expected): + """Ids the model map cannot resolve (or resolves without a + ``supports_tool_search`` opinion) fall through to the name patterns, so + ARNs and unlisted regional variants of supported families keep working.""" + cfg = AmazonAnthropicClaudeMessagesConfig() + + assert cfg._supports_tool_search_on_bedrock(model) is expected + + def test_bedrock_messages_thinking_shape_follows_exact_bedrock_entry_flag( local_model_cost_map, monkeypatch ): From df5425675e2877fa3100e4d2f1b4c1e98a3b4afb Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Tue, 11 Aug 2026 15:16:31 +0000 Subject: [PATCH 3/3] fix(schema): declare supports_tool_search in the model prices schemas --- model_prices_and_context_window.schema.json | 3 +++ tests/test_litellm/test_utils.py | 1 + 2 files changed, 4 insertions(+) diff --git a/model_prices_and_context_window.schema.json b/model_prices_and_context_window.schema.json index 882f514b1991..56400e0666b0 100644 --- a/model_prices_and_context_window.schema.json +++ b/model_prices_and_context_window.schema.json @@ -671,6 +671,9 @@ "supports_tool_choice": { "type": "boolean" }, + "supports_tool_search": { + "type": "boolean" + }, "supports_url_context": { "type": "boolean" }, diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index ed5a9f1dd63c..acd8ef4c96c5 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -921,6 +921,7 @@ def test_aaamodel_prices_and_context_window_json_is_valid(): "supports_response_schema": {"type": "boolean"}, "supports_system_messages": {"type": "boolean"}, "supports_tool_choice": {"type": "boolean"}, + "supports_tool_search": {"type": "boolean"}, "supports_video_input": {"type": "boolean"}, "supports_vision": {"type": "boolean"}, "supports_web_search": {"type": "boolean"},