3.0 What This Teaches
messages.create takes a list of messages that represents
the conversation so far. Understanding the structure of that list is how you build
multi-turn conversations and control what the model knows. This tutorial covers:
- The role/content pair format for each message
- The
userandassistantroles - How to build a multi-turn conversation by appending to the list
- Why the model has no memory between independent calls
- Inspecting the conversation history at any point
3.1 The Messages List
messages parameter is a list of dicts. Each dict has two keys:
"role"- either"user"or"assistant""content"- the text of that turn
messages = [
{"role": "user", "content": "What is a Python list?"},
{"role": "assistant", "content": "A list is an ordered, mutable collection..."},
{"role": "user", "content": "How do I append to one?"},
]
user message and roles must strictly
alternate: user, assistant, user, assistant, and so on. Sending two consecutive
user messages without an assistant turn in between is an API error.
3.2 A Single-Turn Call
# single_turn.py - one question, one answer.
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=256,
messages=[
{"role": "user", "content": "What is a Python list?"}
]
)
print(response.content[0].text)
3.3 Building a Multi-Turn Conversation
messages.create again with the full updated list:
# multi_turn.py - two-turn conversation.
import anthropic
client = anthropic.Anthropic()
messages = [
{"role": "user", "content": "What is a Python list?"}
]
# First turn
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=256,
messages=messages
)
answer1 = response.content[0].text
print("Turn 1:", answer1)
# Append assistant reply, then ask a follow-up
messages.append({"role": "assistant", "content": answer1})
messages.append({"role": "user", "content": "How do I append to one?"})
# Second turn - passes full history so the model has context
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=256,
messages=messages
)
answer2 = response.content[0].text
print("Turn 2:", answer2)
3.4 No Built-In Memory
# Each of these calls knows nothing about the other.
response1 = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=64,
messages=[{"role": "user", "content": "My name is Alex."}]
)
response2 = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=64,
messages=[{"role": "user", "content": "What is my name?"}]
)
# response2 will say it does not know - there is no shared state.
3.5 Inspecting the History
# Print the conversation so far in a readable format.
for msg in messages:
role = msg["role"].upper()
print(f"[{role}] {msg['content'][:80]}")
print()
3.6 Exercise
Exercise
Write a script that carries out a three-turn conversation: ask the model to
explain recursion, then ask for a code example, then ask it to add a base-case
comment to that example. Append each response to the messages list before
sending the next turn. Print all three answers.
3.7 Common Mistakes
Two consecutive user messages
messages = [
{"role": "user", "content": "Hello"},
{"role": "user", "content": "Are you there?"}, # API error
]
Forgetting to append the assistant reply before the next user turn
messages.append({"role": "user", "content": "Follow-up"}) # missing assistant turn
Mutating the messages list across unrelated requests
messages list for two different conversations,
they share history. Start a fresh list for each independent conversation.
3.8 Key Terms
| Term | Meaning |
|---|---|
| role | "user" for human turns, "assistant" for model turns |
| content | The text of one turn in the conversation |
| multi-turn conversation | A call where messages contains more than one exchange |
| stateless API | Each request is independent; the server stores no session between calls |
| conversation history | The full list of prior messages your application maintains and passes on each call |
| alternating roles | The required pattern: user, assistant, user, assistant... |