AnthropicClaude Certified Architect – Foundations2026-100 Prerequisites
Read Messages as typed content blocks
Completed by the knowledge check
Learning objective
Represent Claude Messages API requests, responses, roles, and content blocks, and carry conversation history across stateless calls.
Core idea
The Messages API exchanges structured messages, not chat strings. A request selects a model, supplies instructions and conversation, and bounds generation. A response wraps one assistant message with typed content, a stopping reason and token usage.
The API is also stateless. You always send the full conversational history. A later call does not inherit an earlier one because it uses the same API key, model or response id: your application owns the record, and continuity is whatever you put in messages.
How it works
The request
POST /v1/messages takes model, max_tokens and messages. Instructions that apply from the start go in the top-level system field.
{
"model": "MODEL_ID",
"max_tokens": 512,
"system": "Answer only from the supplied policy text.",
"messages": [
{ "role": "user", "content": "My order reference is ORDER_123." },
{
"role": "assistant",
"content": [{ "type": "text", "text": "What would you like to check?" }]
},
{ "role": "user", "content": "Does that order qualify for a refund?" }
]
}Each message has a role and content. A string content is shorthand for one text block; the array form holds typed blocks such as text, images and documents.
Roles
Conversation alternates role: "user" and role: "assistant", and the API combines consecutive turns of the same role into one. There is no "system" role for input messages. Mid-conversation system messages add a role: "system" message on the models their page lists, not on Claude Sonnet 5, where top-level system remains the only place for instructions.
Earlier turns need not come from Claude: Anthropic permits synthetic assistant messages, so you author the history you send.
The response
A non-streaming response carries id, type: "message", role: "assistant", model, content, stop_reason, stop_sequence and usage. content is an array: a text block has text; a client-tool request is a tool_use block with id, name and input.
stop_reason says why generation ended — end_turn, max_tokens and tool_use among its values; 1.1.1 drives the loop from it. usage reports input_tokens and output_tokens; see 0.1 for budgeting.
Carrying history
On the next turn, send the prior user message, the stored assistant content under role: "assistant", and the new user message, in order. Store the block array, not the rendered text: a string drops tool_use blocks, and a thinking block you pass back must be unmodified, signature included, or the API returns a 400 invalid_request_error. A tool_result goes back in a user message whose tool_use_id matches the tool_use block’s id, not the response id; 1.1.2 owns that pairing and its ordering rules. Replay and compaction across long conversations belong to 5.1.1.
Each call sends the full conversational history, because a later call does not inherit an earlier one.
Key distinctions and trade-offs
| Pair | Difference |
|---|---|
| Role vs block type | A role names the speaker; a block type names the content. A tool result is a tool_result block in a user message, not a tool role. |
Response id vs conversation key | The id identifies one generated message. Your own key loads the stored history. |
Architecture / decision scenario
A support service sends only “Can I get a refund for it?” on the second call, plus the previous response id, and stores every response as one text string. You make the request builder serialize the stored user and assistant content into messages, and the response adapter show text blocks, route tool_use blocks to their handler, and mark the answer complete only after checking stop_reason.
Common exam traps
- Sending only the newest turn because earlier ones are stored in the application.
- Treating an API key, a model or a response
idas a session. - Putting initial instructions in a first
messagesentry, or assumingrole: "system"works on every model. - Assuming every response has exactly one
textblock. - Treating a
tool_useblock as a completed operation, or inventing atoolrole.
What to remember
Model the envelope, roles and block types separately. Use top-level system for initial instructions, inspect every block, branch on stop_reason, and rebuild messages from your own structured record on every call.
Knowledge check
A support service sends only the customer’s newest message on the second call, together with the id of the first response. Claude answers as if the conversation had just begun. Which change restores the conversation?
user and assistant turns in messagesid in the follow-up request metadatamessages on each call. A response id names one generated message, and an API key or a model is not a session. Prompt caching speeds up a repeated prefix you still send; it does not supply turns you leave out.A service saves each response as the joined text of its content and replays that string as the assistant turn on the next call. After turns in which Claude requested a tool, the follow-up calls go wrong. What should the service store for each response?
idtext block of the responsetool rolecontent block array, unchangedtool_use blocks that later tool_result blocks must pair with, and a thinking block passed back must be unmodified. Storing the block array keeps every block intact. A response can hold several blocks, so keeping only one loses content, and the API has no tool role.Claude’s response has id: "msg_A" and a content block { "type": "tool_use", "id": "toolu_B", "name": "lookup_order", ... }. Your handler has the lookup result. How do you send it back?
tool_result block in a user message, with tool_use_id: "msg_A"tool_result block in a user message, with tool_use_id: "toolu_B"tool_result block in an assistant message, with tool_use_id: "toolu_B"role: "tool" that references "toolu_B"user message, and its tool_use_id matches the id of the tool_use block. The response id identifies the whole generated message, not the tool request inside it.A response adapter shows content[0].text as the answer and marks the turn complete. Some responses begin with a short text block followed by a tool_use block. Which change to the adapter handles these responses correctly?
text instead of the first block’smax_tokens so each reply fits in one blockstop_reason before completingtext block per replycontent is an array of typed blocks, and nothing guarantees exactly one text block. The adapter must route each block by type and use stop_reason — tool_use here — to decide whether the turn is finished. A prompt instruction does not change the response format the code must handle.References
- Anthropic, Messages
- Anthropic, Using the Messages API
- Anthropic, Mid-conversation system messages
- Anthropic, Tool use with Claude