Structured Output with Schemas

Getting reliable JSON, XML, and other structured formats out of every response

Why structured output matters at the advanced level

Once you start feeding Claude’s output into another system — a spreadsheet, a script, another prompt in a chain — free-form prose becomes a liability. You need output in a predictable, parseable shape every time. Getting that reliably takes more than “respond in JSON” tacked onto the end of a prompt.

Define the schema explicitly

The most reliable approach is to show Claude the exact shape you want, including field names, types, and how to handle edge cases — not just say “as JSON.”

Extract the following from this customer email into JSON matching
exactly this schema:

{
  "customer_name": string,
  "issue_category": one of ["billing", "technical", "account", "other"],
  "urgency": one of ["low", "medium", "high"],
  "requested_action": string or null if none is explicitly requested,
  "mentioned_order_ids": array of strings, empty array if none
}

Return only the JSON object, no other text.

Email: [paste email]

Notice the schema handles the edge cases up front — what happens when there’s no requested action, what happens when no order IDs are mentioned. Undefined edge cases are the most common source of malformed or inconsistent output.

“Return only the JSON” — and mean it

Claude will often want to add a friendly preamble (“Here’s the extracted data:”) or a trailing note. If you’re parsing the output programmatically, that breaks your parser. State explicitly that the response should contain nothing but the structured output, and if you’re chaining this into code, it’s worth adding one line asking Claude not to wrap the JSON in a markdown code fence either, depending on how your downstream code consumes it.

Watch for: On more complex or ambiguous inputs, Claude may still occasionally break format under pressure — for example, adding a clarifying comment when the input is genuinely ambiguous. For anything feeding into a strict parser, validate the output and have a fallback (like re-asking with an explicit reminder of the schema) rather than assuming compliance every time.

XML tags as a lighter-weight alternative

For output that’s going to be read by a human, or where you want Claude to separate distinct parts of a response without the strictness of full JSON, XML-style tags are a lighter structural tool.

Respond using this exact tag structure:

One-sentence summary

First risk
Second risk

Your recommendation

Tags are easy for both you and Claude to reason about, and they degrade more gracefully than JSON if Claude adds a stray sentence — a parser looking for content between two known tags is more forgiving than one expecting strictly valid JSON syntax.

Nested and conditional structures

For schemas with optional or conditional fields, spell out the condition rather than leaving it implicit — this is the schema version of the negative-example technique from Lesson 1.

"escalation_notes": string,
  — only include this field if urgency is "high"
  — omit the field entirely otherwise, do not include it as null

Validating before you trust it

Structured output prompts are exactly the kind of prompt worth versioning in your library (Lesson 4) — once you’ve found a schema phrasing that reliably parses clean, lock it in and reuse it rather than re-deriving the wording each time.

Key principle: A schema prompt is only as reliable as its edge-case coverage. Every field with a possible “empty” or “not applicable” state needs an explicit instruction for what to output in that case — don’t leave it to Claude to guess between null, an empty string, and omitting the field.

Try it: Take a task where you’re currently copy-pasting information out of Claude’s prose response by hand. Write an explicit schema for it, including edge cases, and compare how much manual cleanup is left.