From 5708d79e2bad1b68ca8b62df36600274cecc1d7e Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Fri, 6 Feb 2026 17:45:45 +0530 Subject: [PATCH] Add update_headers_with_filtered_beta in all messages API providers --- .../llms/azure_ai/anthropic/transformation.py | 9 ++++ .../bedrock/chat/converse_transformation.py | 35 ++++++++++++- .../anthropic_claude3_transformation.py | 52 +++++++++++++------ .../transformation.py | 10 +++- 4 files changed, 86 insertions(+), 20 deletions(-) diff --git a/litellm/llms/azure_ai/anthropic/transformation.py b/litellm/llms/azure_ai/anthropic/transformation.py index 2d8d3b987c7..753bc9c08eb 100644 --- a/litellm/llms/azure_ai/anthropic/transformation.py +++ b/litellm/llms/azure_ai/anthropic/transformation.py @@ -3,6 +3,9 @@ Azure Anthropic transformation config - extends AnthropicConfig with Azure authe """ from typing import TYPE_CHECKING, Dict, List, Optional, Union +from litellm.anthropic_beta_headers_manager import ( + update_headers_with_filtered_beta, +) from litellm.llms.anthropic.chat.transformation import AnthropicConfig from litellm.llms.azure.common_utils import BaseAzureLLM from litellm.types.llms.openai import AllMessageValues @@ -87,6 +90,12 @@ class AzureAnthropicConfig(AnthropicConfig): if "anthropic-version" not in headers: headers["anthropic-version"] = "2023-06-01" + # Filter out unsupported beta headers for Azure AI + headers = update_headers_with_filtered_beta( + headers=headers, + provider="azure_ai", + ) + return headers def transform_request( diff --git a/litellm/llms/bedrock/chat/converse_transformation.py b/litellm/llms/bedrock/chat/converse_transformation.py index a48f0298ddb..5ab52446a77 100644 --- a/litellm/llms/bedrock/chat/converse_transformation.py +++ b/litellm/llms/bedrock/chat/converse_transformation.py @@ -11,6 +11,9 @@ import httpx import litellm from litellm._logging import verbose_logger +from litellm.anthropic_beta_headers_manager import ( + filter_and_transform_beta_headers, +) from litellm.constants import RESPONSE_FORMAT_TOOL_NAME from litellm.litellm_core_utils.core_helpers import ( filter_exceptions_from_params, @@ -1031,7 +1034,28 @@ class AmazonConverseConfig(BaseConfig): # Add computer use tools and anthropic_beta if needed (only when computer use tools are present) if computer_use_tools: - anthropic_beta_list.append("computer-use-2024-10-22") + # Determine the correct computer-use beta header based on model + # "computer-use-2025-11-24" for Claude Opus 4.6, Claude Opus 4.5 + # "computer-use-2025-01-24" for Claude Sonnet 4.5, Haiku 4.5, Opus 4.1, Sonnet 4, Opus 4, and Sonnet 3.7 + # "computer-use-2024-10-22" for older models + model_lower = model.lower() + if "opus-4.6" in model_lower or "opus_4.6" in model_lower or "opus-4-6" in model_lower or "opus_4_6" in model_lower: + computer_use_header = "computer-use-2025-11-24" + elif "opus-4.5" in model_lower or "opus_4.5" in model_lower or "opus-4-5" in model_lower or "opus_4_5" in model_lower: + computer_use_header = "computer-use-2025-11-24" + elif any(pattern in model_lower for pattern in [ + "sonnet-4.5", "sonnet_4.5", "sonnet-4-5", "sonnet_4_5", + "haiku-4.5", "haiku_4.5", "haiku-4-5", "haiku_4_5", + "opus-4.1", "opus_4.1", "opus-4-1", "opus_4_1", + "sonnet-4", "sonnet_4", + "opus-4", "opus_4", + "sonnet-3.7", "sonnet_3.7", "sonnet-3-7", "sonnet_3_7" + ]): + computer_use_header = "computer-use-2025-01-24" + else: + computer_use_header = "computer-use-2024-10-22" + + anthropic_beta_list.append(computer_use_header) # Transform computer use tools to proper Bedrock format transformed_computer_tools = self._transform_computer_use_tools( computer_use_tools @@ -1053,7 +1077,14 @@ class AmazonConverseConfig(BaseConfig): if beta not in seen: unique_betas.append(beta) seen.add(beta) - additional_request_params["anthropic_beta"] = unique_betas + + filtered_betas = filter_and_transform_beta_headers( + beta_headers=unique_betas, + provider="bedrock_converse", + ) + + if filtered_betas: + additional_request_params["anthropic_beta"] = filtered_betas return bedrock_tools, anthropic_beta_list 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 a7065caece2..961158bf053 100644 --- a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py +++ b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py @@ -12,6 +12,9 @@ from typing import ( import httpx +from litellm.anthropic_beta_headers_manager import ( + filter_and_transform_beta_headers, +) from litellm.llms.anthropic.common_utils import AnthropicModelInfo from litellm.llms.anthropic.experimental_pass_through.messages.transformation import ( AnthropicMessagesConfig, @@ -52,9 +55,6 @@ class AmazonAnthropicClaudeMessagesConfig( # Beta header patterns that are not supported by Bedrock Invoke API # These will be filtered out to prevent 400 "invalid beta flag" errors - UNSUPPORTED_BEDROCK_INVOKE_BETA_PATTERNS = [ - "advanced-tool-use", # Bedrock Invoke doesn't support advanced-tool-use beta headers - ] def __init__(self, **kwargs): BaseAnthropicMessagesConfig.__init__(self, **kwargs) @@ -179,30 +179,48 @@ class AmazonAnthropicClaudeMessagesConfig( model: The model name beta_set: The set of beta headers to filter in-place """ - beta_headers_to_remove = set() - - # 1. Filter out beta headers that are universally unsupported on Bedrock Invoke - for beta in beta_set: - for unsupported_pattern in self.UNSUPPORTED_BEDROCK_INVOKE_BETA_PATTERNS: - if unsupported_pattern in beta.lower(): - beta_headers_to_remove.add(beta) - break - - # 2. Filter out extended thinking headers for models that don't support them + # 1. Handle header transformations BEFORE filtering + # (advanced-tool-use -> tool-search-tool) + # This must happen before filtering because advanced-tool-use is in the unsupported list + has_advanced_tool_use = "advanced-tool-use-2025-11-20" in beta_set + if has_advanced_tool_use and self._supports_tool_search_on_bedrock(model): + beta_set.discard("advanced-tool-use-2025-11-20") + beta_set.add("tool-search-tool-2025-10-19") + beta_set.add("tool-examples-2025-10-29") + + # 2. Apply provider-level filtering using centralized JSON config + beta_list = list(beta_set) + filtered_list = filter_and_transform_beta_headers( + beta_headers=beta_list, + provider="bedrock", + ) + + # Update the set with filtered headers + beta_set.clear() + beta_set.update(filtered_list) + + # 2.1. Handle model-specific exceptions: structured-outputs is only supported on Opus 4.6 + # Re-add structured-outputs if it was in the original set and model is Opus 4.6 + model_lower = model.lower() + is_opus_4_6 = any(pattern in model_lower for pattern in ["opus-4.6", "opus_4.6", "opus-4-6", "opus_4_6"]) + if is_opus_4_6 and "structured-outputs-2025-11-13" in beta_list: + beta_set.add("structured-outputs-2025-11-13") + + # 3. Filter out extended thinking headers for models that don't support them extended_thinking_patterns = [ "extended-thinking", "interleaved-thinking", ] if not self._supports_extended_thinking_on_bedrock(model): + beta_headers_to_remove = set() for beta in beta_set: for pattern in extended_thinking_patterns: if pattern in beta.lower(): beta_headers_to_remove.add(beta) break - - # Remove all filtered headers - for beta in beta_headers_to_remove: - beta_set.discard(beta) + + for beta in beta_headers_to_remove: + beta_set.discard(beta) def _get_tool_search_beta_header_for_bedrock( self, diff --git a/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py b/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py index fc75376c0cb..106983a2642 100644 --- a/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py +++ b/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py @@ -1,5 +1,8 @@ from typing import Any, Dict, List, Optional, Tuple +from litellm.anthropic_beta_headers_manager import ( + update_headers_with_filtered_beta, +) from litellm.llms.anthropic.common_utils import AnthropicModelInfo from litellm.llms.anthropic.experimental_pass_through.messages.transformation import ( AnthropicMessagesConfig, @@ -64,7 +67,6 @@ class VertexAIPartnerModelsAnthropicMessagesConfig(AnthropicMessagesConfig, Vert existing_beta = headers.get("anthropic-beta") if existing_beta: beta_values.update(b.strip() for b in existing_beta.split(",")) - # Check for web search tool for tool in tools: if isinstance(tool, dict) and tool.get("type", "").startswith(ANTHROPIC_HOSTED_TOOLS.WEB_SEARCH.value): @@ -79,6 +81,12 @@ class VertexAIPartnerModelsAnthropicMessagesConfig(AnthropicMessagesConfig, Vert if beta_values: headers["anthropic-beta"] = ",".join(beta_values) + # Filter out unsupported beta headers for Vertex AI + headers = update_headers_with_filtered_beta( + headers=headers, + provider="vertex_ai", + ) + return headers, api_base def get_complete_url(