What you will be able to do
- Explain what constrained decoding guarantees and what it leaves to your own validation code
- Request schema-conforming JSON with output_config.format and read it from the right content block
- Use SDK helpers such as client.messages.parse() and understand how they transform and re-validate schemas
- Enable strict: true on tool definitions and know where it is rejected or needs data-handling care
Key concept
Constrained decoding — Claude's token sampling is limited to outputs that fit your JSON Schema, so the response always matches the schema's structure. It replaces the older approach of hoping the model follows format instructions and retrying when it does not.
1.Why prompting alone is not enough
Any code that consumes Claude's output has to parse it. If you only ask for JSON in the prompt, you are relying on the model to follow that instruction every time. The structured outputs documentation lists what goes wrong "even with careful prompting": parsing errors from invalid JSON syntax, missing required fields, inconsistent data types, and schema violations that you then have to catch and retry.
Structured outputs deal with this at generation time. The feature has two parts, and you can use them separately or in the same request. JSON outputs (output_config.format) control the format of Claude's own response. Strict tool use (strict: true) makes tool names and tool inputs match your schema. The documentation sums up the result as "always valid", "type safe" and "no retries needed for schema violations."
Sources1
2.JSON outputs with output_config.format
Setting it up takes three steps. Define a JSON Schema, add output_config.format with type: "json_schema" and that schema, then parse the response. The JSON comes back in the response's text content block, not in a separate field. The schema uses standard JSON Schema, but only a subset of it is supported.
You usually don't write the raw schema yourself. The SDKs build it from native types: Pydantic in Python, Zod or typed JSON Schema literals in TypeScript, plain classes in Java and C#, and so on. In Python, the recommended entry point is client.messages.parse(), which returns a typed parsed_output.
response = client.messages.parse(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Extract contact info: John Smith, john@example.com, interested in the Pro plan",
}
],
output_format=ContactInfo,
)
# Access the parsed output directly
contact = response.parsed_output
print(contact.name, contact.email)The helpers also rewrite your schema before sending it. They remove constraints that constrained decoding does not support, such as minimum, maximum, minLength and maxLength. They move each removed constraint into the field description (for example, "Must be at least 100"), add additionalProperties: false to every object, and keep only supported string formats. Then they validate the response against your original schema, constraints included. Claude sees a simplified schema, and your code still enforces the rest. If you need to edit the transformed schema by hand, transform_schema() gives it to you so you can pass it through output_config yourself.
Not during decoding. The SDK dropped minimum from the schema it sent and wrote the rule into the field description instead, so 42 is a valid integer as far as the grammar is concerned. The SDK's validation step, which checks the response against your original schema, is what rejects it.
The Agent SDK has the same pattern. You pass outputFormat / output_format with a JSON schema, and the final result message carries a structured_output field. The error handling shown in its examples is worth copying: a single-shot query() raises after it yields an error result such as error_max_structured_output_retries, so wrap it in try and don't assume a validated object always comes back.
3.Strict tool use for agent tool calls
In an agent, tool inputs are output too, and your functions run on them directly. Without strict mode, the model can pass the wrong type or leave out a required field. The documentation's booking example: a function that expects passengers: int might get "two" or "2". With strict: true it always gets passengers: 2.
You enable it with a top-level "strict": true next to name, description and input_schema. That gives two guarantees: the tool input follows input_schema, and the tool name is always valid (one of the tools you provided or a server tool). The input arrives in response.content[x].input of a tool_use block:
{
"type": "tool_use",
"name": "get_weather",
"input": {
"location": "San Francisco, CA"
}
}Three constraints to know. First, the computer use and browser use toolset entries do not accept strict: true, and a request that sets it on them is rejected. Second, strict schemas are compiled into grammars and cached for up to 24 hours after last use, apart from message content. Strict tool use is HIPAA eligible, but because of that separate cache, PHI must stay out of property names, enum values, const values and patterns, and appear only in messages. Third, strict mode uses the same schema subset as JSON outputs.
Sources3
4.Choosing between the two
| Aspect | JSON outputs | Strict tool use |
|---|---|---|
| How you enable it | output_config.format with type: "json_schema" | "strict": true on the tool definition |
| What it constrains | Claude's response format | Tool names and tool inputs |
| Where you read the result | The response's text content block | response.content[x].input on a tool_use block |
| Typical use | Extracting data, structured reports, formatting API responses | Agentic workflows, type-safe function calls, nested tool parameters |
A team builds a pipeline that extracts contact fields (name, email, plan) from support tickets and feeds them directly into a database insert without any try/except around the JSON parsing step. The pipeline occasionally crashes because Claude's response includes explanatory text before the JSON or omits a required field. What is the most effective fix to guarantee schema conformance without relying on prompt wording alone?
Correct answer: B — Configure Structured Outputs with a JSON schema in the API's output format field
- A. Incorrect. Wording instructions can reduce but never guarantee stray text or missing fields; Claude can still deviate under load or ambiguity, so the pipeline remains fragile.
- B. Correct. Structured Outputs constrains generation to a declared JSON schema, guaranteeing valid, schema-conforming JSON in the response text and removing the need for prompt-based hoping.
- C. Incorrect. Truncation from running out of tokens is a separate failure mode from stray prose or omitted fields; more tokens doesn't enforce schema conformance.
- D. Incorrect. Backtick stripping only addresses one formatting quirk and does nothing to guarantee required fields are present or types are correct.
Sources1
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.Constrained decoding enforces every constraint in your Pydantic model, including minimum, maximum and length limits.Why is that wrong?
The SDK removes unsupported constraints before sending the schema and enforces them afterwards by validating the response against the original schema. That check happens in your code, not during decoding.
Covered in JSON outputs with output_config.format
2.strict: true can be added to any tool in the tools array, including the computer use and browser use toolsets.Why is that wrong?
Those toolset entries do not accept strict mode, and a request that sets it on them is rejected.
Covered in Strict tool use for agent tool calls
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“Without structured outputs, Claude can generate malformed JSON responses or invalid tool inputs that break your applications.”
↩︎ Why prompting alone is not enough“You can use these features independently or together in the same request.”
↩︎ Why prompting alone is not enough“The parse() method automatically transforms your Pydantic model, validates the response, and returns a parsed_output attribute.”
↩︎ JSON outputs with output_config.format“Remove unsupported constraints (for example, minimum, maximum, minLength, maxLength)”
↩︎ JSON outputs with output_config.format“Strict tool use (strict: true): Guarantee schema validation on tool names and inputs”
↩︎ Choosing between the two“Structured outputs guarantee schema-compliant responses through constrained decoding:”
↩︎ Key concept“This means Claude receives a simplified schema, but your code still enforces all constraints through validation.”
↩︎ Exam trap 1 - 2.
“The result message contains structured_output with validated data”
↩︎ JSON outputs with output_config.format - 3.
“Without strict mode, Claude might return incompatible types ("2" instead of 2) or omit required fields, breaking your functions and causing runtime errors.”
↩︎ Strict tool use for agent tool calls“Do not include PHI in input_schema property names, enum values, const values, or pattern regular expressions.”
↩︎ Strict tool use for agent tool calls“The computer use and browser use toolset entries (computer_toolset_20260801 and browser_toolset_20260801) don't accept strict: true”
↩︎ Exam trap 2