Multi-Turn Conversations
The API is stateless — send the whole message history each time to continue a conversation.
Claude does not remember previous requests. To hold a back-and-forth conversation, you keep the history and send all of it on every call.
How it works
- Start with a
usermessage. - Append Claude's reply as an
assistantmessage. - Add the next
usermessage. - Send the whole array again.
Rules
- The first message must be from
user. - Roles alternate between
userandassistant. - Store the history in your app (in memory, a session, or a database).
Example
// Keep the running history in your app
const messages = [
{ role: "user", content: "My name is Alice." },
];
let res = await client.messages.create({
model: "claude-opus-4-8", max_tokens: 256, messages,
});
messages.push({ role: "assistant", content: res.content });
// Next turn: add the new question and resend everything
messages.push({ role: "user", content: "What's my name?" });
res = await client.messages.create({
model: "claude-opus-4-8", max_tokens: 256, messages,
});
// Claude answers "Alice" because the history was includedWhen to use it
- Build a multi-turn code-review assistant that remembers earlier snippets the user shared in the same session.
- Implement a support chatbot that recalls the user's account tier from the first message in subsequent questions.
- Create a step-by-step recipe assistant where each user message can reference previous instructions.
More examples
Maintain conversation history array
Keeps a history array and appends each turn so every request contains the full conversation.
const history = [];
async function chat(userMessage) {
history.push({ role: "user", content: userMessage });
const msg = await client.messages.create({
model: "claude-haiku-4-5",
max_tokens: 256,
messages: history,
});
history.push({ role: "assistant", content: msg.content[0].text });
return msg.content[0].text;
}Two-turn conversation example
Demonstrates that Claude answers turn 2 correctly only because turn 1 was included in the messages array.
const messages = [];
// Turn 1
messages.push({ role: "user", content: "My name is Alex." });
let res = await client.messages.create({ model: "claude-haiku-4-5", max_tokens: 64, messages });
messages.push({ role: "assistant", content: res.content[0].text });
// Turn 2 — Claude should remember the name
messages.push({ role: "user", content: "What is my name?" });
res = await client.messages.create({ model: "claude-haiku-4-5", max_tokens: 64, messages });
console.log(res.content[0].text); // "Your name is Alex."Trim history to manage token costs
Caps the history length to avoid ever-growing token costs while keeping recent context.
const MAX_TURNS = 10;
function addAndTrim(history, role, content) {
history.push({ role, content });
// Keep only the last MAX_TURNS pairs (20 messages)
if (history.length > MAX_TURNS * 2) {
history.splice(0, history.length - MAX_TURNS * 2);
}
return history;
}
Discussion