fix(bedrock/converse): drop toolSpec.strict for Opus 4.7/4.8 (#31582) - #31585
fix(bedrock/converse): drop toolSpec.strict for Opus 4.7/4.8 (#31582)#31585ly-wang19 wants to merge 2 commits into
Conversation
Bedrock Converse routes Claude Opus 4.7/4.8 through an Anthropic-compatible
validator that maps toolSpec to the native tool shape and rejects the extra
`strict` key with `tools.N.custom.strict: Extra inputs are not permitted`,
even though Anthropic's native API accepts `strict` as a top-level tool field
for the same models. Sonnet 4.5/4.6 and Opus <=4.6 accept `toolSpec.strict`
unchanged.
The existing gate `get_bedrock_base_model(model).startswith("anthropic")`
(introduced in BerriAI#29814 to forward `strict` for Claude on Bedrock Converse) is
too broad and regressed Opus 4.7/4.8 callers — see BerriAI#31582.
Replace the inline check with a small `bedrock_converse_supports_strict_tools`
helper that excludes the Opus 4.7/4.8 family from strict forwarding. All
other Anthropic models on Bedrock keep the existing behavior.
Closes BerriAI#31582.
|
|
Greptile SummaryThis PR adds a targeted exclusion so that
Confidence Score: 5/5Safe to merge — the change is a narrow, well-tested exclusion that restores pre-regression behaviour for Opus 4.7/4.8 without touching any other code path. The fix is a single-function swap in factory.py backed by a clearly scoped helper. The regression test covers all meaningful model-ID spellings for both the excluded (Opus 4.7/4.8) and preserved (Sonnet/Opus ≤4.6, non-Anthropic) paths. No existing tests were weakened, and the change has no impact on routing, auth, or any other critical path. No files require special attention beyond
|
| Filename | Overview |
|---|---|
| litellm/llms/bedrock/common_utils.py | Adds bedrock_converse_supports_strict_tools() helper with a hardcoded tuple of Opus 4.7/4.8 model name patterns to gate toolSpec.strict forwarding; logic is correct and well-documented. |
| litellm/litellm_core_utils/prompt_templates/factory.py | Single-line swap of get_bedrock_base_model(model).startswith("anthropic") for the new bedrock_converse_supports_strict_tools(model) helper — minimal, correct change. |
| tests/test_litellm/litellm_core_utils/prompt_templates/test_bedrock_converse_strict_tools_opus_47_48.py | New regression test file covering Opus 4.7/4.8 strict-drop, Sonnet/Opus ≤4.6 strict-keep, and non-Anthropic drop — pure unit tests with no network calls. |
Reviews (2): Last reviewed commit: "fix(bedrock/converse): move strict-tools..." | Re-trigger Greptile
| _BEDROCK_CONVERSE_STRICT_REJECTED_OPUS_PATTERNS = ( | ||
| "claude-opus-4-7", | ||
| "claude_opus_4_7", | ||
| "claude-opus-4.7", | ||
| "claude_opus_4.7", | ||
| "claude-opus-4-8", | ||
| "claude_opus_4_8", | ||
| "claude-opus-4.8", | ||
| "claude_opus_4.8", | ||
| ) |
There was a problem hiding this comment.
Move capability data
This adds another hardcoded model-specific capability list for Bedrock strict support. The repo rule asks these flags to live in model_prices_and_context_window.json and be read via model info; keeping claude-opus-4-7 / 4-8 in code means the next Bedrock validator exception requires a LiteLLM release instead of a model-data update.
Rule Used: What: Do not hardcode model-specific flags in the ... (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
The original regression test was added to test_litellm_core_utils_prompt_templates_factory.py, which has pre-existing ruff-format violations throughout (multi-line asserts that fit on one line). The lint workflow runs `ruff format --check` on changed files only, so touching that file surfaces those pre-existing violations and fails CI for unrelated reasons. Move the BerriAI#31582 regression coverage into a new dedicated test file so the format check stays green. Also collapses the helper's `not any(...)` onto a single line to satisfy ruff format. Covers: BerriAI#31582
|
Thanks for the PR! I'll make a quick copy branch to test this on internal e2e tests |
|
This has been merged. Thank you again for your contribution! |
What Problem This Solves
Closes #31582.
Sending a tool with
strict: trueto Claude Opus 4.7 or Opus 4.8 on Bedrock Converse fails with a 400:The same request works on direct Anthropic and on Bedrock Sonnet 4.5/4.6 and Opus 4.5/4.6, so this is specific to Opus 4.7/4.8 on Bedrock Converse. It is a regression: working on 1.85.1, broken on 1.90.0/1.90.0-rc.1.
Why This Change Was Made
PR #29814 ("feat(bedrock): forward strict and additionalProperties to Converse toolSpec") started forwarding
strictinto the Bedrock ConversetoolSpec, gated onget_bedrock_base_model(model).startswith("anthropic"). That gate is too broad: Bedrock Converse routes Opus 4.7/4.8 through an Anthropic-compatible validator that mapstoolSpecto the native tool shape (thecustomvariant) and rejects the extrastrictkey, even though Anthropic's native API acceptsstrictas a top-level tool field for these models. Sonnet 4.5/4.6 and Opus ≤4.6 accepttoolSpec.strictand keep the existing behavior.The fix is a focused exclusion: replace the broad
startswith("anthropic")gate inlitellm_core_utils/prompt_templates/factory.pywith a small helperbedrock_converse_supports_strict_toolsinlitellm/llms/bedrock/common_utils.pythat:Falsefor non-Anthropic Bedrock models (preserves the existing "drop strict for Nova/Llama/GPT-OSS" behavior from feat(bedrock): forward strict and additionalProperties to Converse toolSpec #29814),Falsefor the Opus 4.7/4.8 family,Truefor every other Anthropic model on Bedrock (Sonnet 4.5/4.6, Opus ≤4.6, Haiku, etc.).The alternative — always drop
stricton Bedrock and re-add it elsewhere — would undo the user-visible enum-constraint fix from #29814 for Sonnet/Opus ≤4.6 callers. The targeted exclusion preserves the #29814 fix where it works and removes it only where Bedrock rejects the field.User Impact
strict: truetools tobedrock/...claude-opus-4-7orbedrock/...claude-opus-4-8stop getting400 BadRequestError: tools.N.custom.strict: Extra inputs are not permitted. The tool call succeeds (withstrictdropped on the Bedrock hop, matching pre-1.86 behavior).strictis still forwarded totoolSpecas before.Evidence
test_bedrock_tools_pt_strict_dropped_for_opus_47_48covers: Opus 4.7 (3 id spellings —bedrock/us.anthropic.claude-opus-4-7,anthropic.claude-opus-4-7-v1:0, mixed dash/underscore) and Opus 4.8 (same spellings) all dropstrict; Sonnet 4.5 and Opus 4.6 still forwardstrict.test_bedrock_tools_pt_strict_parameter(the feat(bedrock): forward strict and additionalProperties to Converse toolSpec #29814 regression test) still passes — confirms the Sonnet/Nova behavior is unchanged.bedrock/us.anthropic.claude-opus-4-7withstrict: true) is the case the new test locks in.python3 -m pytest tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py -k strict→ 2 passed.test_bedrock_converse_messages_pt_document_various_formats) fails in this file both with and without my changes (verified viagit stash) — it's a pre-existing MIME-type environment issue, not caused by this PR.