Structured outputs & JSON
If your code parses an LLM’s output, the output is an API — and an API that’s “usually valid JSON” is a bug waiting to happen. The good news: getting reliable structured output is a solved problem if you layer three things instead of trusting the prompt alone.
1. Ask for structure — and give the schema
Tell the model the exact shape you want, with types and which fields are required. A schema in the prompt does most of the work:
Return ONLY JSON, no prose, matching this schema:
{
"priority": "low" | "medium" | "high",
"summary": string, // one sentence, <= 40 words
"tags": string[] // 0-5 short tags
}
Be explicit that the response must be JSON only — no greeting, no markdown code fence, no explanation. Prose around the JSON is the most common parse failure.
2. Use the provider’s structured-output mode
Most providers offer a JSON mode or structured outputs that constrains the decoder so the response is guaranteed to be syntactically valid JSON — and, with schema-constrained modes, guaranteed to match your schema. This is stronger than any prompt wording, because it operates on the generation itself. Use it whenever it’s available; keep the schema in the prompt too, since not every model supports constrained decoding.
3. Validate in code — never trust blindly
Always parse and validate the result against your schema (e.g., with a JSON Schema validator or a library like zod). Validation catches the cases the model gets subtly wrong — a missing field, a string where you expected a number, an enum value that isn’t in your list. On failure, you have three options: repair, retry, or fall back.
4. Handle truncation
A frequent failure isn’t malformed JSON — it’s incomplete JSON, because the model hit the output-token limit mid-object. Two defenses:
- Raise
max_tokensto comfortably fit the largest expected output. - Repair or retry when the JSON doesn’t close. A truncated object can often be repaired programmatically, or re-requested with a higher budget.
5. Keep the schema tight
Models produce better structured output when the schema is small and unambiguous:
- Prefer enums over free-form strings for categorical fields.
- Avoid deeply nested or optional-everywhere schemas.
- Give each field a one-line description of what it means.
- Don’t ask for fields the model can’t actually know — that’s where it hallucinates.
Putting it together
1. Prompt: "Return JSON only" + schema with enums and descriptions.
2. Call with JSON/structured-output mode enabled + generous max_tokens.
3. Parse → validate against the schema.
4. On failure → repair truncation, or retry once, or fall back.
That pipeline turns “usually JSON” into “always a valid object your code can trust.”
Checklist
- The prompt asks for JSON only and includes the schema.
- The provider’s JSON / structured-output mode is enabled.
- The response is validated against the schema in code.
-
max_tokensis large enough to avoid truncation. - There’s a repair/retry/fallback path for invalid output.
Ship these practices, don't just read them
VernaOne turns prompts into versioned, model-agnostic endpoints with structured output, evals, and automatic fallback — so the best practices here become defaults, not discipline.
Try VernaOne free →