Managing Multi-Turn Conversation Context in Claude API
When you build a chat feature with the Claude API, the model doesn't remember anything between requests on its own. Every call is stateless — Claude only "knows" what's in the messages array you send with that specific request. A multi-turn conversation is something your application constructs by resending the full history (or a trimmed version of it) with each new user message, and the context window is the hard limit on how many tokens — input plus output — that history can contain before the model stops accepting it.
This matters because the two problems are linked: the longer your conversation runs, the more messages you accumulate, and the closer you get to the context window ceiling. Get the mechanics wrong and you'll either blow past the token limit and get an error, or silently lose early context the model actually needed. Below is how the message format works, how the context window behaves in practice, and the strategies for keeping long conversations coherent and affordable.
How multi-turn conversations actually work
Claude's API expects a messages array where each entry has a role (user or assistant) and content. To continue a conversation, you append the new user message to the array that already contains the prior turns and send the whole thing again:
[
{ "role": "user", "content": "What's the capital of Portugal?" },
{ "role": "assistant", "content": "Lisbon." },
{ "role": "user", "content": "What's its population?" }
]
There's no session ID, no server-side memory, no "continue my chat" endpoint. The entire conversational state lives in that array, which your backend (or client) is responsible for storing and rebuilding on every call. This is true whether you're calling Anthropic's API directly or going through a layer like SubToAPI — the message structure is the same; see /docs/messages for the exact schema.
What the context window actually limits
The context window is the maximum number of tokens the model can process in a single request — your full conversation history, any system prompt, tool definitions, and the model's own response all count against it. Tokens aren't words: roughly 3–4 characters per token for English text, more for code or non-Latin scripts.
Two practical consequences:
- Input cost grows with every turn. Turn 10 of a conversation re-sends turns 1–9 in full. A chat that starts at 200 tokens and grows by 150 tokens per turn is sending nearly 1,500 tokens of history by turn 10, even if the user's latest message is short.
- You will eventually hit the limit. Long-running chats, documents pasted into the conversation, or agents that accumulate tool results will eventually exceed the window if nothing is trimmed.
If a request exceeds the context window, the API returns an error rather than silently truncating — so this isn't a "quality degrades slowly" problem, it's a hard failure you need to design around.
Strategies for managing long conversations
1. Track token usage per request. Every response includes usage metadata showing input and output token counts. Log this per conversation so you can see growth trends before they become failures, not after.
2. Trim or summarize older turns. A common pattern: once a conversation exceeds N turns or M tokens, collapse the oldest messages into a short summary generated by Claude itself ("Summarize this conversation in 3 sentences, preserving key facts") and replace them with that summary as a single system or user message. This keeps continuity without resending the full transcript forever.
3. Keep the system prompt separate and stable. The system parameter isn't part of the messages array and doesn't need to be re-evaluated each turn — set it once per request alongside your trimmed history rather than folding instructions into the conversation itself.
4. Cap history by relevance, not just recency. For support bots or coding assistants, the last 2–3 turns plus a running summary is often more useful than the full raw log — recent context tends to matter more than the oldest messages.
5. Use streaming for long responses. Streaming doesn't change the context window, but it does let you start processing output before the full response is generated, which matters for UX in long conversational turns. See /docs/streaming for implementation details.
Here's a minimal pattern for trimming history before each call:
function buildMessages(history, maxTurns = 20) {
// keep the last N turns, drop the rest
const trimmed = history.slice(-maxTurns * 2); // user+assistant pairs
return trimmed;
}
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "claude-sonnet-4",
max_tokens: 1024,
messages: buildMessages(conversationHistory)
})
});
This is a simple sliding window — fine for casual chat, not sufficient for a conversation where facts from turn 2 need to still be true at turn 50. For that, summarization or external memory (a database lookup injected into the system prompt) works better than relying on raw history alone.
Where tool use fits into context growth
If your multi-turn conversation also uses tool calls, each tool result gets added to the message history just like a regular turn — and tool outputs (API responses, search results, file contents) are often far larger than typical chat messages. If you're building an agent that calls tools repeatedly across a conversation, budget context window space for tool results specifically, not just dialogue. See /docs/tools for how tool-use messages are structured in the conversation array.
If you're already managing multiple Claude API keys across projects and want usage metadata (including per-conversation token counts) surfaced without building your own logging layer, SubToAPI exposes that in the dashboard — useful for spotting which conversations are approaching context limits before they fail in production. Check /pricing for plan details or /docs/quickstart to get started.
Questions
Does Claude remember previous conversations automatically? No. Claude is stateless between API calls — your application must store and resend the message history yourself. There is no server-side session memory.
What happens if my conversation exceeds the context window? The API returns an error rather than truncating silently. You need to trim, summarize, or otherwise reduce the message history before it happens, not react after the fact.
How do I know how many tokens my conversation is using? Check the usage metadata returned with every response — it reports input and output token counts, which you can log per conversation to track growth over time.