fix(bedrock): preserve output_config.effort for Claude 4.6 on Invoke API#23971
fix(bedrock): preserve output_config.effort for Claude 4.6 on Invoke API#23971KevinZhao wants to merge 1 commit intoBerriAI:mainfrom
Conversation
…Invoke API Bedrock Invoke previously stripped `output_config` unconditionally for all models. Claude 4.6 (Opus/Sonnet) supports `output_config.effort` as a stable API parameter for controlling adaptive thinking effort level. This change makes the stripping conditional: preserve `output_config` for Claude 4.6+ models, continue stripping for older models to avoid request rejection. Fixes both entry points: - /v1/chat/completions → Bedrock Invoke (chat path) - /v1/messages → Bedrock Invoke (messages path) Also adds "max" to the AnthropicOutputConfig effort Literal type, as effort="max" is supported by Claude Opus 4.6.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR makes the Bedrock Invoke API's Key changes:
Concern:
Confidence Score: 2/5
|
| Filename | Overview |
|---|---|
| litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py | Conditionally preserves output_config for Claude 4.6 models using _is_claude_4_6_model — a hardcoded string check that violates the project rule against model-specific flags outside model_prices_and_context_window.json. |
| litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py | Same hardcoded _is_claude_4_6_model violation as the chat path; additionally the comment numbering (5b appears before 5a) is inverted. |
| litellm/types/llms/anthropic.py | Adds "max" to the AnthropicOutputConfig.effort Literal — a straightforward type-system fix that is accurate and non-breaking. |
| tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py | Adds well-structured unit tests for both preservation and stripping paths; all calls are mocked (no real network calls). |
| tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py | Adds equivalent coverage for the messages Invoke path; tests are mock-only and complete. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["litellm /v1/chat/completions or /v1/messages\n(with output_config.effort)"] --> B{Bedrock Invoke\ntransformation}
B --> C{_is_claude_4_6_model?}
C -- "Yes (Opus/Sonnet 4.6)" --> D["Keep output_config\nin request body"]
C -- "No (pre-4.6)" --> E["Pop output_config\nfrom request body"]
D --> F["Bedrock Invoke API\n→ effort forwarded"]
E --> G["Bedrock Invoke API\n→ effort stripped"]
style D fill:#c8f7c5,stroke:#27ae60
style E fill:#fdecea,stroke:#e74c3c
style C fill:#fef9e7,stroke:#f39c12
Last reviewed commit: "fix(bedrock): preser..."
| if not AnthropicConfig._is_claude_4_6_model(model): | ||
| _anthropic_request.pop("output_config", None) |
There was a problem hiding this comment.
Hardcoded model check violates AGENTS.md rule #8
_is_claude_4_6_model is a hardcoded string-match check. Per the project's custom rule and AGENTS.md §8 ("Do not hardcode model-specific flags"), model capability decisions must be driven by model_prices_and_context_window.json read via get_model_info (or an existing helper like supports_reasoning). Without this, any future model that gains output_config.effort support on Bedrock Invoke requires a code change here before users benefit — exactly the problem the rule was written to avoid.
All Claude 4.6 models already carry "supports_reasoning": true in the model-prices JSON, so supports_reasoning (or a new supports_output_config_effort flag added to the JSON) could drive this decision without touching the code for future models.
# Option A — reuse existing supports_reasoning helper (reads from model_prices_and_context_window.json)
from litellm.utils import supports_reasoning
if not (AnthropicConfig._is_claude_4_6_model(model) or supports_reasoning(model=model, custom_llm_provider=self.custom_llm_provider)):
_anthropic_request.pop("output_config", None)This same violation also exists at litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py:425.
Rule Used: What: Do not hardcode model-specific flags in the ... (source)
| if not AnthropicModelInfo._is_claude_4_6_model(model): | ||
| anthropic_messages_request.pop("output_config", None) | ||
|
|
||
| # 5a. Remove `custom` field from tools (Bedrock doesn't support it) |
There was a problem hiding this comment.
Comment numbering out of order (5b before 5a)
The comment label # 5b. on line 422 appears in the file before # 5a. on line 428, which reverses the expected ordering and makes the numbering misleading when reading the code sequentially.
| # 5a. Remove `custom` field from tools (Bedrock doesn't support it) | |
| # 5a. Remove `custom` field from tools (Bedrock doesn't support it) |
|
CLA signed |
Summary
Bedrock Invoke API previously stripped
output_configunconditionally for all models (#22797). However, Claude 4.6 models (Opus 4.6 and Sonnet 4.6) supportoutput_config.effortas a stable API parameter for controlling adaptive thinking effort level.This PR makes the stripping conditional:
output_configsoeffort(low/medium/high/max) is forwarded to Bedrockoutput_configto avoid request rejectionChanges
litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py— conditionaloutput_configpop for/v1/chat/completions→ Bedrock Invoke pathlitellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py— same for/v1/messages→ Bedrock Invoke pathlitellm/types/llms/anthropic.py— add"max"toAnthropicOutputConfig.effortLiteral type (Opus 4.6 exclusive)Test plan
test_bedrock_chat_invoke_preserves_output_config_for_claude_4_6— Sonnet 4.6 effort=high, Opus 4.6 effort=maxtest_bedrock_chat_invoke_strips_output_config_for_pre_4_6— Sonnet 4.5, Opus 4.5test_bedrock_messages_preserves_output_config_for_claude_4_6— Opus 4.6 effort=max, Sonnet 4.6 effort=hightest_bedrock_messages_strips_output_config_for_pre_4_6— Claude 3 Haiku, Sonnet 4, Opus 4.5test_output_config_removed_from_bedrock_chat_invoke_requeststill passes (regression)