From 6c46974bf9d2818aad287273a2c993163bb4a7aa Mon Sep 17 00:00:00 2001 From: gnanam1990 Date: Wed, 1 Apr 2026 20:26:21 +0530 Subject: [PATCH] =?UTF-8?q?fix:=20normalize=20tool=20schemas=20so=20requir?= =?UTF-8?q?ed=20=E2=8A=87=20properties=20for=20OpenAI/Codex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenAI and Codex enforce strict JSON Schema validation — every key in `properties` must also appear in `required`. Anthropic schemas often mark fields as optional (omitted from `required`), which causes 400 errors on OpenAI/Codex endpoints. Example: the Agent tool has `subagent_type` in `properties` but not in `required`, producing: "Invalid schema for function 'Agent': Missing 'subagent_type' in required array" Fix: add `normalizeSchemaForOpenAI()` in `convertTools()` that ensures `required` is a superset of all `properties` keys before the schema is sent to the API. Existing `required` entries are preserved; missing ones are appended. Schemas without `properties` pass through unchanged. Fixes #46. Co-Authored-By: Claude Sonnet 4.6 --- src/services/api/openaiShim.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/services/api/openaiShim.ts b/src/services/api/openaiShim.ts index f7a5f6b7..4e92bc0c 100644 --- a/src/services/api/openaiShim.ts +++ b/src/services/api/openaiShim.ts @@ -217,6 +217,21 @@ function convertMessages( return result } +/** + * OpenAI requires every key in `properties` to also appear in `required`. + * Anthropic schemas often mark fields as optional (omitted from `required`), + * which causes 400 errors on OpenAI/Codex endpoints. This normalizes the + * schema by ensuring `required` is a superset of `properties` keys. + */ +function normalizeSchemaForOpenAI(schema: Record): Record { + if (schema.type !== 'object' || !schema.properties) return schema + const properties = schema.properties as Record + const existingRequired = Array.isArray(schema.required) ? schema.required as string[] : [] + const allKeys = Object.keys(properties) + const required = Array.from(new Set([...existingRequired, ...allKeys])) + return { ...schema, required } +} + function convertTools( tools: Array<{ name: string; description?: string; input_schema?: Record }>, ): OpenAITool[] { @@ -227,7 +242,7 @@ function convertTools( function: { name: t.name, description: t.description ?? '', - parameters: t.input_schema ?? { type: 'object', properties: {} }, + parameters: normalizeSchemaForOpenAI(t.input_schema ?? { type: 'object', properties: {} }), }, })) }