1. Define the target schema
Start with the smallest JSON Schema that captures the fields you actually need. Mark every required field explicitly and set strict: true so the gateway refuses to emit extras. Tight schemas are faster, cheaper, and easier to validate downstream.
2. Call the router with response_format
Pass the schema under response_format.json_schema. The router picks a model that supports structured output and constrains decoding to your shape. You get a single string in choices[0].message.content that always parses.
import { Meridian } from '@meridian/sdk';
const client = new Meridian({ apiKey: process.env.MERIDIAN_KEY });
const schema = {
type: 'object',
properties: {
invoice_number: { type: 'string' },
total_amount: { type: 'number' },
line_items: {
type: 'array',
items: {
type: 'object',
properties: {
description: { type: 'string' },
quantity: { type: 'integer' },
unit_price: { type: 'number' }
},
required: ['description', 'quantity', 'unit_price']
}
}
},
required: ['invoice_number', 'total_amount', 'line_items']
};
const result = await client.chat.completions.create({
model: 'azure/model-router',
messages: [
{ role: 'system', content: 'Extract invoice fields as JSON.' },
{ role: 'user', content: rawInvoiceText }
],
response_format: {
type: 'json_schema',
json_schema: { name: 'Invoice', schema, strict: true }
}
});
const invoice = JSON.parse(result.choices[0].message.content);
3. Validate and store
Even with strict mode, run the parsed object through a runtime validator (Zod, Ajv) before persisting. Treat the model output as untrusted input: log schema misses, retry once with a corrective system message, and only then surface an error to the caller. This keeps your pipeline self-healing.