Principle:Anthropics Anthropic sdk python Parsed Output Access
| Knowledge Sources | |
|---|---|
| Domains | Structured_Output, LLM, Data_Extraction |
| Last Updated | 2026-02-15 00:00 GMT |
Overview
The Parsed Output Access principle describes how the SDK provides type-safe access to deserialized structured data through generic typed response containers. Rather than requiring developers to manually extract and parse JSON from response content blocks, the SDK introduces extended message and content block types that carry validated Pydantic model instances directly, accessible via a simple parsed_output property.
Generic Typed Response Containers for Structured Data
The Anthropic API returns responses as Message objects containing a list of content blocks (text, tool use, thinking, etc.). When structured output is requested, the model's JSON response appears as the text field within a TextBlock. Without typed containers, the developer must:
- Iterate through content blocks to find the text block.
- Extract the raw JSON string.
- Parse it manually.
- Validate it against their expected type.
The SDK eliminates this boilerplate by introducing generic container types that are parameterized by the developer's output type (ResponseFormatT). These containers extend the standard API response types with an additional parsed_output attribute that holds the already-validated Pydantic model instance.
The generic type parameter ResponseFormatT serves dual purposes:
- At runtime: It determines which Pydantic model class is used to validate the JSON text via
TypeAdapter(ResponseFormatT).validate_json(text). - At type-check time: It provides IDE autocompletion and static type checking for the
parsed_outputproperty, somessage.parsed_outputis known to be of typeResponseFormatT(orNone).
ParsedMessage Extending Message with parsed_output Property
The SDK uses class inheritance to extend the standard response types without breaking API compatibility:
ParsedTextBlock
ParsedTextBlock extends TextBlock with a single additional attribute: parsed_output: Optional[ResponseFormatT]. This attribute defaults to None and is populated by the parsing logic when structured output is successfully validated. It is excluded from API serialization via __api_exclude__, ensuring it never appears in wire-format data.
ParsedMessage
ParsedMessage extends Message by overriding the content field to use ParsedContentBlock[ResponseFormatT] (a union that includes ParsedTextBlock alongside the standard block types). It adds a convenience parsed_output property that automatically finds and returns the first parsed output from its content blocks.
This design has several important properties:
- Backward compatibility: Since
ParsedMessageextendsMessage, it can be used anywhere aMessageis expected. All existingMessageattributes (id, model, stop_reason, usage, etc.) remain accessible. - Transparent augmentation: The parsed output is added alongside the original data, not instead of it. The raw
textfield is still available on theParsedTextBlockfor inspection or logging. - Discriminated unions: The
ParsedContentBlockunion uses thetypefield as a discriminator, so Pydantic can efficiently determine which block type to instantiate during deserialization.
Type-Safe Access to Deserialized Pydantic Model Instances
The parsed_output property on ParsedMessage provides a zero-ceremony access pattern for retrieving the validated output:
review = message.parsed_output # Returns Optional[MovieReview]
This property iterates through the message's content blocks and returns the parsed_output from the first TextBlock that has a truthy (non-None) parsed output. This design handles the common case where the model produces a single text block containing the structured output.
The type safety guarantee flows through the entire chain:
- The developer specifies
output_format=MovieReviewat the call site. - The return type becomes
ParsedMessage[MovieReview]. - The
parsed_outputproperty returnsOptional[MovieReview]. - The developer gets full IDE autocompletion on the resulting object's fields.
If the model's response does not contain any valid structured output (e.g., the stop reason is max_tokens before completing the JSON), parsed_output returns None, which the developer can check gracefully.
Validation via TypeAdapter
The actual deserialization and validation is performed by the parse_text() function, which uses Pydantic's TypeAdapter.validate_json():
adapted_type = TypeAdapter(output_format)
return adapted_type.validate_json(text)
validate_json() is used rather than model_validate_json() because TypeAdapter supports arbitrary types beyond just BaseModel subclasses. This means developers could theoretically use simple types like list[str] or dict[str, int] as their output format, though BaseModel subclasses are the primary use case.
If validation fails (the JSON does not conform to the expected type), Pydantic raises a ValidationError, which propagates to the caller. This ensures that the parsed_output attribute, when non-None, is guaranteed to be a valid instance of the declared type.