Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Anthropics Anthropic sdk python BaseModel

From Leeroopedia
Knowledge Sources
Domains SDK_Infrastructure, Data_Modeling
Last Updated 2026-02-15 12:00 GMT

Overview

This page documents the SDK's custom BaseModel class and its associated type construction utilities (construct_type, validate_type) that form the foundational data model layer for all API response types.

Description

The _models.py module extends pydantic.BaseModel with a custom construct() method that recursively builds nested models without validation for performance. This is critical because API responses from a trusted server do not need re-validation, so skipping it provides a significant speed boost. The custom construct() handles field aliases, discriminated unions via cached field-alias lookups, extra fields, and Pydantic v1/v2 compatibility transparently.

The module also defines FinalRequestOptions for encapsulating HTTP request parameters, GenericModel for type-parameterized response models, and utility functions: construct_type() for loose (no-validation) type coercion from raw data, validate_type() for strict validation, and add_request_id() for attaching the request-id header value to response model instances. Convenience methods to_dict() and to_json() are provided for serialization with API-name keys by default.

Usage

All API response types in the SDK (e.g., Message, ContentBlock, Usage) inherit from this BaseModel. It is also available to end users who want to define custom models compatible with the SDK's parsing system. The construct_type() function is the primary entry point used by response processing to turn JSON data into typed model instances.

Code Reference

Source Location

  • Repository: Anthropic SDK Python
  • File: src/anthropic/_models.py
  • Lines: 1-918
  • Key classes: BaseModel (line 97), GenericModel (line 782), FinalRequestOptions (in module)

Signature

class BaseModel(pydantic.BaseModel):
    # Pydantic v2 config
    model_config: ClassVar[ConfigDict] = ConfigDict(
        extra="allow",
        defer_build=coerce_boolean(os.environ.get("DEFER_PYDANTIC_BUILD", "true")),
    )

    _request_id: Optional[str] = None

    def to_dict(
        self,
        *,
        mode: Literal["json", "python"] = "python",
        use_api_names: bool = True,
        exclude_unset: bool = True,
        exclude_defaults: bool = False,
        exclude_none: bool = False,
        warnings: bool = True,
    ) -> dict[str, object]

    def to_json(
        self,
        *,
        indent: int | None = 2,
        use_api_names: bool = True,
        exclude_unset: bool = True,
        exclude_defaults: bool = False,
        exclude_none: bool = False,
        warnings: bool = True,
    ) -> str

    @classmethod
    def construct(
        cls: Type[ModelT],
        _fields_set: set[str] | None = None,
        **values: object,
    ) -> ModelT


def construct_type(*, type_: type[_T], value: object) -> _T

def validate_type(*, type_: type[_T], value: object) -> _T

def add_request_id(obj: BaseModel, request_id: str | None) -> None

Import

from anthropic import BaseModel
from anthropic._models import construct_type, validate_type, GenericModel, FinalRequestOptions

I/O Contract

Inputs (construct_type)

Name Type Required Description
type_ type[_T] Yes The target type to construct (e.g., Message, list[ContentBlock], Union[...])
value object Yes The raw data (typically a dict from JSON parsing) to coerce into the target type

Inputs (validate_type)

Name Type Required Description
type_ type[_T] Yes The target type to validate against
value object Yes The raw data to strictly validate

Outputs

Name Type Description
construct_type() return _T A constructed instance of the target type, built without validation for performance
validate_type() return _T A validated instance of the target type, using Pydantic's full validation
to_dict() return dict[str, object] Dictionary representation using API field names by default
to_json() return str JSON string representation using API field names by default

Custom construct() Method

The overridden construct() method recursively builds nested models without running Pydantic validation:

@classmethod
def construct(cls, _fields_set=None, **values):
    m = cls.__new__(cls)
    fields_values = {}

    # Resolve field aliases and populate_by_name config
    model_fields = get_model_fields(cls)
    for name, field in model_fields.items():
        key = field.alias
        if key is None or (key not in values and populate_by_name):
            key = name
        if key in values:
            fields_values[name] = _construct_field(value=values[key], field=field, key=key)
            _fields_set.add(name)
        else:
            fields_values[name] = field_get_default(field)

    # Handle extra fields (not in the model schema)
    extra_field_type = _get_extra_fields_type(cls)
    _extra = {}
    for key, value in values.items():
        if key not in model_fields:
            parsed = construct_type(value=value, type_=extra_field_type) if extra_field_type else value
            _extra[key] = parsed

    object.__setattr__(m, "__dict__", fields_values)
    # Set Pydantic v1 or v2 internal attributes
    return m

Discriminated Union Support

The module includes a caching mechanism for discriminated union resolution. When a union type has a discriminator field, the system:

  1. Extracts the discriminator field name from PropertyInfo metadata
  2. Builds a mapping from discriminator values to their corresponding model types
  3. Caches the mapping in DISCRIMINATOR_CACHE for reuse
  4. Uses the mapping during construct_type() to select the correct variant

Usage Examples

Accessing Response Model Data

import anthropic

client = anthropic.Anthropic()
message = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}],
)

# message is a BaseModel instance with _request_id attached
print(message._request_id)  # "req_xxx"

# Serialize to dict with API field names
data = message.to_dict()

# Serialize to JSON string
json_str = message.to_json()

# Serialize with Python field names instead
data = message.to_dict(use_api_names=False)

Custom Model Subclass

from anthropic import BaseModel

class MyCustomResponse(BaseModel):
    foo: str
    bar_baz: int

# construct() builds without validation -- fast
obj = MyCustomResponse.construct(foo="hello", bar_baz=42)

Dependencies

  • pydantic -- Base model class, field info, validation (v1 and v2 compatible)
  • typing_extensions -- Literal, ClassVar, Protocol, override
  • os -- Reading DEFER_PYDANTIC_BUILD environment variable

Related Pages

Used By

Uses

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment