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

  1. Start with a user message.
  2. Append Claude's reply as an assistant message.
  3. Add the next user message.
  4. Send the whole array again.

Rules

  • The first message must be from user.
  • Roles alternate between user and assistant.
  • Store the history in your app (in memory, a session, or a database).

Example

Example · javascript
// 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 included

When 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.

Example · javascript
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.

Example · javascript
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.

Example · javascript
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

  • Be the first to comment on this lesson.