Follow Discord
Sweep 22 Oct 2026 · 04:32Z Build v2.1.308 527 read Stable v2.1.308 Latest v2.1.308 Next v2.1.308 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · api

structured-outputs changedbuild-with-claude/structured-outputs

Nearest release: v2.1.307, published an hour after this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Recorded here
Lines+58added
Lines−54removed
From line 42 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits21to this page, all time

The whole hunk

from line 42, old and new numbered
/
lines
from line 42
4242 
4343## Why use structured outputs
4444 
45Without structured outputs, Claude can generate malformed JSON responses or invalid tool inputs that break your applications. Even with careful prompting, you may encounter:
45Without structured outputs, Claude can generate malformed JSON responses or invalid tool inputs that break your applications. Even with careful prompting, you might encounter:
4646 
4747* Parsing errors from invalid JSON syntax
4848* Missing required fields
from line 194
194194 
195195 Pass a [Pydantic](https://docs.pydantic.dev/) model to `client.messages.parse()`, the recommended method, as `output_format`. The SDK transforms the model's schema, sends it as `output_config.format`, validates the response, and returns the parsed model in `parsed_output`.
196196 
197 The example above outputs:
197 The previous example outputs:
198198 
199199 ```text Output wrap
200200 name='John Smith' email='[email protected]' plan_interest='Enterprise' demo_requested=True
from line 236
236236 
237237 Wrap a [Zod](https://zod.dev/) schema in `zodOutputFormat()` and pass it to `client.messages.parse()` as `output_config.format`. `zodOutputFormat()` transforms the schema, and `parse()` validates the response and returns the parsed result in `parsed_output`, typed to match the schema.
238238 
239 The example above outputs:
239 The previous example outputs:
240240 
241241 ```javascript Output
242242 {
from line 283
283283 
284284 Pass a plain C# class or record to the generic `Create<T>()` overload. The SDK derives a JSON schema from the type, transforms it, and parses each text block back into it.
285285 
286 The example above outputs:
286 The previous example outputs:
287287 
288288 ```text Output wrap
289289 ContactInfo { Name = John Smith, Email = [email protected], PlanInterest = Enterprise, DemoRequested = True }
from line 331
331331 
332332 The SDK generates and transforms the JSON schema from the struct and unmarshals the response into it.
333333 
334 The example above outputs:
334 The previous example outputs:
335335 
336336 ```text Output wrap
337337 main.ContactInfo{Name:"John Smith", Email:"[email protected]", PlanInterest:"Enterprise", DemoRequested:true}
from line 369
369369 
370370 When you pass a Java class to `outputConfig()`, the SDK derives a JSON schema from it and validates the schema. The builder then produces a `StructuredMessageCreateParams<T>`. Rather than transforming the schema, the SDK's local validation rejects [constraints not supported by the API](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#json-schema-limitations). Read the parsed result with `response.content().stream().flatMap(block -> block.text().stream()).findFirst().orElseThrow().text()`.
371371 
372 The example above outputs:
372 The previous example outputs:
373373 
374374 ```text Output wrap
375375 {"name":"John Smith","email":"[email protected]","plan_interest":"Enterprise","demo_requested":true}
from line 380
380380 </Note>
381381 
382382 <Accordion title="Generic type erasure">
383 Java retains generic type information for fields in the class's metadata, but generic type erasure applies in other scopes. While a JSON schema can be derived from a `BookList.books` field with type `List<Book>`, a valid JSON schema cannot be derived from a local variable of that same type.
383 Java retains generic type information for fields in the class's metadata, but generic type erasure applies in other scopes. Although a JSON schema can be derived from a `BookList.books` field with type `List<Book>`, a valid JSON schema cannot be derived from a local variable of that same type.
384384 
385 If an error occurs while converting a JSON response to a Java class instance, the error message includes the JSON response to assist in diagnosis. If your JSON response may contain sensitive information, avoid logging it directly, or ensure that you redact any sensitive details from the error message.
385 If an error occurs while converting a JSON response to a Java class instance, the error message includes the JSON response to help with diagnosis. If your JSON response might contain sensitive information, avoid logging it directly, or ensure that you redact any sensitive details from the error message.
386386 </Accordion>
387387 
388388 <Accordion title="Local schema validation">
from line 392
392392 
393393 * **Local validation** occurs without sending requests to the remote AI model.
394394 * **Remote validation** is also performed by the AI model upon receiving the JSON schema.
395 * **Version compatibility:** Local validation may fail while remote validation succeeds if the SDK version is outdated.
395 * **Version compatibility:** Local validation might fail while remote validation succeeds if the SDK version is outdated.
396396 * **Disabling local validation:** Pass `JsonSchemaLocalValidation.NO` if you encounter compatibility issues:
397397 
398398 ```java
from line 425
425425 
426426 You can control visibility with annotations:
427427 
428 * `@JsonIgnore` excludes a `public` field or getter method
429 * `@JsonProperty` includes a non-`public` field or getter method
428 * `@JsonIgnore` excludes a `public` field or getter method.
429 * `@JsonProperty` includes a non-`public` field or getter method.
430430 
431431 If you define `private` fields with `public` getter methods, the SDK derives the property name from the getter (for example, `private` field `myValue` with `public` method `getMyValue()` produces a `"myValue"` property). To use a non-conventional getter name, annotate the method with `@JsonProperty`.
432432 
from line 555
555555 }
556556 ```
557557 
558 Local validation checks that you haven't used any unsupported constraint keywords, but constraint values aren't validated locally. For example, an unsupported `"format"` value may pass local validation but cause a remote error.
558 Local validation checks that you haven't used any unsupported constraint keywords, but constraint values aren't validated locally. For example, an unsupported `"format"` value might pass local validation but cause a remote error.
559559 
560560 If you use both Jackson and Swagger annotations to set the same schema field, the Jackson annotation takes precedence.
561561 </Accordion>
from line 602
602602 
603603 `parsedOutput()` returns your model instance on success, or `null` (or an error array) if parsing fails. Use `instanceof` to narrow the type before accessing fields.
604604 
605 The example above outputs:
605 The previous example outputs:
606606 
607607 ```text Output wrap
608608 object(ContactInfo)#42 (4) {
from line 695
695695 
696696 Define a class that extends `Anthropic::BaseModel` and pass it to `messages.create()` as `output_config: {format: Model}`. The SDK derives a JSON schema from the class, transforms it, and assigns the parsed result to the response's `parsed_output` attribute as a typed Ruby object.
697697 
698 The example above outputs:
698 The previous example outputs:
699699 
700700 ```text Output wrap
701701 {name: "John Smith", email: "[email protected]", plan_interest: "Enterprise", demo_requested: true}
from line 740
7407401. **Remove unsupported constraints** (for example, `minimum`, `maximum`, `minLength`, `maxLength`)
7417412. **Update descriptions** by adding each unsupported constraint to the field's description (for example, `{minimum: 100}`)
7427423. **Add `additionalProperties: false`** to all objects
7434. **Filter string formats** to supported list only
7434. **Filter string formats** to the supported list only
7447445. **Validate responses** against your original schema and all its constraints, if the helper validates responses
745745 
746746Claude receives a simplified schema, but a helper that validates responses still enforces every constraint in your code.
from line 875
875875 print(contact)
876876 ```
877877 
878 The example above outputs:
878 The previous example outputs:
879879 
880880 ```text Output wrap
881881 {'name': 'John Smith', 'email': '[email protected]', 'plan_interest': 'Enterprise', 'demo_requested': True}
from line 917
917917 console.log(response.parsed_output);
918918 ```
919919 
920 Use `jsonSchemaOutputFormat()` to pass a plain JSON schema to `parse()`, without installing Zod. The API returns a response that conforms to the schema, and if you declare the schema with `as const`, the type for `parsed_output` is automatically inferred by TypeScript according to your schema. For an imported or generated schema, `parsed_output` is typed as `unknown`.
920 Use `jsonSchemaOutputFormat()` to pass a plain JSON schema to `parse()`, without installing Zod. The API returns a response that conforms to the schema, and if you declare the schema with `as const`, TypeScript automatically infers the type for `parsed_output` according to your schema. For an imported or generated schema, `parsed_output` is typed as `unknown`.
921921 
922 By default, the helper [transforms the schema](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#how-sdk-transformation-works) the same way `zodOutputFormat()` does. Pass `{ transform: false }` as the second argument to send it unchanged. Unlike `zodOutputFormat()`, it doesn't validate the response, so it won't catch violations of [constraints not supported by the API](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#json-schema-limitations), such as `minimum`.
922 By default, the helper [transforms the schema](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#how-sdk-transformation-works) the same way `zodOutputFormat()` does. Pass `{ transform: false }` as the second argument to send it unchanged. Unlike `zodOutputFormat()`, it doesn't validate the response, so it doesn't catch violations of [constraints not supported by the API](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#json-schema-limitations), such as `minimum`.
923923 
924 The example above outputs:
924 The previous example outputs:
925925 
926926 ```javascript Output
927927 { name: 'John Smith', email: '[email protected]', planInterest: 'Pro' }
from line 1032
10321032 }
10331033 ```
10341034 
1035 The example above outputs:
1035 The previous example outputs:
10361036 
10371037 ```text Output wrap
10381038 main.ContactInfo{Name:"John Smith", Email:"[email protected]", PlanInterest:"Enterprise", DemoRequested:true}
from line 1087
10871087 }
10881088 ```
10891089 
1090 The example above outputs:
1090 The previous example outputs:
10911091 
10921092 ```text Output wrap
10931093 {"name":"John Smith","email":"[email protected]","plan_interest":"Enterprise"}
from line 1132
11321132 
11331133 Pass the schema as an associative array to `OutputConfig::with()`, and decode the response with `json_decode()`.
11341134 
1135 The example above outputs:
1135 The previous example outputs:
11361136 
11371137 ```text Output wrap
11381138 array(3) {
from line 1184
11841184 p contact
11851185 ```
11861186 
1187 The example above outputs:
1187 The previous example outputs:
11881188 
11891189 ```text Output wrap
11901190 {"name" => "John Smith", "email" => "[email protected]", "plan_interest" => "Enterprise", "demo_requested" => true}
from line 2160
21602160 
21612161JSON outputs and strict tool use solve different problems and work together:
21622162 
2163* **JSON outputs** control Claude's response format (what Claude says)
2164* **Strict tool use** validates tool parameters (how Claude calls your functions)
2163* **JSON outputs** control Claude's response format (what Claude says).
2164* **Strict tool use** validates tool parameters (how Claude calls your functions).
21652165 
21662166When combined, Claude can call tools with guaranteed-valid parameters AND return structured JSON responses. This is useful for agentic workflows where you need both reliable tool calls and structured final outputs.
21672167 
from line 2252
22522252 ```
22532253 
22542254 ```python Python
2255 client = anthropic.Anthropic()
2256 
22552257 response = client.messages.create(
22562258 model="claude-opus-5-5",
22572259 max_tokens=1024,
from line 2300
22982300 ```
22992301 
23002302 ```typescript TypeScript
2303 const client = new Anthropic();
2304 
23012305 const response = await client.messages.create({
23022306 model: "claude-opus-5-5",
23032307 max_tokens: 1024,
from line 2593
25892593 
25902594Structured outputs use constrained sampling with compiled grammar artifacts. This introduces some performance characteristics to be aware of:
25912595 
2592* **First request latency:** The first time you use a specific schema, there is additional latency while the grammar compiles
2596* **First request latency:** The first time you use a specific schema, there is additional latency while the grammar compiles.
25932597 
2594* **Automatic caching:** Compiled grammars are cached for 24 hours from last use, making subsequent requests much faster
2598* **Automatic caching:** Compiled grammars are cached for 24 hours from last use, making subsequent requests much faster.
25952599 
25962600* **Cache invalidation:** The cache is invalidated if you change:
25972601 
from line 2607
26032607 
26042608When using structured outputs, Claude automatically receives an additional system prompt explaining the expected output format. This means:
26052609 
2606* Your input token count is slightly higher
2607* The injected prompt costs you tokens like any other system prompt
2608* Changing the `output_config.format` parameter will invalidate any [prompt cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) for that conversation thread
2610* Your input token count is slightly higher.
2611* The injected prompt costs you tokens like any other system prompt.
2612* Changing the `output_config.format` parameter will invalidate any [prompt cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) for that conversation thread.
26092613 
26102614### JSON Schema limitations
26112615 
from line 2617
26132617 
26142618<Accordion title="Supported features">
26152619 * All basic types: object, array, string, integer, number, boolean, null
2616 * `enum` (strings, numbers, bools, or nulls only - no complex types). For a capitalization caveat, see [Invalid outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#invalid-outputs).
2620 * `enum` (strings, numbers, Booleans, or nulls only, no complex types). For a capitalization caveat, see [Invalid outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#invalid-outputs).
26172621 * `const`
2618 * `anyOf` and `allOf` (with limitations - `allOf` with `$ref` not supported)
2622 * `anyOf` and `allOf` (with limitations: `allOf` with `$ref` not supported)
26192623 * `$ref`, `$def`, and `definitions` (external `$ref` not supported)
26202624 * `default` property for all supported types
26212625 * `required` and `additionalProperties` (must be set to `false` for objects)
from line 2654
26502654 * Word boundaries: `\b`, `\B`
26512655 * Complex `{n,m}` quantifiers with large ranges
26522656 
2653 Simple regex patterns work well. Complex patterns may result in 400 errors.
2657 Simple regex patterns work well. Complex patterns might result in 400 errors.
26542658</Accordion>
26552659 
26562660<Tip>
from line 2703
26992703 
27002704### Invalid outputs
27012705 
2702While structured outputs guarantee schema compliance in most cases, there are scenarios where the output may not match your schema:
2706Although structured outputs guarantee schema compliance in most cases, there are scenarios where the output might not match your schema:
27032707 
27042708**Refusals** (`stop_reason: "refusal"`)
27052709 
from line 2712
27082712* The response has `stop_reason: "refusal"`
27092713* You'll receive a 200 status code
27102714* You'll be billed for the tokens generated
2711* The output may not match your schema because the refusal message takes precedence over schema constraints
2715* The output might not match your schema because the refusal message takes precedence over schema constraints
27122716 
2713A property that asks for the model's thinking or step-by-step reasoning may lead to a `reasoning_extraction` refusal. Ask for a short explanation instead. See [Keep reasoning in thinking blocks](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks).
2717A property that asks for the model's thinking or step-by-step reasoning might lead to a `reasoning_extraction` refusal. Ask for a short explanation instead. See [Keep reasoning in thinking blocks](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks).
27142718 
27152719**Token limit reached** (`stop_reason: "max_tokens"`)
27162720 
2717If the response is cut off due to reaching the `max_tokens` limit:
2721If the response is cut off because it reached the `max_tokens` limit:
27182722 
27192723* The response has `stop_reason: "max_tokens"`
2720* The output may be incomplete and not match your schema
2724* The output might be incomplete and not match your schema
27212725* Retry with a higher `max_tokens` value to get the complete structured output
27222726 
27232727**Enum value casing**
27242728 
2725Structured outputs don't guarantee the capitalization of string `enum` and `const` values: Claude may return a value that differs from your schema only in capitalization, typically in the first letter of a word following a space. For example, given this schema:
2729Structured outputs don't guarantee the capitalization of string `enum` and `const` values: Claude might return a value that differs from your schema only in capitalization, typically in the first letter of a word following a space. For example, given this schema:
27262730 
27272731```json
27282732{
from line 2735
27312735}
27322736```
27332737 
2734The output may contain `"Conversation Topic 3"` (capital "T") even though that exact value isn't in the enum. The response completes normally, with no error and no special `stop_reason`. This applies to both JSON outputs and strict tool use. Compare enum values case-insensitively, and avoid enum values that differ only in capitalization.
2738The output might contain `"Conversation Topic 3"` (capital "T") even though that exact value isn't in the enum. The response completes normally, with no error and no special `stop_reason`. This applies to both JSON outputs and strict tool use. Compare enum values case-insensitively, and avoid enum values that differ only in capitalization.
27352739 
27362740### Schema complexity limits
27372741 
from line 2757
27532757 
27542758#### Additional internal limits
27552759 
2756Beyond the explicit limits in the preceding table, there are additional internal limits on the compiled grammar size. These limits exist because schema complexity doesn't reduce to a single dimension: features like optional parameters, union types, nested objects, and number of tools interact with each other in ways that can make the compiled grammar disproportionately large.
2760Beyond the explicit limits in the preceding table, there are additional internal limits on the compiled grammar size. These limits exist because schema complexity doesn't reduce to a single dimension: features such as optional parameters, union types, nested objects, and number of tools interact with each other in ways that can make the compiled grammar disproportionately large.
27572761 
2758When these limits are exceeded, you'll receive a 400 error with the message "Schema is too complex for compilation." These errors mean the combined complexity of your schemas exceeds what can be efficiently compiled, even if each individual limit in the preceding table is satisfied. As a final stop-gap, the API also enforces a **compilation timeout of 180 seconds**. Schemas that pass all explicit checks but produce very large compiled grammars may hit this timeout.
2762When these limits are exceeded, you'll receive a 400 error with the message "Schema is too complex for compilation." These errors mean the combined complexity of your schemas exceeds what can be efficiently compiled, even if each individual limit in the preceding table is satisfied. As a final stop-gap, the API also enforces a **compilation timeout of 180 seconds**. Schemas that pass all explicit checks but produce very large compiled grammars might hit this timeout.
27592763 
27602764#### Tips for reducing schema complexity
27612765 
27622766If you're hitting complexity limits, try these strategies in order:
27632767 
27641. **Mark only critical tools as strict.** If you have many tools, reserve it for tools where schema violations cause real problems, and rely on Claude's natural adherence for simpler tools.
27681. **Mark only critical tools as strict.** If you have many tools, reserve strict tool use for those where schema violations cause real problems, and rely on Claude's natural adherence for simpler tools.
27652769 
276627702. **Reduce optional parameters.** Make parameters `required` where possible. Each optional parameter roughly doubles a portion of the grammar's state space. If a parameter always has a reasonable default, consider making it required and having Claude provide that default explicitly.
27672771 
276827723. **Simplify nested structures.** Deeply nested objects with optional fields compound the complexity. Flatten structures where possible.
27692773 
27704. **Split into multiple requests.** If you have many strict tools, consider splitting them across separate requests or sub-agents.
27744. **Split into multiple requests.** If you have many strict tools, consider splitting them across separate requests or subagents.
27712775 
27722776For persistent issues with valid schemas, [contact support](https://support.claude.com/en/articles/9015913-how-to-get-support) with your schema definition.
27732777 
27742778## Migrating from the beta
27752779 
2776The `output_format` parameter has moved to `output_config.format`, and beta headers are no longer required. The `output_format` parameter is deprecated and will be removed in the future. To use it anyway, add the `structured-outputs-2025-11-13` beta header. Without it, the API returns a 400 error.
2780The `output_format` parameter has moved to `output_config.format`, and beta headers are no longer required. The `output_format` parameter is deprecated. To use it anyway, add the `structured-outputs-2025-11-13` beta header. Without it, the API returns a 400 error.
27772781 
27782782The Python SDK (v1.0 and later) does not accept `output_format={...}` on `client.beta.messages.create()` or `count_tokens()` and raises a `TypeError`. Use `output_config` instead. See [Using a raw JSON schema](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#using-a-raw-json-schema) for the updated API shape.
27792783 
from line 2793
27892793 
27902794**Works with:**
27912795 
2792* **[Batch processing](https://platform.claude.com/docs/en/build-with-claude/batch-processing):** Process structured outputs at scale with 50% discount
2796* **[Batch processing](https://platform.claude.com/docs/en/build-with-claude/batch-processing):** Process structured outputs at scale with a 50 percent discount
27932797* **[Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting):** Count tokens without compilation
27942798* **[Streaming](https://platform.claude.com/docs/en/build-with-claude/streaming):** Stream structured outputs like normal responses
27952799* **[Combined usage](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#using-both-features-together):** Use JSON outputs (`output_config.format`) and strict tool use (`strict: true`) together in the same request
from line 2801
27972801**Incompatible with:**
27982802 
27992803* **[Citations](https://platform.claude.com/docs/en/build-with-claude/citations):** Citations require interleaving citation blocks with text, which conflicts with strict JSON schema constraints. Returns 400 error if citations enabled with `output_config.format`.
2800* **Message Prefilling:** Incompatible with JSON outputs
2804* **Message prefilling:** Incompatible with JSON outputs
28012805 
28022806<Tip>
28032807 **Grammar scope:** Grammars apply only to Claude's direct output, not to tool use calls, tool results, or thinking tags (when using [thinking](https://platform.claude.com/docs/en/build-with-claude/thinking)). Grammar state resets between sections, allowing Claude to think freely while still producing structured output in the final response.
from line 2819
28152819 </Card>
28162820 
28172821 <Card title="Tool use with Claude" icon="wrench" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview">
2818 Connect Claude to external tools and APIs. Learn where tools execute and how the agentic loop works.
2822 Connect Claude to external tools and APIs. Learn where tools run and how the agentic loop works.
28192823 </Card>
28202824 
28212825 <Card title="Pricing" icon="calculator" href="https://platform.claude.com/docs/en/about-claude/pricing">
Feedback