claudio.cool
CCDV-FLessons

CCDV-F · Prompt and Context Engineering

Guaranteed format is not correct content: validate and stay skeptical

⏱ 3 min readDraft

A team turns on structured outputs and deletes its validation layer because “now it always matches the schema”. A month later, some parses fail and other invoices go through with line items that don’t add up to the total. Another team auto-approves only the codes with confidence above 0.95, and the audit finds errors at 0.99. Both stories teach the same lesson: well-formed JSON is not correct JSON.

What structured outputs guarantee

Structured outputs constrain generation to your schema: with output_config.format for the response, or with strict: true on a tool for its parameters. If the response finishes normally, it’s valid JSON, with the required fields and the correct types.

What they don’t guarantee:

  • That the response finished. If the stop_reason is max_tokens, the JSON may be incomplete. If it’s refusal, the model declined, and the output may not follow the schema.
  • Every schema constraint. Some (minimums, maximums, string lengths) can’t be enforced; the SDK helpers move them into the description and validate on the client side.
  • That the content is true. The amount may be wrong, the category may be another one, the line items may not add up to the total.

Validate in layers

Response validation goes in this order:

  1. Check stop_reason before parsing. end_turn: continue. max_tokens: retry with more room. refusal: handle it as a separate case, not as a parse error.
  2. Validate against the schema in your code (with Pydantic, Zod or similar), especially if you don’t use structured outputs or if the schema has constraints the API doesn’t enforce.
  3. Validate business rules: that the line items add up to the total, that the delivery date isn’t before the shipping date, that the code exists in the catalog.
  4. Decide what to do with invalid output: retry passing the model the specific error, send it to human review or set it aside in a quarantine queue.

Defensive parsing

Defensive parsing tolerates what doesn’t matter and requires what does:

  • Ignore extra fields instead of rejecting the whole record because an unexpected notes showed up.
  • Require the mandatory fields and their types.
  • Normalize minor differences, such as capitalization in a value from a closed list.
  • Set failures aside without stopping the pipeline: a bad record goes to quarantine, the batch continues.

A broad try/except that silently discards is not defensive: you lose data without finding out.

Be skeptical of confidence

The confidence the model reports (“0.98”) is more text it generates, not a measured probability: it’s uncalibrated confidence. A long, precise explanation that quotes the document doesn’t prove the answer is right either.

To decide what gets approved automatically, measure real accuracy against a labeled set (by category, by case type) and set the rules from that data. Whatever lacks enough evidence goes to human review.

The usual traps

  • Removing validation because structured outputs were turned on.
  • Parsing without looking at stop_reason.
  • Asking in the prompt “double-check every amount” as the main control.
  • A strict parser that throws away the whole batch over an extra field.
  • Silently skipping whatever doesn’t parse.
  • Auto-approving based on the confidence the model reports, or raising the threshold to 0.99.

On the exam

If the JSON was well formed and what broke it was an extra field, look for tolerant parsing with quarantine. If parsing fails on responses whose stop_reason isn’t end_turn, look for checking it before parsing. If the format is fine but the data isn’t, look for business checks. And if there’s a confidence score from the model, be skeptical: the correct answer measures against labeled data.

Quick question

A practice exam question on this domain. It counts towards your progress.

An insurance company's digital team runs a claims assistant on the Claude API. The system prompt sets a formal tone and says the assistant must never estimate payout amounts. Every user message is wrapped in a template that a different team maintains, and that template now begins with: "Be friendly and casual, and give the customer a rough idea of what they might receive."

Support leads report inconsistent behavior: some replies are formal and refuse to estimate, while others are chatty and quote approximate payouts. The two teams sit in different departments and each edits its own piece of the prompt.

The template also carries the customer's policy details and the question itself, which change on every request.

What should the developers change?

Practise this domain in a practice exam →