fix(bedrock): forward output_config.effort for adaptive-thinking Claude - #27040
Closed
mateo-berri wants to merge 1 commit into
Closed
fix(bedrock): forward output_config.effort for adaptive-thinking Claude#27040mateo-berri wants to merge 1 commit into
mateo-berri wants to merge 1 commit into
Conversation
Claude Sonnet 4.6 / Opus 4.6 / Opus 4.7 expose Anthropic's effort parameter through 'output_config.effort' (Messages API and Bedrock Invoke) and through 'additionalModelRequestFields.thinking.effort' (Bedrock Converse). LiteLLM was stripping output_config on every Bedrock route, so Sonnet 4.6 callers saw the effort never reach the wire body. This fix: - Bedrock Invoke /v1/messages: preserve output_config for adaptive-thinking models (Claude 4.6/4.7) and for Opus 4.5 with the effort-2025-11-24 beta header (auto-attached via the existing is_effort_used path). - Bedrock Invoke /completion: same — stop stripping output_config for the supported model set. - Bedrock Converse: fold output_config.effort into thinking.effort and switch reasoning_effort to populate thinking.effort on adaptive-thinking models. output_config itself is still removed before the request signs, matching Bedrock's wire shape. - Map effort-2025-11-24 to itself for 'bedrock' in the beta-headers JSON so the auto-attach for Opus 4.5 isn't dropped on the way out. - Add adaptive-thinking and Opus-4.5-with-beta tests on all three Bedrock routes; haiku/sonnet-4 stays in the strip path.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This was referenced May 2, 2026
Contributor
Author
|
Superceded by #27074 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Relevant issues
Customer report on the LiteLLM Anthropic-via-Bedrock route:
output_config.effortfor Claude Sonnet 4.6 was being silently dropped on every Bedrock surface (Converse and Invoke, /v1/messages and /completion). Tested across v1.83.7, v1.83.14, and v1.84.0 and the parameter never appeared in the wire body.Linear ticket
Resolves LIT-2758
Pre-Submission checklist
tests/test_litellm/directorymake test-unit(136 bedrock unit tests pass locally)@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewType
🐛 Bug Fix
Changes
Bedrock exposes Anthropic's
effortparameter on three routes:/v1/messages(Anthropic Messages API)output_config: {effort: ...}/completion(legacy chat invoke)output_config: {effort: ...}additionalModelRequestFields.thinking.effortAdaptive-thinking models (Claude 4.6 / 4.7) accept
effortnatively with no beta header. Claude Opus 4.5 accepts it on Bedrock Invoke when theeffort-2025-11-24beta is attached.LiteLLM was unconditionally stripping
output_configon every Bedrock route — a defensive measure originally added because pre-4.6 Claude on Bedrock 400s on the field. That defense was correct for older models but caused effort to vanish for Sonnet 4.6 and friends.This change splits the strip behavior by model:
Bedrock Invoke
/v1/messages(AmazonAnthropicClaudeMessagesConfig)_supports_effort_on_bedrockcheck (Claude 4.6/4.7 or Opus 4.5).output_configintact; for everyone else, strip it as before.output_configto theBedrockInvokeAnthropicMessagesRequestTypedDict so the body allowlist preserves it on the supported path. Existing allowlist tests use Haiku and stay green.Bedrock Invoke
/completion(AmazonAnthropicClaudeConfig)_build_bedrock_anthropic_request_base.Bedrock Converse (
AmazonConverseConfig)_fold_output_config_effort_into_thinking: if the caller suppliedoutput_config.efforton an adaptive-thinking model, fold it intothinking.effort(creatingthinking: {type: adaptive, effort: ...}if absent, never overriding an explicit caller value).output_configis then stripped before signing._handle_reasoning_effort_parameterso that on adaptive-thinking models, OpenAIreasoning_effortpopulatesthinking.effort(with type=adaptive) instead of the legacythinking.type=enabled, budget_tokens=...shape.Beta-headers config
effort-2025-11-24to itself forbedrock(wasnull), so the auto-attach inis_effort_used(already triggered byoutput_config.efforton Opus 4.5) is preserved instead of dropped.Tests
test_bedrock_messages_preserves_output_config_for_adaptive_thinking_models— Sonnet 4.6, Opus 4.6, Opus 4.7 (regional + global) all forwardoutput_config, no beta header.test_bedrock_messages_preserves_output_config_for_opus_4_5_with_beta— Opus 4.5 forwardsoutput_configand auto-attaches theeffort-2025-11-24beta.test_output_config_preserved_for_adaptive_thinking_on_bedrock_invokeandtest_output_config_preserved_for_opus_4_5_on_bedrock_invoke— same coverage on /completion.test_converse_folds_output_config_effort_into_thinking_for_46,test_converse_folds_output_config_effort_preserves_existing_thinking,test_converse_reasoning_effort_sets_thinking_effort_for_46— Converse fold path with explicit-thinking precedence.Existing strip-output_config tests (Haiku, Sonnet 4, Nova) all stay green and still assert removal — the model-aware split keeps behavior unchanged for unsupported models.
Note on the documentation question
The reporter also flagged that on the OpenAI-compatible route,
reasoning_effortmaps tothinking: {type: "adaptive"}for Claude 4.6+, which was surprising. That mapping is correct (and documented inlitellm/llms/anthropic/chat/transformation.py::_map_reasoning_effortandcommon_utils.py::_is_adaptive_thinking_model) — Anthropic's adaptive thinking is the recommended replacement forbudget_tokenson those models. Documentation lives in the separateBerriAI/litellm-docsrepo and is not modified here, but the docstring on_map_reasoning_effortalready explains the behavior.Slack Thread