Anthropic shipped message threads in public beta on November 2, 2026, and the headline is easy to misread: median time to first token drops about 35% on 500K-1M-token requests, but your token bill does not move. If you run long agent loops, this is a transport fix with a strict 5-minute idle limit.
Faster requests, same bill: what threads change and what they don't
Message threads are temporary server-side conversation state for the Messages API, launched as a public beta on November 2, 2026. You send the full history once with thread: { "type": "create" }, then send only new messages plus previous_message_id with thread: { "type": "continue" }. Per Anthropic's announcement and platform docs, state lives in encrypted memory, is never written to disk, expires after 5 minutes idle, and is deleted no later than 1 hour after last use.
Every request in a thread must carry the beta header anthropic-beta: message-threads-2026-08-12. Pricing and rate limits are unchanged: Claude still reads the full conversation each turn, so you pay the same input/output tokens while uploading far fewer bytes.
"Yeah nice, but it doesn't reduce tokens cost :( Claude still reads the entire conversation on every turn & token consumption remains unchanged" — @_navicstein, replying to the official launch thread
The official announcement reports roughly 35% lower median TTFT for 500K-1M-token requests, with no token discount.
Threads vs prompt caching in one paragraph
Threads reduce what you send; prompt caching reduces what you pay full price for. Threads do not auto-cache anything — you still set cache_control breakpoints. The detailed caching interaction below follows the implementation breakdown: keep a top-level cache_control on every continuation, with cache reads at 0.1x base input (0.05x on Claude Opus 5.5 and Sonnet 5.5).
Threads vs managed-agent session threads
Search results mix two different "threads." Messages API message threads — this article — are ephemeral request-size optimization with no list/read/delete API. Managed-agent session threads (GET /v1/sessions/{session_id}/threads/{thread_id}) are execution threads inside Anthropic's managed-agents API with list/retrieve/archive endpoints. If docs mention child threads, event streams, or archiving, you are reading the wrong API. See the API reference for session threads to confirm which surface you need.
How a thread actually moves: create, continue, expire
In practice a thread is append-only: create with full context, continue with deltas, replay after loss. There is no branch, edit, rewind, or inspection API. Each response returns a new id, and each id can be continued only once. Field and error rules in this section follow platform docs as detailed in the implementation breakdown.
Create carries everything: full messages, system, and tools, plus:
{
"model": "claude-opus-5-5",
"system": "You are a support agent for Acme. Keep replies short.",
"messages": [{ "role": "user", "content": "Hi! I have a question about an order." }],
"thread": { "type": "create" }
}
Continue carries only what is new, usually a user message or tool_result blocks:
{
"model": "claude-opus-5-5",
"messages": [{ "role": "user", "content": "How long does standard shipping usually take?" }],
"thread": { "type": "continue", "previous_message_id": "msg_xxx_from_create" }
}
Omit system and tools on continue — even "system": null triggers a 400. Wait for message_stop on streams before continuing; the usable continuation ID arrives in message_start.
Which fields you can change mid-thread
Anthropic fingerprints part of the create request. Changing a fingerprinted value returns thread_fingerprint_mismatch and forces a new thread.
| Group | Examples | Rule on continue |
|---|---|---|
| Create-only | system, tools | Never resend; null also fails |
| Fixed | model, tool_choice, thinking, mcp_servers, context_management, output_config, container skills, top-level cache_control handling | Must stay identical |
| Free | max_tokens, stop_sequences, stream, metadata, service_tier | May change per turn |
| Always resend | MCP server URLs / auth tokens, container ID | Not stored server-side, include each time you use them |
Extended-thinking models need extra care: editing system or tools can invalidate prior thinking / redacted_thinking blocks. If a full replay after expiry returns 400, drop the stale thinking blocks from the replayed history rather than retrying verbatim.
The 5-minute rule and the replay you must build
Treat threads as best-effort: retain the full history, system, tools, and file references locally because storage is confirmed only by a successful next continuation. Files are held by reference — a file deleted mid-thread breaks continuation.
The expiry clock resets on every stored response. After 5 minutes idle the next continue returns 404, and you replay the full conversation as a fresh create. Data is gone no later than 1 hour after last use.
| HTTP | Code | What happened | Do this |
|---|---|---|---|
| 404 | thread_not_found | Expired, not stored, wrong key/workspace, first image added to text-only thread, fallback model served it, or response still generating | Verify key/workspace and config, then replay full history as new create |
| 400 | thread_fingerprint_mismatch | A fixed field changed | Restore original value or start new thread |
| 400 | thread_already_continued | That previous_message_id was already used | Continue from the latest id |
| 400 | thread_continue_in_flight | Concurrent continue on same ID | Wait for it, then use its new ID, else replay |
| 400 | thread_unsupported_request | Unsupported setting (e.g. >4 cache breakpoints, batches) | Remove setting or send without thread |
Failed thread requests run before model execution per the docs summary, so they consume no tokens and do not reset the expiry timer. Persist the latest successful response ID atomically before accepting the next turn, and guard replays for idempotency when tool actions have side effects.
Python replay shape (handle only verified thread_not_found; fingerprint, concurrency, and unsupported-request errors need separate branches):
try:
resp = client.beta.messages.create(
model="claude-opus-5-5",
messages=[new_msg], # delta only
thread={"type": "continue", "previous_message_id": last_id},
extra_headers={"anthropic-beta": "message-threads-2026-08-12"},
)
except NotFoundError: # thread_not_found after checking identity/config
resp = client.beta.messages.create(
model="claude-opus-5-5",
system=SYSTEM, tools=TOOLS,
messages=full_history + [new_msg], # you stored this
thread={"type": "create"},
extra_headers={"anthropic-beta": "message-threads-2026-08-12"},
)
Proxy and key-rotation 404 trap
Operator-reported behavior, not yet in official docs: a thread is bound to the organization, workspace, and credential that created it. A relay that rotates API keys per request will create on key A and continue on key B, which looks exactly like expiry: endless 404 then full replay with no latency win.
"thread 绑定创建它的 key 和 workspace,换 key 会 404 thread_not_found。中转站轮换 key 会先吃 404 再全量重发。" — @ak12kpoot (Chinese developer note on proxy behavior)
Pin a thread to one key, or bypass threads on pooled routes.
Where threads run, what they block, and whether you should switch now
Message threads are available on the Claude API, Claude Platform on AWS, Anthropic-managed Google Cloud Claude Models, and Claude in Microsoft Foundry. Every model in beta is covered; there is no separate model allowlist and no stated waitlist.
What is excluded matters more for launch planning:
| Area | Status |
|---|---|
| Amazon Bedrock | Not supported |
| Message Batches | Unsupported — batched thread items fail |
| Token counting endpoint | Unsupported — count full history yourself |
| Compaction / context editing | Unsupported (except clear_thinking with keep all) |
| Zero data retention, HIPAA-ready, inference hooks | Not eligible |
| Thread management API | None — cannot list, read, or delete threads |
Decision checklist
- Use threads now: active coding agents, computer-use loops with screenshots, or document-heavy flows doing dozens of turns with under 5-minute gaps. Pair with prompt caching and a replay path.
- Skip for now: human-paced chat, paused workflows, batch pipelines, ZDR/HIPAA workloads, or Bedrock deployments.
- Combine when it pays: top-level
cache_controlon every request counts toward the 4-breakpoint limit — breakpoints fromsystem/toolson create count again on every continue. Exceeding it returnsthread_unsupported_request, so consolidate breakpoints before enabling both.
See also: Claude API pricing guide 2026, Claude Skills API guide.
FAQ
What beta header and parameter do I need?
Send anthropic-beta: message-threads-2026-08-12 on every request in the thread, plus thread: { "type": "create" } on the first call and thread: { "type": "continue", "previous_message_id": "<last response id>" } after that.
What happens when a thread expires?
The next continue returns 404 thread_not_found. Resend the full messages plus original system/tools as a new create. Expiry is 5 minutes idle, with deletion no later than 1 hour after last use.
Can I list, inspect, or delete threads?
No. There is no management API for Messages API threads. Your local history is the only durable record.
Does it work on Amazon Bedrock?
No. Supported surfaces are the Claude API, AWS Claude Platform, Microsoft Foundry, and Anthropic-managed Google Cloud. Bedrock requests should stay on full-history sends.
Can I change the system prompt or tools mid-thread?
No. Create a new thread with the new system/tools. Sending changed values on continue triggers thread_fingerprint_mismatch. The same applies to model, tool_choice, and thinking config.
Does it work with streaming, tools, and MCP?
Yes, with rules: wait for message_stop before continuing, resend MCP URLs/tokens and container IDs each turn, and send fallbacks on every request or none — a fallback-model response is not stored and must be replayed.