Skip to content

4.3 Structured Output with Tool Use

When you need guaranteed schema-compliant structured output from Claude, there is a clear reliability hierarchy:

  1. tool_use with JSON schemas — eliminates JSON syntax errors entirely
  2. Prompt-based JSON — model can produce malformed JSON

Commit this hierarchy to memory. The exam builds on it. With tool use, the tool’s JSON schema constrains the shape of what Claude returns, eliminating syntax issues like missing brackets, trailing commas, or unquoted keys. The separate tool_choice parameter is what forces the model to call the tool at all. Prompt-based extraction (asking the model to output JSON in a text response) gives you no structural guarantees and will periodically produce unparseable output in production.

The tool_choice parameter controls whether and how the model calls tools. Understanding the three modes is critical for the exam:

"auto" (default): The model decides whether to call a tool or return text. It may choose to respond with a text message instead of calling the extraction tool. Use this when the model legitimately needs the option to respond conversationally.

"any": The model MUST call a tool but chooses which one. Use this when you have multiple extraction schemas (e.g., extract_invoice, extract_receipt, extract_contract) and the document type is unknown. The model selects the appropriate tool and returns structured output. Guaranteed structured output, flexible tool selection.

{"type": "tool", "name": "extract_metadata"}: The model MUST call the specific named tool. Use this to force a mandatory first step — for example, ensuring metadata extraction runs before enrichment steps. No flexibility, maximum control.

extract_metadata here is a tool you defined yourself; the name is arbitrary. tool_choice also applies per request, not per conversation. Once the forced call returns, send the next request with auto (or leave the parameter out), otherwise the model is obliged to call the same tool again and you loop.

// Force guaranteed structured output with unknown document type
const response = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 4096,
tool_choice: { type: "any" },
tools: [extractInvoiceTool, extractReceiptTool, extractContractTool],
messages: [{ role: "user", content: documentText }]
});
// Force a specific extraction step
const response = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 4096,
tool_choice: { type: "tool", name: "extract_metadata" },
tools: [extractMetadataTool],
messages: [{ role: "user", content: documentText }]
});

This is where the exam gets sneaky. tool_use with JSON schemas eliminates syntax errors but does NOT prevent semantic errors:

  • Sum discrepancies: Line items that do not sum to the stated total
  • Field placement errors: Values placed in the wrong fields (e.g., a date in an amount field when both are strings)
  • Fabrication: The model invents values for required fields when the source document lacks the information

The schema guarantees structure. It doesn’t guarantee correctness. Semantic validation needs additional logic (covered in Task Statement 4.4).

Effective schema design prevents entire classes of errors at the structural level:

Optional/nullable fields — When source documents may not contain certain information, make those fields optional or nullable. This is the primary defence against fabrication. If a field is required, the model is pressured to produce a value even when the source has none. If the field is nullable, the model can honestly return null.

{
"type": "object",
"properties": {
"invoice_number": { "type": "string" },
"vendor_name": { "type": "string" },
"payment_terms": { "type": ["string", "null"] },
"purchase_order": { "type": ["string", "null"] }
},
"required": ["invoice_number", "vendor_name"]
}

“unclear” enum value — For ambiguous cases where the source is genuinely unclear, add an explicit “unclear” option to enum fields. This prevents the model from forcing a classification when the evidence is ambiguous.

“other” + detail string — For extensible categorisation, include an “other” enum value paired with a freeform detail string field. This captures edge cases that your predefined categories do not cover.

{
"category": {
"type": "string",
"enum": ["invoice", "receipt", "contract", "unclear", "other"]
},
"category_detail": {
"type": ["string", "null"],
"description": "Freeform detail when category is 'other'"
}
}

Format normalisation rules — Include format normalisation instructions in the prompt alongside the schema. The schema enforces structure. The prompt enforces formatting consistency (e.g., “All dates in ISO 8601 format,” “All currency amounts as decimal numbers without currency symbols”).

Your extraction system uses tool_use with a strict JSON schema where all fields are required. Testers report the model invents plausible-looking dates and monetary amounts when processing documents that lack this information. What is the best fix?

  • A. Add an instruction to the prompt telling the model that it must not hallucinate any values at all
  • B. Switch from tool_use to prompt-based JSON extraction, which gives more flexibility in the output
  • C. Make fields optional or nullable when source documents may not contain the information
  • D. Add a post-extraction validation step that checks all values against the source document
Answer & explanation

Correct: C

  • A — Vague instructions do not override the schema constraint. Required fields structurally pressure the model to produce values regardless of instructions.
  • B — This moves backwards in the reliability hierarchy. Prompt-based JSON introduces syntax errors without solving the fabrication problem.
  • C — Optional/nullable fields allow the model to return null instead of fabricating values. This addresses fabrication at the schema design level — the root cause.
  • D — Post-hoc validation is valuable but addresses symptoms. Making fields optional prevents fabrication at the schema level, which is the correct root cause fix.

Six exam-style multiple-choice questions on Structured Output with Tool Use. Pick an answer, then open the explanation.

Your extraction system uses tool_use with a strict JSON schema where all fields are required. Testers report the model invents plausible-looking dates and monetary amounts when processing documents that lack this information. What is the best fix?

  • A. Add an instruction telling the model not to hallucinate values
  • B. Switch from tool_use to prompt-based JSON extraction for more flexibility
  • C. Add a post-extraction validation step that checks all values against the source document
  • D. Make fields optional or nullable when source documents may not contain the information
Answer & explanation

Correct: D

  • A is wrong because vague instructions do not override the schema constraint. Required fields structurally pressure the model to produce values regardless of instructions.
  • B is wrong because this moves backwards in the reliability hierarchy. Prompt-based JSON introduces syntax errors without solving fabrication.
  • C is wrong because post-hoc validation addresses symptoms, not the root cause. Making fields optional prevents fabrication at the schema level.
  • D is correct because optional/nullable fields allow the model to return null instead of fabricating values. This addresses fabrication at the schema design level.

You need guaranteed structured output from Claude when processing documents of unknown type. You have three extraction tools: extract_invoice, extract_receipt, and extract_contract. Which tool_choice setting is correct?

  • A. tool_choice: { type: “auto” }
  • B. tool_choice: { type: “any” }
  • C. tool_choice: { type: “tool”, name: “extract_invoice” }
  • D. Do not set tool_choice and let the API default handle it
Answer & explanation

Correct: B

  • A is wrong because “auto” allows the model to return text instead of calling a tool, providing no guarantee of structured output.
  • B is correct because “any” guarantees a tool call while letting the model choose which extraction tool suits the document type. This gives guaranteed structured output with flexible tool selection.
  • C is wrong because forcing a specific tool means every document is processed as an invoice, regardless of actual type.
  • D is wrong because the default is “auto”, which has the same problem as option A — no guarantee of structured output.

Which of the following errors can tool_use with JSON schemas prevent?

  • A. Line items that do not sum to the stated total
  • B. Values placed in the wrong fields (e.g., a date in an amount field)
  • C. Malformed JSON with missing brackets and trailing commas
  • D. Fabricated data for information absent from the source document
Answer & explanation

Correct: C

  • A is wrong because sum discrepancies are semantic errors. The schema ensures structure, not mathematical correctness.
  • B is wrong because field placement is a semantic error. Both fields might accept strings, and the schema cannot verify which value belongs where.
  • C is correct because tool_use with JSON schemas eliminates JSON syntax errors entirely — missing brackets, trailing commas, unquoted keys.
  • D is wrong because fabrication is a semantic error. The schema forces the model to produce a value of the right type but cannot verify its truthfulness.

Your document extraction schema has a “category” enum field with values: [“invoice”, “receipt”, “contract”]. Processing reveals documents that do not fit these categories, and the model forces incorrect classifications. What schema design fix is most appropriate?

  • A. Add “unclear” for ambiguous documents and “other” paired with a freeform detail string field
  • B. Remove the enum constraint and use a freeform string field
  • C. Add a confidence score to each classification and filter low-confidence results
  • D. Expand the enum to include every possible document type
Answer & explanation

Correct: A

  • A is correct because “unclear” handles genuinely ambiguous cases and “other” with a detail string captures edge cases while preserving structured categorisation.
  • B is wrong because removing the enum loses the classification structure that makes downstream processing possible.
  • C is wrong because confidence scores are poorly calibrated and do not address the missing categories.
  • D is wrong because you cannot anticipate every document type. The “other” + detail pattern is extensible without constant schema updates.

When should you use tool_choice { type: “tool”, name: “extract_metadata” } instead of tool_choice “any”?

  • A. When you want the model to choose the most appropriate extraction tool
  • B. When you want guaranteed structured output with unknown document types
  • C. When you need to force a mandatory first step before any other processing
  • D. When you want the model to optionally return text if no tool fits
Answer & explanation

Correct: C

  • A is wrong because flexible tool selection is the purpose of “any”, not forced tool selection.
  • B is wrong because guaranteed output with unknown types requires “any” so the model can select the appropriate tool.
  • C is correct because forced tool selection ensures a mandatory step executes regardless of model preference — for example, metadata extraction must run before enrichment steps.
  • D is wrong because optionally returning text is the behaviour of “auto”, not forced selection.

You are designing a JSON schema for extracting financial data. Some documents include tax identification numbers and some do not. How should you define the tax_id field?

  • A. type: [“string”, “null”] without including it in the required array
  • B. type: “string” with a required constraint to ensure completeness
  • C. type: “string” with a default value of “N/A”
  • D. Omit the field entirely and add it in post-processing if found
Answer & explanation

Correct: A

  • A is correct because nullable type combined with optional status allows the model to honestly return null when the information is absent.
  • B is wrong because making tax_id required pressures the model to fabricate a plausible-looking tax number when the document lacks one.
  • C is wrong because a default value of “N/A” is still fabrication — it fills the field with a placeholder rather than acknowledging absence.
  • D is wrong because omitting the field means you cannot distinguish “field not found” from “field not extracted” in the output.