Skip to main content
All posts

Claude API Message Threads Beta: Send Only New Messages

How the Claude API message threads beta works: fixed fields, 5-minute expiry, no ZDR, and how it differs from prompt caching.

IntentCode··14 min read

TL;DR

  • Claude API message threads entered beta on 2026-11-02 and keep the conversation on the server.
  • Follow-up requests send only new messages, so requests shrink and time to first token drops.
  • Threads expire after 5 minutes, are append-only and not ZDR-eligible, so keep your own copy.

The problem message threads solve

The Messages API has always been stateless. By the tenth turn of a conversation you resend the previous nine turns, the system prompt and every tool definition on each request. In agent loops, tool results pile up too, and the request body can quickly grow to several megabytes.

That design is simple, but long conversations pay twice. You pay in network transfer for content the server has already seen, and you pay in the time it takes the server to receive and start processing a large request. Users feel this as "the answer starts late."

On November 2, 2026, Anthropic released message threads in beta to reduce exactly this. The official release notes say the API keeps the conversation on the server, so each later request sends only the new messages. The docs add that requests get smaller and that time to first token (TTFT) stays lower and steadier as the conversation grows.

How it works: one create, many continues

You add a single thread field to the request body. Every request in a thread must carry the anthropic-beta: message-threads-2026-08-12 header.

The first request sends "thread": {"type": "create"} together with the full conversation so far, plus system and tools. The API stores the conversation, including Claude's reply, under the response id. The response itself is the usual message.

From the next turn on, you send "thread": {"type": "continue", "previous_message_id": "<previous response id>"} and only the messages since the previous response. Usually that is the user's next question, or the tool_result blocks answering a tool_use in the previous response. Each new response id is what you continue from next.

bash
curl -sS https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2026-10-21" \
  -H "anthropic-beta: message-threads-2026-08-12" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-opus-5-5",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "How long does shipping usually take?"}],
    "thread": {"type": "continue", "previous_message_id": "'"$MESSAGE_ID"'"}
  }'

This is the second turn. The key detail is that system and tools are absent.

Fields you can and cannot change

A thread pins the settings of its create request, like a fingerprint. The docs split fields into three groups.

GroupFieldsOn a continue request
Create-onlysystem, tools400 if sent (even as null)
Fixedmodel, tool_choice, thinking, mcp_servers, output_config, top-level cache_control, the beta header set, and more400 thread_fingerprint_mismatch if different
Freemax_tokens, stop_sequences, stream, metadata, service_tierMay change every turn

The one that bites most often in practice is model switching. If you route a conversation to a smaller model midway to save cost, you need to start a new thread with a create request at that point. If your system prompt is rebuilt every turn with the date or user settings, you also need to move those values into messages.

Five constraints you need to know

First, a thread is best-effort. It expires 5 minutes after its last request, and the API deletes it no more than 1 hour after its last use. Each stored response restarts the 5 minutes. If a thread cannot be continued, the continue request returns a 404 with thread_not_found, and you recover by sending the full conversation in a new create request.

Second, no response tells you whether that turn was stored. The docs therefore tell you to keep your own copy of the conversation. It is safest to treat a thread as a transfer-saving cache, not as storage.

Third, a thread is append-only and each response id can be continued once. To edit an earlier message or branch from an older point, you start a new thread. If your chat UI has a "regenerate answer" button, that path needs its own handling.

Fourth, when streaming, the response id arrives in the message_start event, but you should continue only after message_stop. Continuing earlier can return a 404. If stop_reason is pause_turn, continue with "messages": [], and if it is refusal, the docs say not to continue that thread.

Fifth, data retention. A thread is held in memory, encrypted under a server-managed key and never written to durable storage, but the feature is not eligible for zero data retention (ZDR). If your privacy policy promises that conversations are not kept by your AI provider, check that wording before you turn this on.

How it differs from prompt caching

This part is easy to confuse, so it gets its own section. The docs state plainly that a thread does not cache your prompt for you. Prompt caching works exactly as it does without a thread, and you still choose where the cache breakpoints go.

In other words, threads cut what you send, and caching cuts the cost of reading it again. Using both together is the default. Sending a top-level cache_control on every request caches each turn.

Note that a request with thread can carry at most 4 cache_control breakpoints, and the top-level cache_control counts as one. Breakpoints placed on system and tools in the create request count again on every continue request. Going over returns a 400 thread_unsupported_request.

An adoption checklist

Check these in order before you adopt it.

  • Are your conversations actually long? Two or three turn Q&A gains almost nothing.
  • Do you already keep the original conversation in a database or memory? The 404 recovery path depends on it.
  • Does your code switch model, system prompt or tools midway? If so, turn those points into new thread starts.
  • Is your platform supported? Per the release notes it is in beta on the Claude API, Claude Platform on AWS, Claude Models on Google Cloud (Anthropic managed) and Microsoft Foundry.
  • Does your organization need ZDR or have regulatory requirements? If so, this feature is not covered.
python
def send_turn(client, state, new_messages):
    thread = ({"type": "continue", "previous_message_id": state.last_id}
              if state.last_id else {"type": "create"})
    extra = {} if state.last_id else {"system": state.system, "tools": state.tools}
    try:
        res = client.messages.create(model=state.model, max_tokens=1024,
            messages=new_messages if state.last_id else state.history + new_messages,
            extra_body={"thread": thread}, extra_headers={"anthropic-beta": "message-threads-2026-08-12"}, **extra)
    except NotFoundError:  # thread_not_found -> create again with the full history
        state.last_id = None
        return send_turn(client, state, new_messages)
    state.history += new_messages + [{"role": "assistant", "content": res.content}]
    state.last_id = res.id
    return res

This is a sketch of the structure. The app always owns the original history, and when a thread disappears it starts over from that copy. Check the exact parameter names and exception classes in the docs for the SDK version you use.

What it means for our stack

The chatbot on the IntentCode homepage is a RAG setup that answers with Claude. Most conversations are short, one question plus retrieved context, so prompt caching matters more for us than threads right now. Agent loops that call tools many times, or features where people talk about a long document for a while, are the better first candidates for an experiment.

In short, message threads are an optimization that cuts transfer size and wait time for long conversations. Remember that they do not replace your conversation store and that they change your data retention picture, and you can try them without much risk.

References

Get new posts by email

Notes from building our products, about twice a week. Questions? Ask Dot.