Fix tool schema OpenAI compatibility (#301)

* fix: remove union type arrays from tool schemas for OpenAI compatibility

OpenAI rejects JSON Schema union types containing "array" without an
"items" subschema. The http tool's "body" and json tool's "data" params
used union types to accept any value. Replace with freeform (untyped)
schemas which OpenAI treats as accepting any JSON value.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: update schema tests to assert type is absent, fix missed json.rs test

- http.rs test: assert body has no "type" (not just has description)
- json.rs test: update to match the freeform schema change (was still
  asserting type is present)

Co-Authored-By: Claude Opus 4.6 <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
This commit is contained in:
Zaki Manian
2026-02-22 07:52:34 +00:00
committed by GitHub
co-authored by Claude Opus 4.6
parent c3ce26278a
commit a320f265b3
2 changed files with 14 additions and 10 deletions
+7 -5
View File
@@ -231,8 +231,7 @@ impl Tool for HttpTool {
}
},
"body": {
"type": ["object", "array", "string", "number", "boolean", "null"],
"description": "Request body (for POST/PUT/PATCH)"
"description": "Request body (for POST/PUT/PATCH). Can be a JSON object, array, string, or other value."
},
"timeout_secs": {
"type": "integer",
@@ -561,16 +560,19 @@ mod tests {
}
#[test]
fn test_http_tool_schema_body_has_type() {
fn test_http_tool_schema_body_is_freeform() {
let schema = HttpTool::new().parameters_schema();
let body = schema
.get("properties")
.and_then(|p| p.get("body"))
.expect("body schema missing");
// Body is intentionally freeform (no "type" constraint) for OpenAI
// compatibility. OpenAI rejects union types containing "array" unless
// "items" is also specified, and body accepts any JSON value.
assert!(
body.get("type").is_some(),
"body schema must include a type for OpenAI-compatible tool validation"
body.get("type").is_none(),
"body schema should not have a 'type' to be freeform for OpenAI compatibility"
);
}
+7 -5
View File
@@ -28,8 +28,7 @@ impl Tool for JsonTool {
"description": "The JSON operation to perform"
},
"data": {
"type": ["string", "object", "array", "number", "boolean", "null"],
"description": "JSON input data. Pass a string for parse, any type otherwise."
"description": "JSON input data. Pass a string for parse, or any JSON value (object, array, string, number, boolean, null) otherwise."
},
"path": {
"type": "string",
@@ -192,16 +191,19 @@ mod tests {
}
#[test]
fn test_json_tool_schema_data_has_type() {
fn test_json_tool_schema_data_is_freeform() {
let schema = JsonTool.parameters_schema();
let data = schema
.get("properties")
.and_then(|p| p.get("data"))
.expect("data schema missing");
// Data is intentionally freeform (no "type" constraint) for OpenAI
// compatibility. OpenAI rejects union types containing "array" unless
// "items" is also specified.
assert!(
data.get("type").is_some(),
"data schema must include a type for OpenAI-compatible tool validation"
data.get("type").is_none(),
"data schema should not have a 'type' to be freeform for OpenAI compatibility"
);
}
}