Principle:Anthropics Anthropic sdk python Message Request Construction
| Knowledge Sources | |
|---|---|
| Domains | API_Client, LLM |
| Last Updated | 2026-02-15 00:00 GMT |
Overview
The Message Request Construction principle describes how the Anthropic Python SDK uses Python's TypedDict system to build structurally typed request bodies that map directly to the JSON payloads expected by the Messages API. This approach provides compile-time parameter validation through static type checkers while keeping the runtime representation as plain dictionaries.
Theoretical Basis
Structural Type Safety with TypedDict
The SDK defines request parameters as TypedDict subclasses rather than Pydantic models or plain dictionaries. This design choice offers several advantages:
- Zero runtime overhead -- TypedDicts are ordinary Python dicts at runtime; no object construction, validation, or serialization cost is incurred until the SDK explicitly transforms them.
- IDE autocompletion -- Type checkers (mypy, pyright) and IDEs can offer field-level autocomplete and flag missing or mistyped keys at development time.
- JSON mapping -- The TypedDict fields map one-to-one to the JSON keys in the API request body, making the SDK surface a transparent projection of the REST API schema.
Required[] Typed Fields
The SDK uses typing_extensions.Required[] annotations within TypedDict(total=False) classes to precisely separate mandatory from optional parameters:
- Required fields --
max_tokens,messages, andmodelare annotated withRequired[T], meaning a type checker will report an error if they are omitted. - Optional fields -- All other fields (e.g.,
temperature,system,tools) are implicitly optional because the base class usestotal=False.
This pattern ensures that the three fields the API always requires are enforced at the type level, while every other field can be omitted without a type error.
Base-Streaming-NonStreaming Hierarchy
Request parameter types are organized into a three-level hierarchy:
MessageCreateParamsBase-- Contains all common fields shared by both streaming and non-streaming requests. Usestotal=FalsewithRequired[]for the three mandatory fields.MessageCreateParamsNonStreaming-- Extends the base and addsstream: Literal[False]as an optional field.MessageCreateParamsStreaming-- Extends the base and addsstream: Required[Literal[True]]as a required field.
The union MessageCreateParams = Union[MessageCreateParamsNonStreaming, MessageCreateParamsStreaming] represents the full space of valid request shapes. This discriminated union on the stream field allows the SDK to select the correct return type (Message vs Stream[RawMessageStreamEvent]) based on the parameter variant.
How TypedDicts Map to JSON API Request Bodies
When a user constructs a parameters dict and passes it to Messages.create(), the SDK calls maybe_transform() to convert the TypedDict into the final JSON-serializable dictionary. The transformation step handles:
- Omission of unset fields -- Fields that were not provided (represented by sentinel
omit/NOT_GIVENvalues) are stripped from the request body so the API receives only explicitly set values. - Iterable-to-list conversion -- Fields typed as
Iterable[T](such asmessagesandtools) are materialized into concrete lists. - Nested type coercion -- Nested TypedDicts (e.g.,
MessageParam,ToolChoiceParam) are recursively transformed.
Design Constraints
- The
messagesfield acceptsIterable[MessageParam], notList[MessageParam]. This allows generators and other lazy sequences, which is useful for programmatic message construction. - The
modelfield usesModelParam, which is a union of known model string literals and a genericstrfallback, providing autocomplete for known models while remaining forward-compatible with new model releases. - The
systemfield accepts either a plainstror anIterable[TextBlockParam], supporting both simple string system prompts and structured multi-block system prompts with cache control. - A maximum of 100,000 messages is allowed in a single request.