What Is Structured Output?
Structured output refers to LLM responses that conform to a predefined format — most commonly JSON — rather than generating free-form prose. By constraining the output format, applications can reliably parse and use LLM responses in downstream code without fragile string manipulation or regex extraction.
Structured output is the foundation of any LLM application that needs to extract data, populate databases, call APIs, or return machine-readable results.
Why Structure Matters
Without structured output, parsing LLM responses is fragile:
// Unstructured LLM output:
"The product is called Widget Pro, costs $49.99, and ships in 3-5 business days."
// Your code must now extract three fields from prose:
// - Name: Widget Pro
// - Price: $49.99
// - Shipping: 3-5 business days
// ...and hope the phrasing never changes
With structured output:
{
"name": "Widget Pro",
"price": 49.99,
"shipping_days_min": 3,
"shipping_days_max": 5
}
No parsing required — just response.name, response.price.
Methods for Achieving Structured Output
1. JSON Mode
Some APIs offer a dedicated JSON mode that guarantees the output will be valid JSON, though not necessarily conforming to a specific schema:
const response = await openai.chat.completions.create({
model: "gpt-4o",
response_format: { type: "json_object" },
messages: [
{ role: "system", content: "Return a JSON object with keys: name, price, shipping_days." },
{ role: "user", content: pageContent }
]
});
const data = JSON.parse(response.choices[0].message.content);
2. Structured Outputs with JSON Schema
OpenAI's response_format: { type: "json_schema" } guarantees the output matches a specific schema using grammar-constrained decoding:
const response = await openai.chat.completions.create({
model: "gpt-4o",
response_format: {
type: "json_schema",
json_schema: {
name: "product_extraction",
strict: true,
schema: {
type: "object",
properties: {
name: { type: "string" },
price: { type: "number" },
in_stock: { type: "boolean" }
},
required: ["name", "price", "in_stock"],
additionalProperties: false
}
}
},
messages: [{ role: "user", content: pageContent }]
});
3. Function Calling / Tool Use
Define the expected output as a function signature. The model fills in the parameters:
const tools = [{
type: "function",
function: {
name: "extract_product",
parameters: {
type: "object",
properties: {
name: { type: "string", description: "Product name" },
price: { type: "number", description: "Price in USD" }
},
required: ["name", "price"]
}
}
}];
4. Grammar-Constrained Generation
Open-source inference engines (llama.cpp, vLLM, Outlines) support constrained generation at the logit level — preventing the model from ever producing tokens that would violate the target grammar.
Structured Output for Web Extraction
KnowledgeSDK uses structured output internally across all extraction endpoints. The /v1/extract endpoint returns a typed, schema-validated object — you never receive free-form prose that you need to parse:
import KnowledgeSDK from "@knowledgesdk/node";
const sdk = new KnowledgeSDK({ apiKey: "knowledgesdk_live_..." });
const result = await sdk.extract("https://example.com/product");
// Fully typed, structured output — no parsing required
console.log(result.title); // string
console.log(result.content); // markdown string
console.log(result.category); // classified category string
console.log(result.metadata); // structured metadata object
The /v1/classify endpoint similarly returns a structured classification object, not raw text.
Error Handling for Structured Output
Even with schema enforcement, always validate parsed output before trusting it:
import { z } from "zod";
const ProductSchema = z.object({
name: z.string().min(1),
price: z.number().positive(),
in_stock: z.boolean()
});
const raw = JSON.parse(response.choices[0].message.content);
const product = ProductSchema.parse(raw); // throws ZodError if invalid
Combining JSON Schema enforcement from the LLM with Zod validation in your application gives you two layers of type safety.