Skip to content
Domain 4Task 4.3

Structured Output with Tool Use

Learn this interactively

What You Need to Know

Structured output is a reply whose fields and types match a fixed shape. A JSON schema defines that shape: the fields, their types and which fields are required. With tool_use, Claude replies by calling a tool. The arguments of that call fill the tool's schema. With prompt-based JSON, the prompt asks Claude for JSON in a text response.

This lesson uses one made-up example throughout: an accounting firm whose software imports fields from client invoices, receipts and contracts. A reply that the software cannot parse stops the import. A wrong value creates a wrong accounting record.

For guaranteed schema-compliant output, there is a two-tier reliability hierarchy: first tool_use with JSON schemas, then prompt-based JSON. With tool_use, the tool's JSON schema constrains the shape of what Claude returns. This constraint eliminates syntax errors, such as missing brackets, trailing commas and unquoted keys. Prompt-based JSON is plain text with no structural guarantees. The model can produce malformed JSON, and in production it periodically will. That malformed JSON makes the firm's import fail. A separate parameter, tool_choice, can force the model to call a tool.

tool_choice: The Three Modes

tool_choice controls whether the model calls tools and how it calls them. It has three modes.

"auto" (default): The model decides whether to call a tool or return text. It may answer in text instead of calling the extraction tool, for example for the firm's faded receipt. Use this mode when the model legitimately needs the option to respond conversationally.

"any": The model must call a tool but chooses which one. Use this when there are multiple extraction schemas (e.g., extract_invoice, extract_receipt, extract_contract) and the document type is unknown, as with the firm's unsorted incoming mail. The model picks the appropriate tool. The output is guaranteed to be structured, and the tool selection stays flexible.

{"type": "tool", "name": "extract_metadata"}: The model must call the specific named tool. Use this mode to force a mandatory first step, such as extracting metadata before the enrichment steps, the later steps that add data to the record. This mode gives no flexibility and maximum control.

extract_metadata is your own tool. Its name is arbitrary. tool_choice applies per request, not per conversation. After the forced call returns, send the next request with auto, or omit the parameter. Otherwise, the model must call the same tool again, and you are in a loop.

typescript
// 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 }]
});

What tool_use Does NOT Prevent

tool_use with JSON schemas eliminates syntax errors but does not prevent semantic errors, where valid JSON holds wrong content.

  • Sum discrepancies: line items that do not sum to the stated total
  • Field placement errors: values in the wrong fields, such as 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

All three kinds of error pass the schema and appear in the firm's accounting records, because the schema guarantees structure, not correctness. Semantic validation needs additional logic. Task Statement 4.4 covers that logic.

Schema Design for Production

Good schema design prevents entire classes of errors at the structural level.

Optional/nullable fields. When a source document may lack some information, make the fields for that information optional or nullable. This is the primary defence against fabrication. A required field pressures the model to produce a value even when the source has none. A nullable field lets the model honestly return null. Many of the firm's receipts have no purchase order. If you make that field required, you encourage the model to invent a purchase order.

json
{
  "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. An enum field accepts only the values in a fixed list. Add an explicit "unclear" option to enum fields for genuinely unclear sources. Otherwise the model must classify the source anyway, as with a torn scan that could be a receipt or an invoice.

"other" + detail string. When the categories must be extensible, pair an "other" enum value with a freeform string field for the detail. This pair captures edge cases that your predefined categories do not cover, such as a client's bank statement.

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

Format normalisation rules. Put format normalisation instructions in the prompt alongside the schema. The schema enforces structure. The prompt enforces formatting consistency, such as "All dates in ISO 8601 format" or "All currency amounts as decimal numbers without currency symbols".

Key Concept

tool_use with a JSON schema stops syntax errors, not semantic ones. Optional or nullable fields stop fabrication when a source may lack information. tool_choice "any" guarantees structured output for unknown document types.

In the exam

The exam builds on the two-tier hierarchy and the three tool_choice modes. Answer with them even where the API has changed since (see the note below). If a question asks for guaranteed structured output for an unknown document type, the answer is any. The usual trap is the belief that tool_use prevents all extraction errors.

Current state

Exam guide v1.0 frames the hierarchy as the two tiers above. Current state (checked 6 October 2026): the API adds two controls that came after the guide. strict: true on a tool definition is one; the guide's appendix names it "strict mode for syntax error elimination". output_config.format is the other. It constrains the response itself rather than a tool call. The docs list a fourth tool_choice mode, {"type": "none"}. This mode blocks tool calls. It is the default when you pass no tools. The guide names three modes, so answer with three.

As of 14 November 2026, the define-tools page names Claude Fable 5.2, Mythos 5.2, Opus 5.5, Sonnet 5.5, Fable 5.1 and Mythos 5.1. It says that these models reject forced {"type": "any"} and {"type": "tool"} with a 400 error. Manual extended thinking rejects both on any model. In those cases, the documented method is "auto" with strict: true, or output_config.format when the response itself needs a fixed JSON shape. The claude-sonnet-5 model in the code above is not on that list.

Exam Traps

Exam Trap

Believing tool_use with JSON schemas prevents all extraction errors

The exam guide says strict JSON schemas via tool use eliminate syntax errors but not semantic errors, such as values that do not sum, misplaced data and fabricated values. Current docs (October 2026) guarantee schema-valid tool inputs only when strict: true is set. Validate separately.

Exam Trap

Relying on tool_choice 'auto' to guarantee a tool call

'auto' can skip the tool call. For several schemas and unknown document types the exam guide says use 'any'. Current docs (November 2026): Fable 5.2, Mythos 5.2, Opus 5.5, Sonnet 5.5, Fable 5.1 and Mythos 5.1 reject 'any'. On them, use 'auto' with strict: true.

Exam Trap

Making all schema fields required to ensure data completeness

Required fields pressure the model to fabricate values when the source lacks the information. Make the fields a document may lack nullable, so the model can return null, and keep fields that are always present required.

Practice Scenario

An extraction system uses tool_use with a strict JSON schema in which every field is required. When a document lacks a date or amount, the model invents a plausible one. An instruction not to invent values has not stopped it. What is the best fix?

Build Exercise

Build Exercise

Build a Structured Extraction Tool with JSON Schema

Difficulty
45 minutes

What you'll learn

  • Design JSON schemas with optional/nullable fields to prevent fabrication of missing data
  • Understand the three tool_choice modes (auto, any, forced) and when to use each
  • Recognise that tool_use eliminates syntax errors but not semantic errors
  • Apply schema design patterns: unclear enum values, other + detail string, format normalisation
  1. Define an extraction tool with a JSON schema: 3 required fields, 3 optional/nullable fields, an enum with unclear and other options, and a detail string field for the other category

    Why: Schema design directly prevents fabrication. Required fields pressure the model to invent values when information is absent. Optional/nullable fields allow honest null responses. This is the root cause fix for hallucinated extraction data.

    You should see: A valid JSON schema with required array containing only the 3 always-present fields, nullable type definitions for optional fields, and an enum array including unclear and other alongside the standard categories.

  2. Test with tool_choice auto and observe cases where the model returns text instead of calling the tool

    Why: The exam tests the distinction between auto, any, and forced tool_choice. Auto allows the model to respond conversationally instead of calling a tool, which means no guaranteed structured output. You need to see this failure mode firsthand.

    You should see: At least one response where the model returns a text message describing the document contents instead of calling the extraction tool. This demonstrates why auto is unsuitable when you need guaranteed structured output.

  3. Switch to tool_choice any and verify the model always returns structured output via a tool call

    Why: tool_choice any guarantees a tool call while letting the model choose which tool. This is the correct setting for guaranteed structured output when the document type is unknown, a key exam distinction from auto.

    You should see: Every response has stop_reason of tool_use and contains a valid tool call with structured output conforming to your schema. No text-only responses.

  4. Force a specific tool with tool_choice {type: tool, name: extract_metadata} and verify the mandatory extraction step runs

    Why: Forced tool selection ensures a mandatory first step executes regardless of the model decision. The exam tests this for scenarios like metadata extraction that must run before enrichment steps.

    You should see: The response always calls the exact tool you specified, even when the document content might suggest a different tool would be more appropriate. The model has no flexibility in tool selection.

  5. Process 5 documents — 3 with complete data and 2 with missing fields — and verify nullable fields return null rather than fabricated values

    Why: This validates the most important schema design principle: optional/nullable fields prevent fabrication. The exam specifically tests the scenario where required fields pressure the model to invent plausible-looking data for absent information.

    You should see: For the 3 complete documents, all fields populated with correct values. For the 2 documents missing information, the nullable fields return null instead of fabricated values. No invented dates, amounts, or identifiers.

Sources