Structured Outputs
Get type-safe JSON responses that conform to a specific schema. Perfect for building reliable applications that need predictable output formats.
What are Structured Outputs?
Structured outputs ensure that AI responses conform to a specific JSON schema. Instead of hoping the AI returns valid JSON, you can guarantee it by providing a schema that the model must follow.
❌ Without Structured Outputs
"Please return JSON with name and age fields"
May return invalid JSON, missing fields, or wrong types
✅ With Structured Outputs
Provide JSON schema with required fields and types
Guaranteed valid JSON matching your exact schema
Basic Example
structured-output.ts
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://www.superagentstack.com/api/v1',
apiKey: process.env.OPENROUTER_KEY,
defaultHeaders: { 'superAgentKey': process.env.SUPER_AGENT_KEY },
});
const response = await client.chat.completions.create({
model: 'openai/gpt-4o',
messages: [{
role: 'user',
content: 'Extract the person\'s information: "Hi, I\'m John Doe, 25 years old from NYC"'
}],
response_format: {
type: 'json_schema',
json_schema: {
name: 'person_info',
strict: true,
schema: {
type: 'object',
properties: {
name: { type: 'string', description: 'Full name' },
age: { type: 'number', description: 'Age in years' },
location: { type: 'string', description: 'City or location' }
},
required: ['name', 'age', 'location'],
additionalProperties: false
}
}
}
});
// Parse the guaranteed valid JSON
const person = JSON.parse(response.choices[0].message.content!);
console.log(person);
// Output: { name: "John Doe", age: 25, location: "NYC" }Response Format Types
| Type | Description | Use Case |
|---|---|---|
text | Default text response | General conversations |
json_object | Valid JSON without schema | Flexible JSON responses |
json_schema | JSON matching exact schema | Type-safe structured data |
Supported Schema Types
| Type | Description | Example |
|---|---|---|
string | Text values | "John Doe" |
number | Numeric values | 25, 3.14 |
boolean | True/false values | true, false |
array | Lists of items | ["item1", "item2"] |
object | Nested objects | {"key": "value"} |
enum | Predefined values | "red", "green", "blue" |
Complex Schema Example
complex-schema.ts
const response = await client.chat.completions.create({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Analyze this product review...' }],
response_format: {
type: 'json_schema',
json_schema: {
name: 'review_analysis',
strict: true,
schema: {
type: 'object',
properties: {
sentiment: {
type: 'string',
enum: ['positive', 'negative', 'neutral']
},
rating: {
type: 'number',
minimum: 1,
maximum: 5
},
key_points: {
type: 'array',
items: { type: 'string' },
maxItems: 5
},
categories: {
type: 'object',
properties: {
quality: { type: 'number', minimum: 1, maximum: 5 },
price: { type: 'number', minimum: 1, maximum: 5 },
service: { type: 'number', minimum: 1, maximum: 5 }
},
required: ['quality', 'price', 'service']
},
would_recommend: { type: 'boolean' }
},
required: ['sentiment', 'rating', 'key_points', 'categories', 'would_recommend']
}
}
}
});
const analysis = JSON.parse(response.choices[0].message.content!);
// Guaranteed structure with all fieldsStreaming with Structured Outputs
Structured outputs work with streaming. The JSON is built incrementally and validated when complete.
streaming-structured.ts
const stream = await client.chat.completions.create({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Generate a story outline' }],
stream: true,
response_format: {
type: 'json_schema',
json_schema: {
name: 'story_outline',
schema: {
type: 'object',
properties: {
title: { type: 'string' },
characters: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
role: { type: 'string' }
},
required: ['name', 'role']
}
},
plot: { type: 'string' }
},
required: ['title', 'characters', 'plot']
}
}
}
});
let content = '';
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content;
if (delta) {
content += delta;
console.log('Partial:', content);
}
}
// Final content is guaranteed valid JSON
const outline = JSON.parse(content);curl Example
bash
curl -X POST https://www.superagentstack.com/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_KEY" \
-H "superAgentKey: $SUPER_AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o",
"messages": [{"role": "user", "content": "Extract: John, 25, NYC"}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "number"},
"city": {"type": "string"}
},
"required": ["name", "age", "city"]
}
}
}
}'Model Support
✅ Fully Supported
- • OpenAI GPT-4o, GPT-4o-mini
- • Google Gemini 2.0 Flash
- • Anthropic Claude 3.5 Sonnet
- • Meta Llama 3.1 70B+
⚠️ Limited Support
- • Smaller models may not follow complex schemas
- • Some models only support simple JSON
- • Check OpenRouter model pages for details
Best Practices
Keep Schemas Simple
Start with simple schemas and gradually add complexity. Very complex schemas may be harder for models to follow consistently.
Use Descriptions
Add clear descriptions to your schema properties. This helps the model understand what each field should contain.
Set Constraints
Use
minimum, maximum, maxItems, and enumto constrain values and improve reliability.