Avoid top-level composition in tool schemas

This commit is contained in:
wuyang6
2026-05-11 11:51:11 +08:00
parent 0e2a00990f
commit 8cca3793e0
6 changed files with 53 additions and 46 deletions
@@ -1,8 +1,14 @@
{
"type": "object",
"properties": {
"records": {"type": "array"},
"records_path": {"type": "string"},
"records": {
"type": "array",
"description": "Canonical records. Provide exactly one of records or records_path."
},
"records_path": {
"type": "string",
"description": "Path to records JSON/JSONL. Provide exactly one of records or records_path."
},
"output_path": {"type": "string"},
"output_dir": {"type": "string"},
"output_format": {
@@ -13,9 +19,5 @@
"require_validation_ok": {"type": "boolean", "default": true},
"overwrite": {"type": "boolean", "default": true},
"export_table": {"type": "boolean", "default": true}
},
"anyOf": [
{"required": ["records"]},
{"required": ["records_path"]}
]
}
}
@@ -1,15 +1,17 @@
{
"type": "object",
"properties": {
"records": {"type": "array"},
"records_path": {"type": "string"},
"records": {
"type": "array",
"description": "Canonical records. Provide exactly one of records or records_path."
},
"records_path": {
"type": "string",
"description": "Path to records JSON/JSONL. Provide exactly one of records or records_path."
},
"output_path": {"type": "string"},
"output_dir": {"type": "string"},
"require_validation_ok": {"type": "boolean", "default": true},
"overwrite": {"type": "boolean", "default": true}
},
"anyOf": [
{"required": ["records"]},
{"required": ["records_path"]}
]
}
}
@@ -1,8 +1,14 @@
{
"type": "object",
"properties": {
"draft_text": {"type": "string"},
"draft_path": {"type": "string"},
"draft_text": {
"type": "string",
"description": "Dataset draft text. Provide exactly one of draft_text or draft_path."
},
"draft_path": {
"type": "string",
"description": "Path to UTF-8 dataset draft text. Provide exactly one of draft_text or draft_path."
},
"batch_id": {"type": "string", "default": "aabbccdd"},
"source_type": {
"type": "string",
@@ -12,9 +18,5 @@
"base_timestamp": {"type": "integer"},
"timestamp_step_ms": {"type": "integer", "minimum": 1, "default": 60000},
"default_request_id": {"type": "string", "default": "aabbccdd"}
},
"anyOf": [
{"required": ["draft_text"]},
{"required": ["draft_path"]}
]
}
}
@@ -1,11 +1,13 @@
{
"type": "object",
"properties": {
"records": {"type": "array"},
"records_path": {"type": "string"}
"records": {
"type": "array",
"description": "Canonical records. Provide exactly one of records or records_path."
},
"anyOf": [
{"required": ["records"]},
{"required": ["records_path"]}
]
"records_path": {
"type": "string",
"description": "Path to records JSON/JSONL. Provide exactly one of records or records_path."
}
}
}
+6 -18
View File
@@ -437,11 +437,11 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo
'properties': {
'draft_text': {
'type': 'string',
'description': 'Dataset draft text in dataset draft text v1 format.',
'description': 'Dataset draft text in dataset draft text v1 format. Provide exactly one of draft_text or draft_path.',
},
'draft_path': {
'type': 'string',
'description': 'Path to a UTF-8 dataset draft text file. Prefer this for large drafts.',
'description': 'Path to a UTF-8 dataset draft text file. Prefer this for large drafts. Provide exactly one of draft_text or draft_path.',
},
'batch_id': {
'type': 'string',
@@ -469,10 +469,6 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo
'description': 'Required for generated data; returned by data_agent_confirm_generation_plan.',
},
},
'anyOf': [
{'required': ['draft_text']},
{'required': ['draft_path']},
],
},
handler=resolve_handler(handlers, 'data_agent_normalize_dataset_draft', 'data-agent'),
),
@@ -490,17 +486,13 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo
{'type': 'array'},
{'type': 'string'},
],
'description': 'Canonical records as an array, or a JSON string containing the array.',
'description': 'Canonical records as an array, or a JSON string containing the array. Provide exactly one of records or records_path.',
},
'records_path': {
'type': 'string',
'description': 'Path to records JSON/JSONL. Prefer this when records are large.',
'description': 'Path to records JSON/JSONL. Prefer this when records are large. Provide exactly one of records or records_path.',
},
},
'anyOf': [
{'required': ['records']},
{'required': ['records_path']},
],
},
handler=resolve_handler(handlers, 'data_agent_validate_dataset_records', 'data-agent'),
),
@@ -519,11 +511,11 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo
{'type': 'array'},
{'type': 'string'},
],
'description': 'Canonical records as an array, or a JSON string containing the array.',
'description': 'Canonical records as an array, or a JSON string containing the array. Provide exactly one of records or records_path.',
},
'records_path': {
'type': 'string',
'description': 'Path to records JSON/JSONL. Prefer this when records are large.',
'description': 'Path to records JSON/JSONL. Prefer this when records are large. Provide exactly one of records or records_path.',
},
'output_path': {
'type': 'string',
@@ -552,10 +544,6 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo
},
},
'required': ['output_path'],
'anyOf': [
{'required': ['records']},
{'required': ['records_path']},
],
},
handler=resolve_handler(handlers, 'data_agent_export_dataset_records', 'data-agent'),
),
+11
View File
@@ -647,6 +647,17 @@ target: Agent(tag='地图导航')
self.assertEqual(export_payload['record_count'], 1)
self.assertTrue(table_exists)
def test_tool_schemas_avoid_top_level_composition_keywords(self) -> None:
# 部分 Bedrock/Anthropic 兼容后端不接受顶层 anyOf/oneOf/allOf。
blocked_keywords = {'anyOf', 'oneOf', 'allOf'}
violations = [
name
for name, tool in default_tool_registry().items()
if blocked_keywords.intersection(tool.parameters)
]
self.assertEqual(violations, [])
def test_data_agent_tools_route_relative_outputs_to_session_output(self) -> None:
with tempfile.TemporaryDirectory() as tmp_dir:
root = Path(tmp_dir)