Ship schemas that work for you
Need to ensure cross-provider compatibility? Or squeeze the most out of a single model's structured output? Without validation, models silently ignore unsupported schema features — and you get unexpected results.
Type Safety
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "number" }, // ⚠️ no integer constraint
"role": { "type": "string" }
}
// ⚠️ missing "required" — model may omit fields
// ⚠️ missing "additionalProperties: false"
}{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" }, // ✓ precise type
"role": { "type": "string" }
},
"required": ["name", "age", "role"], // ✓ all fields required
"additionalProperties": false // ✓ no extra fields
}Without strict constraints, models inject unexpected fields or omit values entirely. Adding additionalProperties: false and requiring all fields ensures you get exactly what you expect — nothing more, nothing less.
Accuracy
{
"type": "object",
"properties": {
"sentiment": { "type": "string" }, // ⚠️ no guidance — model guesses
"confidence": { "type": "number" }, // ⚠️ unbounded — could be 9999
"language": { "type": "string" } // ⚠️ free-form — "English", "en", "eng"?
},
"required": ["sentiment", "confidence", "language"],
"additionalProperties": false
}{
"type": "object",
"properties": {
"sentiment": {
"type": "string",
"enum": ["positive", "negative", "neutral"] // ✓ constrained values
},
"confidence": {
"type": "number",
"minimum": 0, "maximum": 1 // ✓ bounded range
},
"language": {
"type": "string",
"description": "ISO 639-1 code, e.g. 'en'" // ✓ format guidance
}
},
"required": ["sentiment", "confidence", "language"],
"additionalProperties": false
}Without enums, bounds, and descriptions, models guess values freely. You get "happy" instead of "positive", confidence scores of 85 instead of 0.85, and inconsistent language codes. Adding constraints guides the model to produce precise, consistent output.
Compatibility
{
"type": "object",
"properties": {
"name": { "type": "string" },
"category": {
"oneOf": [ // ⚠️ rejected by OpenAI strict mode
{ "type": "string" },
{ "type": "integer" }
]
}
},
"required": ["name", "category"]
// ⚠️ works on Anthropic, fails on OpenAI
}{
"type": "object",
"properties": {
"name": { "type": "string" },
"category": { "type": "string" } // ✓ single type — works everywhere
},
"required": ["name", "category"],
"additionalProperties": false // ✓ universal compatibility
}Each provider supports a different subset of JSON Schema. A schema that works on one may fail silently or be rejected outright on another. Validating against your target model catches these incompatibilities before deployment.
Predictability
{
"type": "object",
"properties": {
"result": {
"anyOf": [ // ⚠️ ambiguous — model picks randomly
{
"type": "object",
"properties": {
"value": { "type": "string" },
"items": { // ⚠️ deep nesting confuses models
"anyOf": [
{ "type": "string" },
{ "type": "array", "items": { "type": "string" } }
]
}
}
},
{ "type": "string" }
]
}
}
}{
"type": "object",
"properties": {
"value": { "type": "string" }, // ✓ flat, explicit
"items": {
"type": "array", // ✓ single clear type
"items": { "type": "string" }
}
},
"required": ["value", "items"],
"additionalProperties": false // ✓ predictable structure
}Complex schema structures with deep nesting and ambiguous unions confuse models. They may produce partially valid output, hallucinate fields, or silently fall back to unstructured text. Simpler, flatter schemas produce far more predictable results.
See every issue
Catch problems before they reach production — per keyword, per model.
Know it's valid
Validate against the exact model you're deploying to. No guessing.
Fix in one click
Auto-fix resolves issues instantly, or shows you exactly what to change.