fix(bedrock): drop toolSpec.strict for Claude Sonnet 5 on Converse - #33196
Conversation
Greptile SummaryThis PR fixes a 400 error on Bedrock Converse when calling Claude Sonnet 5 with tools that include a
Confidence Score: 5/5Safe to merge — the change is a pure data addition to the cost map that gates an existing code path, with no logic modifications and no backwards-incompatible behavior. The fix adds a single boolean flag to six cost-map entries in both JSON files, exactly mirroring the pattern already in place for Opus 4.7/4.8 and Sonnet 4. The gate function and stripping logic in common_utils.py are untouched. New tests cover all six variants across three levels (tool transformation, helper function, and raw cost-map values), all without real network calls. PR description includes before/after real API proof. No existing tests are weakened or removed. No files require special attention.
|
| Filename | Overview |
|---|---|
| model_prices_and_context_window.json | Adds bedrock_converse_supports_strict_tools: false to all six Sonnet 5 entries, consistent with existing Opus 4.7/4.8 and Sonnet 4 entries. |
| litellm/model_prices_and_context_window_backup.json | Mirror of the main JSON — same six Sonnet 5 entries receive bedrock_converse_supports_strict_tools: false, keeping both files in sync. |
| tests/test_litellm/litellm_core_utils/prompt_templates/test_bedrock_converse_strict_tools_opus_47_48.py | Extends the existing regression suite with 13 new Sonnet 5 cases across three test functions; all tests are mock-only, covering the tool transformation, the helper function, and the cost-map flag values. |
Reviews (1): Last reviewed commit: "fix(bedrock): drop toolSpec.strict for C..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
|
||
|
|
||
| def _classify_a2a_route(path: str) -> Optional[str]: | ||
| if path.endswith(_A2A_INVOKE_SUFFIX) and any(path.startswith(prefix) for prefix in _A2A_TRANSPORT_PREFIXES): |
There was a problem hiding this comment.
Medium: Bare A2A requests bypass metering
The A2A handler accepts message/send and message/stream through POST /a2a/{agent_id}, with the operation selected by the JSON-RPC method field. This classifier returns None for that path, so a customer can send successful billable agent requests through the bare route without incrementing the enterprise counter. Inspect the JSON-RPC method or have the endpoint stamp a server-controlled response marker so only billable operations on the multiplexed route are recorded.
PR overviewThis PR adjusts Bedrock Converse handling for Claude Sonnet 5 by dropping the There is one open security issue: bare A2A JSON-RPC requests to Open issues (1)
Fixed/addressed: 0 · PR risk: 5/10 |
Bedrock routes Claude Sonnet 5 through the same Anthropic-compatible validator as Opus 4.7/4.8 and Sonnet 4, which rejects toolSpec.strict with 'tools.0.custom.strict: Extra inputs are not permitted'. Set bedrock_converse_supports_strict_tools: false on all six Sonnet 5 entries so the existing gate strips the field, matching the fix shape of BerriAI#31582
36143ad to
c2e887b
Compare
|
Waiting on this! Will this work with inference profiles too? I.E |
7c56317
into
BerriAI:litellm_oss_daily_2026_07_20
Yes this should work with that configuration as well |
|
Thanks for merging, @tin-berri. Flagging a follow-up so this doesn't get lost: the merge landed on The equivalent Opus 4.7/4.8 fix for #31582 reached |
Relevant issues
Fixes #33193
Linear ticket
Resolves LIT-4261
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaito re-request a review after pushing changes)Note on CI: after retargeting to litellm_oss_daily_2026_07_20 and rebasing,
auth-and-jwtandBlock fork dependency changespass. The only red check isosv-scan, which flags two freshly published advisories in UI dev dependencies (brace-expansion, GHSA-3jxr-9vmj-r5cp andjs-yaml, GHSA-52cp-r559-cp3m inui/litellm-dashboard/package-lock.json); it fails the same way on sibling PRs #34083, #34067 and #34034, and fork PRs are not allowed to modify lockfiles per theBlock fork dependency changespolicy, so the bump has to happen in the canonical repositoryDelays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
The branch was later rebased onto litellm_oss_daily_2026_07_20 to satisfy the uv.lock parity check; the proof runs below were captured at the pre-rebase commits referenced in each section (
10d5804b3ebefore,2eee00e0f8after) and the rebased headc2e887b2a2carries the identical diffReal Bedrock calls against
us.anthropic.claude-sonnet-5in us-east-1, proxy started withLITELLM_LOCAL_MODEL_COST_MAP=Trueso the local cost map (where this fix lives) is used instead of the remote one. Config:Before, at base commit
10d5804b3e(litellm_oss_daily_2026_07_13). Tool definition containsstrictand Bedrock rejects the request:Before, same commit
10d5804b3e,/v1/responseswith nostrictanywhere in the request; the Responses to ChatCompletions bridge inserts the field itself, so this endpoint is broken for this model with no client-side workaround:After, at fix commit
2eee00e0f8, identical chat completions request now returns a real tool call:{"id":"chatcmpl-8284e712-b85d-4ae0-b5d1-7528f6538703","created":1784022777,"model":"claude-sonnet","object":"chat.completion","choices":[{"finish_reason":"tool_calls","index":0,"message":{"content":"","role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"{\"city\": \"Prague\"}","name":"get_weather"},"id":"tooluse_kUJAnoxDYhw0MVoHDlYqRT","type":"function"}]}}],"usage":{"completion_tokens":50,"prompt_tokens":444,"total_tokens":494,...}}After, same commit
2eee00e0f8, identical/v1/responsesrequest also succeeds; output contains the function call (response id and message item trimmed for brevity):{"id":"resp_...","created_at":1784022840,"model":"claude-sonnet","object":"response","output":[{"type":"message",...},{"type":"function_call","name":"get_weather","arguments":"{\"city\": \"Prague\"}",...}],...}Control checks from the same proxy: the chat completions request without the
strictkey succeeds on both commits, andstrictis still forwarded for models that accept it (covered by thetest_bedrock_tools_pt_strict_kept_for_other_anthropiccases)Type
🐛 Bug Fix
Changes
Same shape as the #31582 fix for Opus 4.7/4.8. Bedrock routes Claude Sonnet 5 through the Anthropic-compatible validator that rejects
toolSpec.strict, but the six Sonnet 5 entries (anthropic.claude-sonnet-5plusglobal./us./eu./au./jp.inference profiles) never got thebedrock_converse_supports_strict_tools: falseflag, so the gate inbedrock_converse_supports_strict_tools()fell back to its forward-by-default behavior for Anthropic models and every tool call carryingstrict400'dThis PR sets
bedrock_converse_supports_strict_tools: falseon those six entries in bothmodel_prices_and_context_window.jsonandlitellm/model_prices_and_context_window_backup.json, and extends the existing regression test filetests/test_litellm/litellm_core_utils/prompt_templates/test_bedrock_converse_strict_tools_opus_47_48.pywith the Sonnet 5 cases (13 new parametrized cases across_bedrock_tools_pt, thebedrock_converse_supports_strict_toolshelper and the cost map flag check). The new cases fail on the base commit and pass with the fix; the full file is 40 passed