When another program will consume Claude's answer, you don't want prose — you want
reliable JSON that matches a schema every time. The trick is to use tool_use as a typed output
contract, handle nullable fields honestly, and wrap it in a validation-retry loop. This is the
"Structured Data Extraction" exam scenario.
tool_use as schemanullable fieldsvalidation-retrybatch APIprefill / JSON mode
Explain like I'm 10
Imagine you want answers on a form with labelled boxes instead of a messy paragraph — name here, age
there. A JSON schema is that form. If Claude doesn't know someone's age, the honest move is to leave
the box blank (null), not to make up "42." And if it scribbles outside the lines, you hand the form
back and say "fill box 3 properly," until it's right. Forms, not essays — and blanks are allowed.
The reliable pattern: tool_use as a contract
Rather than asking for JSON in prose and hoping, you define a tool whose input_schema is
exactly the shape you want, and let Claude "call" it. Because the API enforces the schema, you get typed,
predictable fields. Extract a messy invoice and watch the structured result:
document
extracted (schema-valid)
The non-negotiables
Nullable, not invented: fields that may be absent are typed ["string","null"] and the
description says "null if not present." This stops the model fabricating a plausible-but-wrong value.
Validation-retry loop: validate the output against the schema; on failure, return the precise error
and let Claude fix it — bounded to a few attempts (Domain 2's structured-error idea).
Batch at scale: extracting from thousands of docs? Use the Message Batches API — ~50% cheaper,
async, built for high-volume non-realtime jobs.
Multi-pass for hard docs: extract → a second pass verifies/critiques the extraction
(evaluator–optimizer) for accuracy-critical data.
Exam trap: for a missing field the correct design is an explicit null, not
an empty string, a guess, or omitting it silently. Marking every field required forces
fabrication. And for bulk extraction the right tool is the Batch API (cost + throughput), not a hot loop
of real-time calls.
Takeaways: get reliable JSON by using tool_use as a typed schema
contract. Model genuinely-optional fields as nullable (null beats a fabricated value), and enforce shape
with a bounded validation-retry loop. For high volume use the Message Batches API; for
accuracy-critical extraction add a verification pass.