Follow Discord
Sweep 10 Nov 2026 · 02:18Z Build v2.1.322 539 read Stable v2.1.311 Latest v2.1.322 Next v2.1.322 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-code

Get structured output from agents changedagent-sdk/structured-outputs

Nearest release: v2.1.322, published 15 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 10 Nov 2026 17:24 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 10 Nov 2026 17:37 UTC.

Upstream edited
Recorded here
Lines+34added
Lines−13removed
From line 77 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits12to this page, all time

The whole hunk

from line 77, old and new numbered
/
lines
from line 77
7777 }
7878 })) {
7979 // The result message contains structured_output with validated data
80 if (message.type === "result" && message.subtype === "success" && message.structured_output) {
80 if (message.type === "result" && message.subtype === "success" && !message.is_error && message.structured_output) {
8181 console.log(message.structured_output);
8282 // { company_name: "Anthropic", founded_year: 2021, headquarters: "San Francisco, CA" }
8383 }
from line 114
114114 ),
115115 ):
116116 # The result message contains structured_output with validated data
117 if isinstance(message, ResultMessage) and message.structured_output:
117 if (
118 isinstance(message, ResultMessage)
119 and not message.is_error
120 and message.structured_output
121 ):
118122 print(message.structured_output)
119123 # {'company_name': 'Anthropic', 'founded_year': 2021, 'headquarters': 'San Francisco, CA'}
120124 except Exception as error:
from line 173
169173 }
170174 }
171175 })) {
172 if (message.type === "result" && message.subtype === "success" && message.structured_output) {
176 if (message.type === "result" && message.subtype === "success" && !message.is_error && message.structured_output) {
173177 // Validate and get fully typed result
174178 const parsed = FeaturePlan.safeParse(message.structured_output);
175179 if (parsed.success) {
from line 223
219223 }
220224 ),
221225 ):
222 if isinstance(message, ResultMessage) and message.structured_output:
226 if (
227 isinstance(message, ResultMessage)
228 and not message.is_error
229 and message.structured_output
230 ):
223231 # Validate and get fully typed result
224232 plan = FeaturePlan.model_validate(message.structured_output)
225233 print(f"Feature: {plan.feature_name}")
from line 301
293301 }
294302 }
295303 })) {
296 if (message.type === "result" && message.subtype === "success" && message.structured_output) {
304 if (message.type === "result" && message.subtype === "success" && !message.is_error && message.structured_output) {
297305 const data = message.structured_output as { total_count: number; todos: Array<{ file: string; line: number; text: string; author?: string; date?: string }> };
298306 console.log(`Found ${data.total_count} TODOs`);
299307 data.todos.forEach((todo) => {
from line 356
348356 output_format={"type": "json_schema", "schema": todo_schema}
349357 ),
350358 ):
351 if isinstance(message, ResultMessage) and message.structured_output:
359 if (
360 isinstance(message, ResultMessage)
361 and not message.is_error
362 and message.structured_output
363 ):
352364 data = message.structured_output
353365 print(f"Found {data['total_count']} TODOs")
354366 for todo in data["todos"]:
from line 391
379391 
380392Structured output generation can fail when the agent cannot produce valid JSON matching your schema. This typically happens when the schema is too complex for the task, the task itself is ambiguous, or the agent hits its retry limit trying to fix validation errors. It can also happen without any validation failure: a [model fallback](https://code.claude.com/docs/en/model-config.md#automatic-model-fallback) can retract an already-completed output mid-stream, and if no retry replaces it the run ends with the same error. Check the `errors` list on the error result message to tell the two causes apart before debugging your schema.
381393 
382When an error occurs, the result message has a `subtype` indicating what went wrong:
394Check the result message's `subtype`:
383395 
384396| Subtype | Meaning |
385397| - | - |
386| `success` | Output was generated and validated successfully |
398| `success` | The run ended without an error subtype |
387399| `error_max_structured_output_retries` | No valid output remained after multiple attempts (validation failures, or a model-fallback retraction with no successful retry) |
388400 
389A result can also end with subtype `success` but no `structured_output` value, for example when the run completes without the agent producing a structured output. Treat that case as a failure as well. The troubleshooting entry [structured\_output is None but the result says success](https://code.claude.com/docs/en/agent-sdk/troubleshooting.md#structured_output-is-none-but-the-result-says-success) covers this case. The example below treats a result as successful only when the `subtype` is `success` and `structured_output` is present, and handles every other result as a failure:
401A `success` subtype doesn't by itself mean the run produced an answer. Treat a result as a failure when the result's `is_error` is `true` or `structured_output` is absent:
390402 
403* **`is_error` on the result is `true`**: for example, the final model request ended in an API error or a refusal. Don't use a `structured_output` value on such a result.
404* **`structured_output` is absent**: to find the cause, see [structured\_output is None but the result says success](https://code.claude.com/docs/en/agent-sdk/troubleshooting.md#structured_output-is-none-but-the-result-says-success)
405 
406The example below applies these checks:
407 
391408```typescript TypeScript theme={null}
392409import { query } from "@anthropic-ai/claude-agent-sdk";
393410 
from line 428
411428 }
412429 })) {
413430 if (msg.type === "result") {
414 if (msg.subtype === "success" && msg.structured_output) {
431 if (msg.subtype === "success" && !msg.is_error && msg.structured_output) {
415432 // Use the validated output
416433 console.log(msg.structured_output);
417434 } else if (msg.subtype === "error_max_structured_output_retries") {
418435 console.error("Could not produce valid output");
419436 } else {
420 console.error("Run ended without a structured output");
437 console.error("Run ended with an error or without a structured output");
421438 }
422439 }
423440 }
from line 469
452469 ),
453470 ):
454471 if isinstance(message, ResultMessage):
455 if message.subtype == "success" and message.structured_output:
472 if (
473 message.subtype == "success"
474 and not message.is_error
475 and message.structured_output
476 ):
456477 # Use the validated output
457478 print(message.structured_output)
458479 elif message.subtype == "error_max_structured_output_retries":
459480 print("Could not produce valid output")
460481 else:
461 print("Run ended without a structured output")
482 print("Run ended with an error or without a structured output")
462483 except Exception as error:
463484 # A single-shot query() raises after yielding an error result. If the
464485 # failure was an error result, the error subtype branches above have
Feedback