Skip to content

feat(bedrock): forward strict and additionalProperties to Converse toolSpec - #29813

Closed
mateo-berri wants to merge 1 commit into
litellm_internal_stagingfrom
claude/cool-clarke-I904A
Closed

feat(bedrock): forward strict and additionalProperties to Converse toolSpec#29813
mateo-berri wants to merge 1 commit into
litellm_internal_stagingfrom
claude/cool-clarke-I904A

Conversation

@mateo-berri

@mateo-berri mateo-berri commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

A customer reported that strict: true on tools is silently ignored for Claude on Bedrock: give a tool an enum and ask for a value outside it, and GPT and direct-Anthropic stay inside the enum while Claude-on-Bedrock returns the out-of-enum value. This re-applies the fix from #25209, which was correct and approved (Greptile 5/5) but went stale with merge conflicts since April after unrelated refactors landed in _bedrock_tools_pt. The hunks no longer applied, but the change itself was still valid, so this is a clean rebase onto current staging rather than a rewrite. Related: #10062, #16725, #6136

Linear ticket

Pre-Submission checklist

  • I have added meaningful tests
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

CI (LiteLLM team)

  • Branch creation CI run
    Link:
  • CI run for the last commit
    Link:
  • Merge / cherry-pick CI run
    Links:

Screenshots / Proof of Fix

Reproduce against a live proxy hitting real Bedrock (Claude). Define a tool whose only enum value is celsius and ask for Fahrenheit; before this change the call comes back with additionalProperties/strict dropped and the model free to pick an out-of-enum value, after it the schema reaches Bedrock intact.

curl -s http://localhost:4000/v1/chat/completions \
  -H "Authorization: Bearer $LITELLM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0",
    "messages": [{"role": "user", "content": "What is the weather in Dallas in Fahrenheit? Call the tool."}],
    "tool_choice": "required",
    "tools": [{
      "type": "function",
      "function": {
        "name": "get_weather",
        "strict": true,
        "description": "Get the weather for a city",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {"type": "string"},
            "unit": {"type": "string", "enum": ["celsius"]}
          },
          "required": ["city", "unit"],
          "additionalProperties": false
        }
      }
    }]
  }' | jq '.choices[0].message.tool_calls[0].function.arguments'

With the fix the returned unit stays "celsius" (the only enum member) instead of "fahrenheit".

Type

🐛 Bug Fix

Changes

litellm/types/llms/bedrock.py: add additionalProperties: bool to ToolJsonSchemaBlock and strict: bool to ToolSpecBlock (both total=False, so the keys stay optional).

litellm/litellm_core_utils/prompt_templates/factory.py: in _bedrock_tools_pt, forward strict from the OpenAI function and additionalProperties from the schema, each only when present. Bedrock requires additionalProperties: false alongside strict: true or it rejects the request, so both have to travel together.

tests/llm_translation/test_bedrock_completion.py: add test_bedrock_tools_pt_strict_parameter covering both the pass-through and the absent-by-default cases. It fails (KeyError on strict) without the factory change and passes with it.

…olSpec

Bedrock Converse supports strict in toolSpec since 2026-02, but
_bedrock_tools_pt only whitelisted type/properties/required/name/description,
so strict: true was silently dropped and Claude-on-Bedrock ignored enum
constraints that GPT and direct-Anthropic honored. Forward strict from the
OpenAI function and additionalProperties from the schema (Bedrock requires
the latter alongside strict), passing each only when present.

https://claude.ai/code/session_01WQjWd8NfUB3vxERwudbHkv
@mateo-berri

mateo-berri commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

Closing in favor of #29814, which carries the identical change on a properly named branch. Continuing review there

@mateo-berri mateo-berri closed this Jun 5, 2026
@codecov

codecov Bot commented Jun 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@mateo-berri
mateo-berri deleted the claude/cool-clarke-I904A branch June 5, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant