fix: filter unsupported beta headers for Bedrock Invoke API (#19877)

- Add whitelist-based filtering for anthropic_beta headers
- Only allow Bedrock-supported beta flags (computer-use, tool-search, etc.)
- Filter out unsupported flags like mcp-servers, structured-outputs
- Remove output_format parameter from Bedrock Invoke requests
- Force tool-based structured outputs when response_format is used

Fixes #16726
This commit is contained in:
Jay Prajapati 2026-01-28 07:17:27 +05:30 committed by GitHub
parent 54a83e75cc
commit 4717f742eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 141 additions and 1 deletions

View file

@ -53,13 +53,26 @@ class AmazonAnthropicClaudeConfig(AmazonInvokeConfig, AnthropicConfig):
model: str,
drop_params: bool,
) -> dict:
return AnthropicConfig.map_openai_params(
# Force tool-based structured outputs for Bedrock Invoke
# (similar to VertexAI fix in #19201)
# Bedrock Invoke doesn't support output_format parameter
original_model = model
if "response_format" in non_default_params:
# Use a model name that forces tool-based approach
model = "claude-3-sonnet-20240229"
optional_params = AnthropicConfig.map_openai_params(
self,
non_default_params,
optional_params,
model,
drop_params,
)
# Restore original model name
model = original_model
return optional_params
def transform_request(
@ -90,6 +103,8 @@ class AmazonAnthropicClaudeConfig(AmazonInvokeConfig, AnthropicConfig):
_anthropic_request.pop("model", None)
_anthropic_request.pop("stream", None)
# Bedrock Invoke doesn't support output_format parameter
_anthropic_request.pop("output_format", None)
if "anthropic_version" not in _anthropic_request:
_anthropic_request["anthropic_version"] = self.anthropic_version
@ -117,6 +132,26 @@ class AmazonAnthropicClaudeConfig(AmazonInvokeConfig, AnthropicConfig):
if "opus-4" in model.lower() or "opus_4" in model.lower():
beta_set.add("tool-search-tool-2025-10-19")
# Filter out beta headers that Bedrock Invoke doesn't support
# AWS Bedrock only supports a specific whitelist of beta flags
# Reference: https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages-request-response.html
BEDROCK_SUPPORTED_BETAS = {
"computer-use-2024-10-22", # Legacy computer use
"computer-use-2025-01-24", # Current computer use (Claude 3.7 Sonnet)
"token-efficient-tools-2025-02-19", # Tool use (Claude 3.7+ and Claude 4+)
"interleaved-thinking-2025-05-14", # Interleaved thinking (Claude 4+)
"output-128k-2025-02-19", # 128K output tokens (Claude 3.7 Sonnet)
"dev-full-thinking-2025-05-14", # Developer mode for raw thinking (Claude 4+)
"context-1m-2025-08-07", # 1 million tokens (Claude Sonnet 4)
"context-management-2025-06-27", # Context management (Claude Sonnet/Haiku 4.5)
"effort-2025-11-24", # Effort parameter (Claude Opus 4.5)
"tool-search-tool-2025-10-19", # Tool search (Claude Opus 4.5)
"tool-examples-2025-10-29", # Tool use examples (Claude Opus 4.5)
}
# Only keep beta headers that Bedrock supports
beta_set = {beta for beta in beta_set if beta in BEDROCK_SUPPORTED_BETAS}
if beta_set:
_anthropic_request["anthropic_beta"] = list(beta_set)

View file

@ -464,3 +464,108 @@ def test_opus_4_5_model_detection():
for model in non_opus_4_5_models:
assert not config._is_claude_opus_4_5(model), \
f"Should not detect {model} as Opus 4.5"
def test_structured_outputs_beta_header_filtered_for_bedrock_invoke():
"""
Test that unsupported beta headers are filtered out for Bedrock Invoke API.
Bedrock Invoke API only supports a specific whitelist of beta flags and returns
"invalid beta flag" error for others (e.g., structured-outputs, mcp-servers).
This test ensures unsupported headers are filtered while keeping supported ones.
Fixes: https://github.com/BerriAI/litellm/issues/16726
"""
config = AmazonAnthropicClaudeConfig()
messages = [{"role": "user", "content": "test"}]
# Test 1: structured-outputs beta header (unsupported)
headers = {"anthropic-beta": "structured-outputs-2025-11-13"}
result = config.transform_request(
model="anthropic.claude-4-0-sonnet-20250514-v1:0",
messages=messages,
optional_params={},
litellm_params={},
headers=headers,
)
# Verify structured-outputs beta is filtered out
anthropic_beta = result.get("anthropic_beta", [])
assert not any("structured-outputs" in beta for beta in anthropic_beta), \
f"structured-outputs beta should be filtered, got: {anthropic_beta}"
# Test 2: mcp-servers beta header (unsupported - the main issue from #16726)
headers = {"anthropic-beta": "mcp-servers-2025-12-04"}
result = config.transform_request(
model="anthropic.claude-4-0-sonnet-20250514-v1:0",
messages=messages,
optional_params={},
litellm_params={},
headers=headers,
)
# Verify mcp-servers beta is filtered out
anthropic_beta = result.get("anthropic_beta", [])
assert not any("mcp-servers" in beta for beta in anthropic_beta), \
f"mcp-servers beta should be filtered, got: {anthropic_beta}"
# Test 3: Mix of supported and unsupported beta headers
headers = {"anthropic-beta": "computer-use-2024-10-22,mcp-servers-2025-12-04,structured-outputs-2025-11-13"}
result = config.transform_request(
model="anthropic.claude-4-0-sonnet-20250514-v1:0",
messages=messages,
optional_params={},
litellm_params={},
headers=headers,
)
# Verify only supported betas are kept
anthropic_beta = result.get("anthropic_beta", [])
assert not any("structured-outputs" in beta for beta in anthropic_beta), \
f"structured-outputs beta should be filtered, got: {anthropic_beta}"
assert not any("mcp-servers" in beta for beta in anthropic_beta), \
f"mcp-servers beta should be filtered, got: {anthropic_beta}"
assert any("computer-use" in beta for beta in anthropic_beta), \
f"computer-use beta should be kept, got: {anthropic_beta}"
def test_output_format_removed_from_bedrock_invoke_request():
"""
Test that output_format parameter is removed from Bedrock Invoke requests.
Bedrock Invoke API doesn't support the output_format parameter (only supported
in Anthropic Messages API). This test ensures it's removed to prevent errors.
"""
config = AmazonAnthropicClaudeConfig()
messages = [{"role": "user", "content": "test"}]
# Create a request with output_format via map_openai_params
non_default_params = {
"response_format": {"type": "json_object"}
}
optional_params = {}
# This should trigger tool-based structured outputs
optional_params = config.map_openai_params(
non_default_params=non_default_params,
optional_params=optional_params,
model="anthropic.claude-4-0-sonnet-20250514-v1:0",
drop_params=False,
)
result = config.transform_request(
model="anthropic.claude-4-0-sonnet-20250514-v1:0",
messages=messages,
optional_params=optional_params,
litellm_params={},
headers={},
)
# Verify output_format is not in the request
assert "output_format" not in result, \
f"output_format should be removed for Bedrock Invoke, got keys: {result.keys()}"