Understanding Roles and Turns in the Messages API
Every request to the Claude Messages API is built from two ingredients: a system prompt and a list of messages.
The system prompt sets the stage once, at the top level of the request.
The messages list is where the actual conversation lives, and it follows a strict shape: a user turn, then an assistant turn, then user again, and so on.
Understanding this alternating structure is the single most important mental model for working with the API, because almost every bug in a Messages API integration traces back to a misunderstanding of roles and turns.
Summary
- Core Idea: A conversation is a
messagesarray of strictly alternatinguserandassistantturns, plus a separate top-levelsystemprompt that is not part of that array. - Why It Matters: The API validates turn order and role alternation; get it wrong and the request fails before Claude ever sees it.
- Key Concepts: role, turn, system prompt, conversation state, statelessness.
- When to Use: Any time you send a request to
client.messages.create(), whether it's a single question or a long back-and-forth conversation. - Limitations / Trade-offs: The API itself remembers nothing between requests; the alternating structure is a contract you must satisfy yourself on every call.
- Related Topics: the messages array as conversation state, content block types, system prompt formatting.
Foundations
A role is a label on each entry in the messages array that says who is "speaking" in that turn.
There are two roles you send: user, which represents input from a person or your application, and assistant, which represents Claude's own prior replies.
A turn is one complete entry in the array, tagged with a role and carrying content.
The system prompt is a separate concept entirely: it is a top-level system parameter on the request, not a message with a role, and it sets persona, constraints, or output format for the whole conversation rather than representing a back-and-forth exchange.
Here is the smallest possible request, showing where roles and turns fit:
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
system="You are a concise, friendly assistant.",
messages=[
{"role": "user", "content": "What is the capital of France?"},
],
)Notice that system sits outside messages entirely.
The messages array here has exactly one turn, with role user.
That is the simplest valid shape: a single user turn, no assistant turns yet, because Claude has not replied.
Mechanics & Interactions
The API enforces a strict alternation rule on the messages array: the first message must have role user, and roles must alternate strictly from there.
You cannot send two user turns in a row, and you cannot send an assistant turn as the very first entry.
If you violate this, the request fails with a 400 error before any model inference happens - the validation is purely structural, checked against the shape of the array, not against the content inside it.
A second, easy-to-miss detail is that the API is stateless.
Claude does not remember your previous request the next time you call the endpoint.
Every request is evaluated fresh, using only whatever is in that request's messages array.
This means that after Claude replies, if you want to continue the conversation, you must append Claude's reply as a new assistant turn and then add your next question as a new user turn - all in the same array, sent again on the next call.
Request 1: system: "..."
messages: [ user: "What is the capital of France?" ]
-> response: assistant reply ("Paris.")
Request 2: system: "..." (same system prompt)
messages: [ user: "What is the capital of France?",
assistant: "Paris.", (Claude's prior reply, now in the array)
user: "What is its population?" ] (new question)
-> response: assistant reply, aware of "Paris" from contextEach request carries the full history so far.
The array grows by two entries per round trip: one assistant entry appended from the prior response, and one new user entry with your next input.
This is why the mental model matters so much: if you think of the API as "remembering" the conversation, you will be surprised when Claude has no idea what you talked about a moment ago.
The truth is closer to handing Claude a transcript from scratch on every single call, and the transcript is only as complete as what you choose to resend.
Advanced Considerations & Applications
A subtlety worth internalizing early: a turn's content does not have to be a single string.
It can be a list of content blocks, and those blocks can be of different types - text, image, tool_use, or tool_result - mixed within one turn.
A user turn responding to a tool call, for example, typically carries a tool_result block rather than plain text.
An assistant turn that decides to call a tool carries a tool_use block instead of, or alongside, text.
The role/turn alternation rule still applies regardless of what content types are inside each turn - alternation is about the role label, not the content shape.
| Approach | Strength | Weakness | Best Fit |
|---|---|---|---|
| Plain string content | Simplest to read and write | Cannot mix content types in one turn | Simple text-only exchanges |
| List of content blocks | Supports text, images, tool_use, tool_result together | More verbose, requires understanding block types | Vision, tool use, or any mixed-content turn |
The other consequence of statelessness worth planning for early is cost and context growth: because you resend the entire history every time, a long conversation means a growing request body and growing token usage on every single call, even though most of it is identical to the previous call.
That growth is manageable for short exchanges and becomes a real design concern for long-running conversations, which is a topic covered in its own right elsewhere in this section.
Common Misconceptions
- "Claude remembers our earlier conversation automatically." It does not - the Messages API has no server-side memory. Every reply Claude gives is based solely on what you put in that request's
messagesarray. - "The system prompt is just the first user turn." It's a genuinely separate top-level parameter, not part of the alternating
messagesarray, and it isn't subject to the role-alternation rule at all. - "I can send two user messages back to back if I have two things to say." You can't send them as two separate array entries with role
user- either combine them into oneuserturn's content, or wait for anassistantturn in between. - "Turns and content blocks are the same thing." A turn is the role-labeled entry in
messages; a content block is one piece of that turn's content. One turn can hold several blocks of different types.
FAQs
What are the only two roles allowed in the messages array?
user and assistant. The system prompt is configured separately via the top-level system parameter, not as a role inside messages.
Does the messages array need to start with a user turn?
Yes. The first entry must have role user, and roles must strictly alternate user, assistant, user, assistant, and so on from there.
What happens if I send two consecutive turns with the same role?
The API rejects the request with a 400 error before running inference, because the role sequence violates the required alternation.
Does Claude remember what I said in a previous API call?
No. The Messages API is stateless server-side. Claude only "remembers" what is included in the current request's messages array, which is why you resend prior turns on every call.
Where does the system prompt fit relative to the messages array?
It's a separate top-level system parameter on the request, not a turn inside messages. It applies to the whole conversation rather than representing one side of a back-and-forth.
Can a single turn contain more than plain text?
Yes. A turn's content can be a list of content blocks - text, image, tool_use, or tool_result - and a single turn can mix several block types together.
If I want to continue a conversation, what exactly do I add to the array?
Append Claude's prior reply as a new assistant turn, then add your next input as a new user turn, and send the whole array again on your next request.
Is there a performance cost to resending the whole conversation every time?
Yes - since every request carries the full history, both request size and token usage grow as a conversation gets longer, even though most of the content is unchanged from the previous call.
Can an assistant turn be the very first entry in the messages array?
No. The array must begin with a user turn. Sending an assistant turn first is a structural violation and the request fails validation.
Is role alternation checked based on message content or message structure?
It's purely structural - the API checks the sequence of role labels in the array, regardless of what content types or text those turns actually contain.
Why does an assistant turn sometimes contain a tool_use block instead of text?
When Claude decides to call a tool, it expresses that decision as a tool_use content block within its assistant turn, rather than (or alongside) a plain text reply.
What role does a tool result get sent back under?
Tool results are sent back as a tool_result content block inside a user turn - the role alternation rule still applies, so this follows the preceding assistant turn that requested the tool.
Related
- Messages API Basics - send your first multi-turn request end to end.
- Building Multi-Turn Conversations with the Messages Array - the mechanics of resending history on every call.
- Messages API Roles and Content Block Types Reference - a reference table of every content block type.
- Formatting System Prompts for Consistent Claude Behavior - how to write the separate system parameter well.
Stack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5 - and the official
anthropicPython SDK (latest 0.x release). Model names, SDK versions, and pricing move quickly - verify current specifics at platform.claude.com/docs before relying on them.