fix bedrock schema bounds filtering

This commit is contained in:
冯基魁 2026-06-28 04:47:57 +08:00
parent 71e69d3485
commit fada84a66a
2 changed files with 41 additions and 5 deletions

View file

@ -168,10 +168,12 @@ def remove_custom_field_from_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.
"""
@ -187,6 +189,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)
@ -211,8 +215,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
@ -327,6 +326,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 = {
@ -341,7 +341,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"],
@ -359,7 +383,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": []}