This commit is contained in:
冯基魁 2026-08-27 17:16:24 -05:00 committed by GitHub
commit 0c55417448
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 5 deletions

View file

@ -206,10 +206,12 @@ def normalize_custom_field_on_tools(request_body: dict) -> None:
def normalize_json_schema_custom_types_to_object(schema: dict) -> None:
"""
In-place: replace JSON Schema ``type: \"custom\"`` with ``\"object\"`` (iterative walk).
In-place: normalize JSON Schema fields unsupported by Bedrock (iterative walk).
Anthropic / Claude Code use ``custom`` for tool schemas; Bedrock Invoke and
Bedrock Converse only accept standard JSON Schema type strings.
Bedrock Invoke also rejects ``minimum`` and ``maximum`` on number schemas,
even though other providers accept those JSON Schema validation keywords.
Uses an explicit stack (not recursion) to satisfy recursive-function guards in CI.
"""
@ -225,6 +227,8 @@ def normalize_json_schema_custom_types_to_object(schema: dict) -> None:
seen.add(node_id)
if node.get("type") == "custom":
node["type"] = "object"
node.pop("minimum", None)
node.pop("maximum", None)
items = node.get("items")
if isinstance(items, dict):
stack.append(items)
@ -249,8 +253,9 @@ def normalize_tool_input_schema_types_for_bedrock_invoke(request_body: dict) ->
Bedrock Invoke (Anthropic Messages) validates ``input_schema`` as JSON Schema.
Anthropic's API allows ``type: \"custom\"`` for Claude Code custom tools; Bedrock
rejects it with: ``tools.0.custom.input_schema.type: Input should be 'object'``.
Bedrock also rejects ``minimum`` and ``maximum`` constraints on number schemas.
Normalizes ``type: \"custom\"`` to ``\"object\"`` throughout each tool's
Normalizes provider-unsupported schema fields throughout each tool's
``input_schema`` (recursive for nested properties, items, combinators).
Args:

View file

@ -1,4 +1,3 @@
import asyncio
import copy
import json
import os
@ -624,6 +623,7 @@ def test_normalize_tool_input_schema_types_for_bedrock_invoke():
"""
Claude Code sends ``input_schema.type: \"custom\"`` for custom tools.
Bedrock Invoke rejects this; it requires JSON Schema ``type: \"object\"``.
Bedrock also rejects ``minimum`` and ``maximum`` numeric bounds.
"""
request = {
@ -638,7 +638,31 @@ def test_normalize_tool_input_schema_types_for_bedrock_invoke():
"properties": {
"nested": {
"type": "custom",
"properties": {"x": {"type": "string"}},
"properties": {
"x": {"type": "string"},
"score": {
"type": "number",
"minimum": 0,
"maximum": 1,
},
"values": {
"type": "array",
"items": {
"type": "number",
"minimum": -1,
"maximum": 1,
},
},
"choice": {
"oneOf": [
{
"type": "number",
"minimum": 0,
"maximum": 10,
}
]
},
},
}
},
"required": ["nested"],
@ -656,7 +680,14 @@ def test_normalize_tool_input_schema_types_for_bedrock_invoke():
agent_tool = request["tools"][0]
assert agent_tool["type"] == "custom"
assert agent_tool["input_schema"]["type"] == "object"
assert agent_tool["input_schema"]["properties"]["nested"]["type"] == "object"
nested_schema = agent_tool["input_schema"]["properties"]["nested"]
assert nested_schema["type"] == "object"
assert "minimum" not in nested_schema["properties"]["score"]
assert "maximum" not in nested_schema["properties"]["score"]
assert "minimum" not in nested_schema["properties"]["values"]["items"]
assert "maximum" not in nested_schema["properties"]["values"]["items"]
assert "minimum" not in nested_schema["properties"]["choice"]["oneOf"][0]
assert "maximum" not in nested_schema["properties"]["choice"]["oneOf"][0]
assert request["tools"][1]["input_schema"]["type"] == "object"
request2 = {"messages": []}