A\
Lessons/Domain 4
4.412 min

Implement validation, retry, and feedback loops for extraction quality

Structured output tooling guarantees valid JSON but not correct JSON. This task is about the layer that runs after extraction: validating values against business rules, retrying with specific error feedback when the model got a transformation wrong, and recognizing when retrying cannot help because the information was never in the source. Done well, it turns silent extraction errors into structured signals you can reconcile, escalate, or feed back into prompt improvement.

Validation and retry-with-feedback loopSource documentClaude: tool_use extractionSchema-valid JSONcalculated_total / stated_totalconflict_detected, detected_patternValidation layer (your code)Semantic error?Accept, downstreamnoInfo in source?vs missing inputyesNull, human reviewnoRetry: document + failed extraction + errorsyesDashed = bounded retry loop; stop and escalate after N attempts.
The post-extraction validation and retry-with-feedback loop: schema guarantees valid JSON, your code checks semantics, transformation errors retry with specific feedback, and missing-input errors escalate instead of looping.

Schema is syntax, not truth

Enforcing output with a tool_use JSON schema (see 4.3) buys you exactly one guarantee: the response will be syntactically valid, schema-shaped JSON. Every required field is present, every enum value is legal, every type matches. What it does not buy you is correctness. A model can return perfectly valid JSON where the line items add up to $340 but total says $420, where a shipping address lands in the billing_address field, or where a year is transcribed as 2024 instead of 2025.

These are semantic validation errors, and they are invisible to the schema. The schema only knows shapes and types, not the business relationships between fields. So a production extraction system needs a second layer: application code that runs after the model returns and checks values against domain rules. Do the numbers reconcile? Is this field internally consistent? Does this reference resolve?

The split to memorize: tool use eliminates syntax errors; your validation layer catches semantic errors. Retrying to fix a JSON syntax error is almost never necessary once you use tool use. Retrying to fix a semantic error is exactly what the rest of this lesson is about.

Retry with specific error feedback

When validation fails on a fixable problem, the remedy is a retry-with-error-feedback loop, not a blind re-run. A blind re-run (same prompt, same document) tends to reproduce the same mistake because nothing about the input changed. Instead, construct a follow-up request that gives the model everything it needs to self-correct: the original source document, the specific extraction it produced, and the specific validation errors stated concretely.

Concreteness matters. "That was wrong, try again" gives the model nothing to act on. "The line items sum to 340.00 but you reported total=420.00; recompute total from the line items or re-read the printed invoice total" points directly at the defect. You are effectively turning your validator's output into a targeted prompt.

messages = [
  {"role": "user", "content": original_document},
  {"role": "assistant", "content": failed_tool_use},
  {"role": "user", "content":
     "Validation failed: line_items sum to 340.00 but total=420.00. "
     "Re-extract so total equals the sum of line_items."}
]

This is a bounded loop. Validate, and if it still fails after a small number of attempts, stop and route to a human rather than looping forever.

Know when a retry cannot help

This is the single most important judgment call in the task statement: retries only help when the information exists and the model got the transformation wrong. They cannot conjure information that is not in the source.

Retry will succeed for format mismatches and structural output errors: a mis-normalized date, a value placed in the wrong field, line items summed incorrectly, a currency symbol left in a numeric field. The correct answer is present in the document; the model just needs a nudge.

Retry will not succeed when the required field simply is not in the provided document, for example a po_number that only exists on a separate purchase order you never passed in. Re-prompting an absent fact pressures the model to fabricate a value to satisfy the request, which is worse than an honest null. The correct design here is to make the field optional and nullable (see 4.3), let the model return null, and route to a different data source or a human, not to keep retrying. Before you build a retry loop, ask: is this a transformation error or a missing-input error?

Self-correction fields: extract the check, not just the answer

You can move validation into the extraction itself by designing the schema so the model surfaces the raw material for a check, rather than only its conclusion. The canonical pattern: alongside the value the document states, ask for the value you can independently compute.

For invoices, extract both stated_total (the number printed on the document) and calculated_total (the model's sum of the line items). Your validator then compares the two; a mismatch is an immediate, cheap signal of a transcription or arithmetic problem, on either the model's side or the document's. Similarly, add a conflict_detected boolean with a detail field so the model can flag when the source itself is internally inconsistent, for example two different totals printed in two places.

{
  "line_items": [ ],
  "calculated_total": 340.00,
  "stated_total": 420.00,
  "conflict_detected": true,
  "conflict_detail": "Line items sum to 340.00; printed total reads 420.00"
}

This converts a silent, hard-to-detect error into structured data you can branch on: reconcile automatically, retry, or escalate. It also distinguishes a model error from a document error, which a plain total field never could.

Feedback loops with detected_pattern

Validation and retry close the loop on a single extraction; a feedback loop closes the loop on the system over time. The key instrument is a detected_pattern field attached to each finding or extraction, recording which construct in the source triggered the output, for example the specific code pattern that made a reviewer flag a line, or the document structure a value was pulled from.

Why this matters: when a human later dismisses a finding as a false positive, detected_pattern lets you aggregate dismissals by pattern. If 90% of dismissed code-review findings share detected_pattern: "unused-import-in-test-file", you have pinpointed a category to suppress or re-prompt, instead of guessing. Without it, you only know that people dismissed findings, not what they were reacting to.

This is the extraction-quality analogue of the review feedback loops elsewhere in Domain 4: instrument the output with enough provenance that you can do systematic error analysis and improve the prompt, rather than tuning blind. The pattern generalizes, tag each output with the signal that produced it so dismissals become data.

Anti-patterns to avoid

avoid
Treating a valid JSON schema as proof the extraction is correct.

Why it fails: A tool_use schema guarantees syntax and shape, not truth. Values can sum wrong, land in the wrong field, or transpose digits while remaining perfectly schema-valid.

instead Add an application-level semantic validation layer that checks business relationships (totals reconcile, fields internally consistent) after the model returns.

avoid
Retrying blindly: re-running the same prompt on failure, or sending 'that was wrong, try again.'

Why it fails: Nothing in the input changed, so the model tends to repeat the same mistake, and a vague error gives it nothing specific to correct.

instead Send a retry that includes the original document, the failed extraction, and the specific validation errors so the model can self-correct against a concrete target.

avoid
Retrying to recover a field that is absent from the source document.

Why it fails: Retries cannot create information that was never provided; re-prompting pressures the model to fabricate a value just to satisfy a required field.

instead Detect missing-input errors, make the field nullable, accept null, and route to another data source or human; reserve retries for format and structural errors.

avoid
Shipping findings or extractions with no provenance about what triggered them.

Why it fails: When humans dismiss false positives you cannot tell which patterns are responsible, so you tune the prompt blind.

instead Attach a detected_pattern field to each finding so dismissals can be aggregated by pattern for systematic false-positive analysis.

Worked example: Invoice extraction: catching totals that do not reconcile

You run a structured data extraction system (Scenario 6) that pulls invoices into a downstream accounting system. Extraction uses a forced tool_use schema, so the JSON is always valid. Yet finance reports that some records post the wrong amount.

Step 1: Design the schema to expose a check. Rather than a single total, the extraction tool asks for both the model's own sum and the printed value, plus a conflict flag:

{
  "invoice_id": "INV-2025-0442",
  "line_items": [
    {"desc": "Widget", "qty": 10, "unit": 20.00, "amount": 200.00},
    {"desc": "Setup", "qty": 1, "unit": 140.00, "amount": 140.00}
  ],
  "calculated_total": 340.00,
  "stated_total": 420.00,
  "po_number": null,
  "conflict_detected": true
}

Step 2: Validate semantics in your code. The schema is valid, but your validator compares calculated_total (340.00) to stated_total (420.00) and flags a mismatch. This is a semantic error the schema could never catch.

Step 3: Classify the error before acting. Is the correct information in the document? The line items and the printed total are both present, so this is a transformation and consistency problem, a good retry candidate. Contrast po_number: null: the PO lives on a separate document you never supplied, so retrying it would only invite fabrication. Leave it null and fetch it elsewhere.

Step 4: Retry with specific feedback. Send the original invoice, the failed extraction, and the concrete error:

Validation failed on INV-2025-0442: line_items sum to 340.00 but
stated_total=420.00. Re-read the invoice, confirm each line amount and
the printed total. If the document itself is inconsistent, set
conflict_detected=true and leave both totals as printed.

On retry the model finds a third line it had missed (Tax 80.00), returns calculated_total=420.00, conflict_detected=false, and validation passes.

Step 5: Bound the loop and instrument it. Cap retries (for example 2 attempts); if the totals still disagree, mark conflict_detected and route to human review rather than looping. Tag the record with detected_pattern: "missed-tax-line" so that if this recurs you can improve the prompt systematically rather than guessing.

Exam tips

  • Tool use and JSON schemas eliminate syntax errors only. Values that do not sum, wrong-field placement, and transposed digits are semantic errors that require a separate application-level validation layer.
  • An effective retry includes three things: the original document, the failed extraction, and the specific validation errors. 'Try again' is not a retry strategy.
  • Retries fix transformation errors (format, structure, arithmetic) but never recover information absent from the source. Missing-input errors need a nullable field plus an alternate source or human, not a retry.
  • Self-correction pattern: extract calculated_total alongside stated_total and compare them; add conflict_detected for internally inconsistent sources. This turns silent errors into structured signals.
  • detected_pattern on each finding lets you aggregate dismissals by pattern for systematic false-positive analysis; without it you tune prompts blind.
  • Retry loops must be bounded. After N failed attempts, escalate to human review rather than looping indefinitely or letting the model fabricate.
Official exam objectives for 4.4
Knowledge of
  • Retry-with-error-feedback: appending specific validation errors to the prompt on retry to guide the model toward correction
  • The limits of retry: retries are ineffective when the required information is simply absent from the source document (vs format or structural errors)
  • Feedback loop design: tracking which code constructs trigger findings (detected_pattern field) to enable systematic analysis of dismissal patterns
  • The difference between semantic validation errors (values don't sum, wrong field placement) and schema syntax errors (eliminated by tool use)
Skills in
  • Implementing follow-up requests that include the original document, the failed extraction, and specific validation errors for model self-correction
  • Identifying when retries will be ineffective (e.g., information exists only in an external document not provided) versus when they will succeed (format mismatches, structural output errors)
  • Adding detected_pattern fields to structured findings to enable analysis of false positive patterns when developers dismiss findings
  • Designing self-correction validation flows: extracting "calculated_total" alongside "stated_total" to flag discrepancies, adding "conflict_detected" booleans for inconsistent source data

Flashcards from this lesson

Tool use guarantees valid JSON. What class of errors does it NOT prevent?

Semantic errors: line items that do not sum to the total, values placed in the wrong field, transposed digits. Only syntax and shape are guaranteed.

What three things should a retry request include for effective self-correction?

The original source document, the failed extraction, and the specific validation errors stated concretely.

When is a retry guaranteed to be ineffective?

When the required information is simply absent from the provided source (a missing-input error). Retrying only pressures the model to fabricate; make the field nullable and use another source or human.

What schema pattern lets you automatically detect a bad invoice total?

Extract both calculated_total (the model's sum of line items) and stated_total (the printed value) and compare them; add conflict_detected for internally inconsistent sources.

What does the detected_pattern field enable?

Systematic analysis of dismissal and false-positive patterns by recording which source construct triggered each finding, so dismissals can be aggregated by pattern.

Format mismatch vs missing information: which is a retry candidate?

Format, structural, and arithmetic mismatches are retry candidates because the correct info is present. Missing information is not; it needs a nullable field and an alternate source.

Why must retry loops be bounded?

To avoid infinite loops and runaway cost when a defect is not self-correctable. After a capped number of attempts, escalate to human review instead of looping or fabricating.

Study all flashcards with spaced repetition