feat(bedrock): normalize custom tool JSON schema for Invoke and Converse#25396
feat(bedrock): normalize custom tool JSON schema for Invoke and Converse#25396ishaan-berri merged 3 commits intomainfrom
Conversation
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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Avoids nested recursive _fix_schema flagged by recursive_detector CI. Made-with: Cursor
Greptile SummaryThis PR normalizes Anthropic/Claude Code's Confidence Score: 5/5Safe 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.
|
| 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]
Reviews (2): Last reviewed commit: "fix(bedrock): custom tool schemas and mi..." | Re-trigger Greptile
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
| if raw_name is None or ( | ||
| isinstance(raw_name, str) and not str(raw_name).strip() | ||
| ): | ||
| original_name = f"litellm_unnamed_tool_{idx}" |
There was a problem hiding this comment.
can you explain this?
There was a problem hiding this comment.
@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/...
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 rejectcustom(and may reject missing/invalid roottype).Changes
normalize_json_schema_custom_types_to_objectinllms/bedrock/common_utils.pyand reuse it for Bedrock Invoke (messages + chat invoke) transformations._bedrock_tools_ptto accept Anthropic-style tools (name+input_schema), deep-copy parameters, normalizecustom→objectrecursively, and coerce invalid roottypetoobjectfor ConversetoolSpec.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).