Skip to content

feat(bedrock): normalize custom tool JSON schema for Invoke and Converse#25396

Merged
ishaan-berri merged 3 commits intomainfrom
litellm_bedrock-normalize-custom-tool-schema
Apr 14, 2026
Merged

feat(bedrock): normalize custom tool JSON schema for Invoke and Converse#25396
ishaan-berri merged 3 commits intomainfrom
litellm_bedrock-normalize-custom-tool-schema

Conversation

@Sameerlite
Copy link
Copy Markdown
Collaborator

@Sameerlite Sameerlite commented Apr 9, 2026

Summary

Claude Code and the Anthropic Messages API send tool definitions with input_schema.type: "custom". Amazon Bedrock Invoke and Converse validate JSON Schema strictly and reject custom (and may reject missing/invalid root type).

Changes

  • Introduce normalize_json_schema_custom_types_to_object in llms/bedrock/common_utils.py and reuse it for Bedrock Invoke (messages + chat invoke) transformations.
  • Update _bedrock_tools_pt to accept Anthropic-style tools (name + input_schema), deep-copy parameters, normalize customobject recursively, and coerce invalid root type to object for Converse toolSpec.inputSchema.json.

Tests

  • test_normalize_tool_input_schema_types_for_bedrock_invoke, test_bedrock_invoke_messages_transform_converts_custom_tool_schema_type_to_object (tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py).
  • test_bedrock_converse_tools_pt_converts_custom_schema_type_to_object (tests/llm_translation/test_bedrock_completion.py).
image

Anthropic/Claude Code use input_schema.type "custom"; Bedrock rejects it.
- Add normalize_json_schema_custom_types_to_object and use it for Invoke,
  chat invoke, and _bedrock_tools_pt (Anthropic input_schema + OpenAI params).
- Coerce invalid root types to object for Converse toolSpec.
- Tests for invoke transform, converse _bedrock_tools_pt, and unit helper.

Made-with: Cursor
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Apr 9, 2026 5:10am

Request Review

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq bot commented Apr 9, 2026

Merging this PR will not alter performance

✅ 16 untouched benchmarks


Comparing litellm_bedrock-normalize-custom-tool-schema (ec91021) with main (97f722f)

Open in CodSpeed

Avoids nested recursive _fix_schema flagged by recursive_detector CI.

Made-with: Cursor
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 9, 2026

Greptile Summary

This PR normalizes Anthropic/Claude Code's type: \"custom\" in tool input_schema to standard JSON Schema types before sending to Amazon Bedrock, which strictly validates JSON Schema and rejects \"custom\". It covers both the Bedrock Converse path (_bedrock_tools_pt in factory.py) and the Bedrock Invoke path (normalize_tool_input_schema_types_for_bedrock_invoke in common_utils.py), and adds graceful handling of missing or blank tool names for both paths.

Confidence Score: 5/5

Safe to merge — core normalization logic is correct, deep-copies protect callers, and tests cover both Converse and Invoke paths end-to-end.

All findings are P2 style suggestions (inline imports without explanatory comments). No logic bugs, no data mutation of caller inputs, no missing guards, no security concerns, and tests are thorough.

No files require special attention.

Vulnerabilities

No security concerns identified. Changes are confined to schema normalization and tool-name sanitization in Bedrock request transformation, with no auth, secrets, or data-handling implications.

Important Files Changed

Filename Overview
litellm/llms/bedrock/common_utils.py Adds normalize_json_schema_custom_types_to_object (iterative, cycle-safe walker), normalize_tool_input_schema_types_for_bedrock_invoke, and ensure_bedrock_anthropic_messages_tool_names — all correct and well-documented.
litellm/litellm_core_utils/prompt_templates/factory.py _bedrock_tools_pt extended to accept Anthropic-style tools (name+input_schema), deep-copies parameters, normalizes custom types, and coerces invalid root type to object; adds inline imports consistent with pre-existing pattern in the same function.
litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py Wires up ensure_bedrock_anthropic_messages_tool_names alongside the existing normalize_tool_input_schema_types_for_bedrock_invoke call in transform_anthropic_messages_request.
litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py Adds normalize_tool_input_schema_types_for_bedrock_invoke to _build_bedrock_anthropic_request_base for the chat/Invoke path; correct placement after remove_custom_field_from_tools.
litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py Robustifies tool name handling in translate_anthropic_tools_to_openai — gracefully falls back to generated name when name is missing or blank.
tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py Adds three pure-unit tests (no network) covering: schema type normalization, missing tool names, and end-to-end transform_anthropic_messages_request with custom types.
tests/llm_translation/test_bedrock_completion.py Adds test_bedrock_converse_tools_pt_converts_custom_schema_type_to_object covering Converse path for both Anthropic-style and OpenAI-style tools with custom schema types.
tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_anthropic_experimental_pass_through_adapters_transformation.py No substantial changes visible in the diff for this file; no issues found.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Incoming tool definitions\nname + input_schema\nOR function.parameters] --> B{Bedrock path?}

    B --> |Converse _bedrock_tools_pt| C[copy.deepcopy parameters]
    B --> |Invoke AnthropicClaudeConfig| D[normalize_tool_input_schema_types_for_bedrock_invoke]

    C --> E[unpack_defs - expand $ref]
    E --> F[normalize_json_schema_custom_types_to_object]
    F --> G{root type valid?}
    G -->|No| H[set type = object]
    G -->|Yes| I[Build BedrockToolJsonSchemaBlock]
    H --> I

    D --> J[for each tool: normalize_json_schema_custom_types_to_object on input_schema]
    J --> K[ensure_bedrock_anthropic_messages_tool_names]
    K --> L[Bedrock Invoke request body]
    I --> M[Bedrock Converse request body]
Loading

Reviews (2): Last reviewed commit: "fix(bedrock): custom tool schemas and mi..." | Re-trigger Greptile

Comment thread litellm/litellm_core_utils/prompt_templates/factory.py
Normalize JSON Schema type custom to object for Bedrock invoke and
_bedrock_tools_pt, ensure stable names for tools without name, and
avoid KeyError in the Anthropic messages adapter when translating
tools to OpenAI format for bedrock/converse.

Made-with: Cursor
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this change do? @Sameerlite

if raw_name is None or (
isinstance(raw_name, str) and not str(raw_name).strip()
):
original_name = f"litellm_unnamed_tool_{idx}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@krrish-berri-2 The code in adapters/transformation.py is used for /v1/messages → litellm.completion adapter flows. For Bedrock, that mainly means bedrock/converse/...

@ishaan-berri ishaan-berri merged commit e2fc7d6 into main Apr 14, 2026
104 of 107 checks passed
@ishaan-berri ishaan-berri deleted the litellm_bedrock-normalize-custom-tool-schema branch April 14, 2026 17:21
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.

3 participants