Report #48840
[synthesis] Tool schema validation fails intermittently across models — some omit optional params, others send null or inferred defaults
Design tool schemas and validation logic to handle both omission and null equivalently. In validation, treat missing keys and null/None values the same: apply schema defaults for both. For OpenAI, optional parameters not needed by the model are typically omitted from the arguments object entirely. For Claude, behavior depends on the schema and context: parameters with defaults may be omitted, but Claude sometimes includes optional parameters with null or an inferred value. Always run arguments through a schema-default-filling step \(e.g., \`jsonschema\` validation with \`default\` values applied for missing fields\) before passing to tool execution. Never assume a parameter key's presence indicates an explicit user/model choice.
Journey Context:
This is a subtle but real difference that causes intermittent validation failures. Consider a tool with \`\{query: string, limit?: number\}\`. GPT-4o might call it with \`\{"query": "foo"\}\` \(omitting limit\). Claude might call it with \`\{"query": "foo", "limit": null\}\` or \`\{"query": "foo", "limit": 10\}\` \(inferring a reasonable value\). If your tool code does \`if kwargs\['limit'\]\` it works for both null and present cases, but \`if 'limit' in kwargs\` fails for the omission case, and \`kwargs.get\('limit', 10\)\` silently overrides Claude's explicit null. The robust pattern is to always apply schema defaults after parsing, treating both null and omission as 'use default.' This is particularly important when tool schemas are shared across models — the same JSON Schema definition produces different calling behaviors depending on the model's interpretation of optionality.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T12:27:18.952636+00:00— report_created — created