If you have ever wired an AI response into a real system, you know the failure mode. You ask for JSON, and most of the time you get JSON. Then, on the response that matters, the model adds a friendly sentence before the opening brace, or wraps everything in a code fence, or renames a field. Your parser throws, the queue backs up, and someone gets paged.
Structured outputs solve this at the source. Instead of hoping the model returns clean data, you constrain Claude to a schema you define, so every response arrives in the exact shape your code expects. For any Australian business putting Claude behind an automation, this is the difference between a demo and something you can run unattended.
Why free-text responses break production pipelines
A language model is trained to be helpful and conversational. That instinct is useful in a chat window and a liability in a data pipeline. When you parse a model's prose with a regular expression or a naive JSON.parse, you are betting that the model behaves identically on every input. It will not.
The common breakages we see when auditing client automations:
Preamble text. The model explains what it is about to return before returning it, so the first character is not a brace.
Markdown fences. The payload is valid JSON but wrapped in triple backticks, which a strict parser rejects.
Drifting field names. On an ambiguous input the model invents a field, drops a required one, or changes casing.
Type slippage. A number arrives as a string, a date as free text, or a boolean as the word yes.
Silent truncation. A long response is cut off mid-object, and the parser fails on the last record only.
Each of these is rare on its own. Across thousands of calls a week, rare becomes daily. One firm we worked with was quietly re-keying every failed extraction by hand, which cost roughly $45,000 a year in analyst time before anyone measured it.
How Claude produces structured JSON
The reliable path is tool use. You define a tool with an input schema, and you tell Claude it must call that tool. The model then fills in the tool's arguments rather than writing a message, and the arguments are validated against your schema before they reach you. In practice you are not asking Claude to write JSON; you are asking it to fill in a form whose fields you control.
This matters because the constraint lives in the request, not in a paragraph of instructions the model may or may not follow. A prompt that says please return only JSON is a suggestion. A tool schema is a contract. When you set tool_choice to force the tool, Claude cannot answer in prose even if the input tempts it to.
The mechanics are the same whether you call Claude through the API directly or through the Claude Agent SDK. Define the schema once, force the tool, and validate the result on your side as a second line of defence.
Writing a schema that actually holds
A schema that holds is one the model can satisfy on its worst input, not just its best. The goal is to remove ambiguity so there is only one correct shape to return.
Constrain every field you can
Use enums for anything categorical. A status field that can only be open, paid, or overdue removes an entire class of drift.
Mark required fields explicitly and keep the required set small. If a field is genuinely optional, model it as optional rather than forcing the model to invent a value.
Give each field a plain description. The description is prompt real estate; a one-line note like invoice total in AUD, digits only is read by the model and shapes the output.
Prefer flat structures. Deeply nested objects are harder for the model to keep consistent and harder for you to validate.
Validate on your side anyway
Schema enforcement at the model layer catches most problems, but you still own the last check. Run the returned object through a validator such as Zod or Pydantic, and decide what happens when validation fails: retry once with the error fed back to Claude, route the record to a human queue, or fail loudly. Never write an unvalidated payload straight to your database.
For anything touching personal information, that validation step is also where your Privacy Act obligations live. If a field should never contain a customer's full name or account number, the validator is where you catch a model that included it by mistake.
A worked example: invoice extraction for an accounting firm
A Sydney accounting practice wanted to pull structured data from the PDF invoices its clients email in. The old process was a junior staffer reading each invoice and typing the supplier, ABN, total, GST, and due date into a spreadsheet. Accurate enough, but slow, and it did not scale past a few hundred documents a month.
We defined a single extraction tool. Supplier name is a required string. ABN is a required string with a description noting the 11-digit format. Total and GST are numbers in AUD. Due date is an ISO date string. Line items are an optional array, each with a description and an amount. Claude reads the invoice text and fills in the tool; the arguments arrive already shaped, and a Pydantic model checks them before anything is written.
The result: the same firm now processes the full inbox in minutes, and the analyst reviews only the handful of records the validator flags. The extraction itself is boring, which is exactly what you want from infrastructure. Scaled across a busy practice, the recovered time was worth well over $120K a year, and the numbers going into client files became more consistent, not less.
Where teams still trip up
Structured outputs are reliable, but they are not magic. A few habits separate the pipelines that stay up from the ones that need constant babysitting:
Treating the schema as write-once. Your data changes; revisit the schema when new invoice formats or edge cases appear.
Skipping the retry path. A single retry that feeds the validation error back to Claude resolves most transient failures without human involvement.
Logging only successes. Capture the raw model output on every failure so you can see what actually went wrong, rather than guessing.
Over-nesting to mirror an internal data model. Extract flat, then reshape in your own code where you have full control.
Get those right and structured outputs become the quiet backbone of a pipeline you can trust with real work: extraction, classification, routing, and enrichment that run overnight without anyone watching.
If you are weighing up where Claude could take manual data handling off your team's plate, we help Australian businesses design and ship these pipelines end to end. Book a brainstorm and we will map the highest-value place to start.



