Skip to content

Summary: Schemas that refuse to lie

An extraction pipeline returns a purchase order number that was never on the invoice: plausible, well formatted, invented. The model did not go rogue. The schema declared the field required, the document had nothing to put in it, and the model filled the slot the only way it could. The lie was designed in. This lesson treats structured output as honesty engineering: guarantee the shape, then design the shape so the truth always fits inside it.

  • A JSON Schema on a tool definition is code-level enforcement of output shape. This is the track’s decide-versus-enforce spine touching the model’s output directly: a prompt instruction about format is a request, a schema is a guarantee.
  • The classic extraction move, carried over from the Building with Claude track: define a tool whose input schema is the record you want, and the model’s tool call is your data. This lesson presumes those mechanics and adds the design judgment.
  • The tool choice ladder (tool_choice) is a dial of guarantees. Auto, the default, lets the model decide whether to call a tool at all, so it guarantees nothing about shape. Any forces some tool call, so some schema is honored while the model routes. Forcing one specific tool by name guarantees that schema on every single run, which is the mode extraction pipelines want. (A fourth mode, none, forbids tool calls entirely and has no role in extraction.)
  • Strict mode (strict: true on the tool definition) closes the last gap. Anthropic’s docs describe the mechanism as constraining the model’s token sampling so only schema-valid output can be generated. Malformed output stops being a failure mode. The same guarantee exists for whole responses through the structured outputs feature (output_config).
  • Enforcement cuts both ways. A required, non-nullable field on a document that lacks the information makes the honest answer syntactically illegal, so the model invents a plausible value. Every required field is a bet that the information exists on every document you will ever process.
  • The fix is making absence representable: allow null alongside the real type, and say in the field description that null is the expected answer when the document is silent.
  • Required plus nullable beats optional. An omitted optional field is ambiguous: absent from the document, or just skipped? A required nullable field forces an explicit verdict, so null means “I looked, and it is not there.” Absence becomes a statement instead of a silence.
  • Every enum needs an escape hatch. A closed vocabulary on an open world force-fits reality into the nearest legal value, silently. Add a catch-all value plus a detail string capturing what was actually seen. The catch-all’s frequency is a sensor on your inputs, which beats silent misclassification.
  • The guarantee has a precise boundary: schema validity is syntactic, not semantic. Totals can disagree with line-item sums, a delivery date can land in the invoice date field, supplier and customer can swap, all inside perfectly valid JSON. Schemas check shape; these are errors of content.
  • Semantic validation is therefore still your job: cheap, deterministic cross-field checks in code, downstream of the model. Do the line items sum to the total? Is the date sane? If the enum says other, is the detail filled in? That is the enforce half of decide-versus-enforce, applied to content.
  • Validation-and-retry loops work when the retry message carries the specific error (“line items sum to 4,120.00 but the total says 4,210.00, re-read and correct”). Reading errors, transposed digits, and swapped fields usually fix in one round trip because the answer exists in the source.
  • The judgment call that names the lesson: a retry can only help when the correct answer exists in the source. Retrying because a nullable field came back null is fabrication pressure with extra steps; by attempt three the model will oblige. An honest null is the system working. Cap retries at one or two, then escalate to a human queue.

You can now hear “guaranteed valid JSON” precisely: a true claim about syntax and an empty one about truth. When you design or evaluate an extraction system, you have the checklist: which tool choice rung, is strict mode on, can every field honestly say “not present,” where is the enum escape hatch, what do the semantic validators check, and does the retry loop distinguish misreading from absence? The next lesson turns from the output contract to the input side of the same relationship: designing the tools themselves, where descriptions, boundaries, and error messages decide whether an agent uses your tools the way you meant.