{"slug": "claude-message-threads-smaller-requests-for-long-agents", "title": "Claude Message Threads: Smaller Requests for Long Agents", "summary": "Anthropic added message threads to its Messages API as a public beta on November 2, 2026, behind the `message-threads-2026-08-12` header, letting agent loops send only new messages per turn instead of re-uploading the full conversation. Anthropic's release notes state that long conversations and agent loops \"can now send smaller requests and get a lower time to first token with message threads,\" though the documentation publishes no latency or token-saving figures. Threads expire 5 minutes after the last request and are deleted no more than 1 hour after last use, do not change pricing or rate limits, are unavailable to organizations with zero data retention, HIPAA readiness or inference hooks enabled, and do not work with Message Batches, token counting or compaction.", "body_md": "On November 2, 2026, Anthropic's release notes added message threads to the Messages API as a public beta behind the `message-threads-2026-08-12` header. The idea is simple. Today, every turn of an agent loop uploads the entire conversation again, and the API validates and tokenizes all of it again. With a thread, the API keeps the conversation on its side for a short time, and each later request sends only what is new.\n\nThat is the whole feature, and it matters most to one kind of customer: anyone running long tool-calling loops where a request can carry hundreds of kilobytes of history before the model reads the new tool result. Anthropic's stated benefit is a lower and steadier time to first token as the conversation grows. It publishes no latency or token-saving figures on the documentation page, so none appear here.\n\nWhat follows is the contract as the documentation states it on November 5, 2026: how a thread is created and continued, how fast it expires, which request fields are frozen for its lifetime, how prompt caching interacts with it, which features and organisations are excluded, and what each of the five error codes means. The last section is a decision grid for teams deciding whether to adopt it during the beta.\n\n1. 01One parameter, two modes.A create request sends the full conversation with system and tools; every continue request sends only the new messages plus the previous response id. The response is an ordinary message.\n2. 02A thread is best-effort and short-lived.It expires 5 minutes after its last request and is deleted no more than 1 hour after last use. A continue request that cannot be served returns a 404, and your application must replay the full conversation. You remain the source of truth.\n3. 03Nothing about the bill changes.Anthropic states that threads do not change pricing or rate limits, and that a thread does not cache your prompt. Prompt caching still needs breakpoints, and a threaded request may carry at most four.\n4. 04Several customers cannot use it yet.Threads are not eligible for zero data retention, return a 400 for organisations with HIPAA readiness or inference hooks enabled, and do not work with Message Batches, token counting or compaction.\n5. 05Adopt it where the loop is long and the data policy allows.Agent loops with many tool calls per task gain the most. Short chats, batch jobs and regulated workloads should wait for the beta to widen.\n\n## 01 — The ChangeWhat changed on *November 2*\n\nUntil this week, the Messages API was stateless by design. Each call carried the system prompt, the tool definitions and every prior message, and the API rebuilt the model's input from scratch. For a ten-turn chat that is a rounding error. For an agent that makes sixty tool calls over an hour, the history dominates every request, and the time the API spends receiving and tokenizing it happens before the model generates a single token.\n\nAnthropic's [release notes entry for November 2, 2026](https://platform.claude.com/docs/en/release-notes/overview) puts the benefit in one sentence: long conversations and agent loops \"can now send smaller requests and get a lower time to first token with message threads\". The API keeps the conversation on the server, so each later request sends only the new messages. The entry also states the two limits that shape everything else: a thread expires 5 minutes after its last request and is deleted no more than 1 hour after its last use.\n\nThe feature is in beta on every current model, from Haiku 4.5 through Opus 5.5 to Fable 5.1 and Mythos 5.1, and on four platforms: the Claude API, Claude Platform on AWS, Anthropic-managed Claude on Google Cloud, and Microsoft Foundry. The documentation notes that message threads are a different thing from the session threads in Claude Managed Agents. If you have read our piece on [the Managed Agents update](https://www.digitalapplied.com/blog/claude-managed-agents-update-effort-webhooks-skills), do not carry its vocabulary over. A message thread is a transport optimisation for people who run their own loop.\n\nA failure case to hold in mind from the start: a thread is not memory. It cannot be continued from a different organisation, workspace, user or service account, and there is no API to list, read or delete one. A team that treats it as session storage will discover on the first 404 that the conversation is gone unless they kept their own copy.\n\n`system` and `tools` from the create request, and a fingerprint of the fixed fields used to check later requests. It is held in memory, encrypted under a server-managed key, never written to durable storage, and deleted no more than 1 hour after last use. Files are held by reference, so every file the conversation uses must stay available while the thread is in use.\n## 02 — MechanicsCreate, continue, *replay*\n\nThe documentation describes three operations. **Create** is your existing first request with one addition: `\"thread\": {\"type\": \"create\"}`. The API stores the conversation, including Claude's reply, under the response `id`. **Continue** sends only the messages since that response plus `\"thread\": {\"type\": \"continue\", \"previous_message_id\": \"<id>\"}`, and leaves `system` and `tools` out. The thread keeps the values from the create request. **Replay** is what you do when a continue request returns a 404: send the full conversation again in a new create request and carry on from the new `id`.\n\nHere is the shape from the cURL example in [Anthropic's message-threads documentation](https://platform.claude.com/docs/en/build-with-claude/message-threads), trimmed to the two turns. The second request sets `previous_message_id` to the `id` of the first response.\n\n```\n# Turn 1: full conversation, create a thread\ncurl -sS --fail-with-body https://api.anthropic.com/v1/messages \\\n  -H \"x-api-key: $ANTHROPIC_API_KEY\" \\\n  -H \"anthropic-version: 2026-10-21\" \\\n  -H \"anthropic-beta: message-threads-2026-08-12\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\n    \"model\": \"claude-opus-5-5\",\n    \"max_tokens\": 1024,\n    \"cache_control\": {\"type\": \"ephemeral\"},\n    \"system\": \"You are a support agent for Acme. Keep replies short.\",\n    \"messages\": [{\"role\": \"user\", \"content\": \"Hi! I have a question about an order.\"}],\n    \"thread\": {\"type\": \"create\"}\n  }'\n\n# Turn 2: only the new message; system and tools stay out\ncurl -sS --fail-with-body https://api.anthropic.com/v1/messages \\\n  -H \"x-api-key: $ANTHROPIC_API_KEY\" \\\n  -H \"anthropic-version: 2026-10-21\" \\\n  -H \"anthropic-beta: message-threads-2026-08-12\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\n    \"model\": \"claude-opus-5-5\",\n    \"max_tokens\": 1024,\n    \"cache_control\": {\"type\": \"ephemeral\"},\n    \"messages\": [{\"role\": \"user\", \"content\": \"How long does standard shipping usually take?\"}],\n    \"thread\": {\"type\": \"continue\", \"previous_message_id\": \"'\"$message_id\"'\"}\n  }'\n```\n\nTwo rules follow from the append-only design. Each response `id` can be continued exactly once, so a loop must always continue from the latest `id`. And the API does not check the new messages against what it already holds: if you send the previous response again, the request errors, and if you resend a user message it can appear twice. In a tool loop the continue request normally starts with the `tool_result` blocks that answer the previous turn's `tool_use`.\n\nThe official SDKs wrap all of this in a thread helper. You create it with the same fields as a Messages request, then send one turn at a time. It adds the beta header, leaves `system` and `tools` out of continue requests, resends the fixed fields, and replays on a 404 once by itself. Anthropic also notes that the beta tool runner in the SDK now uses a thread by default, which means some teams will be on threads without changing a line.\n\nOne example of a step that trips people: a response that ends with `stop_reason: \"pause_turn\"` is resumed with a continue request from that response's `id` and an empty `messages` list. Sending a new user message while the turn is paused is rejected.\n\n## 03 — ExpiryThe *five-minute* clock\n\nThe expiry rule is the design decision that makes threads a transport feature rather than a storage feature. A thread expires 5 minutes after its last request, and each response the API stores restarts that clock. Deletion follows no more than 1 hour after the last use. There is no API to list, read or delete a thread; the only way to keep one alive is to send the next request within five minutes.\n\nFive minutes is comfortable for an agent loop that calls a tool, gets a result in seconds and continues. It is not comfortable for a workflow that waits on a human approval, a CI run or a long external job between turns. Those loops will see the 404 often, and the replay path becomes the common case rather than the exception.\n\nThe documentation is direct about the consequence. Your application stays the source of truth for the conversation. No response to a create or continue request tells you whether the API stored that turn; you find out on the next continue. Anthropic lists several reasons a continue can fail beyond plain expiry: the previous turn was served but not stored (for example a tool call cut off by `max_tokens`), a fallback model wrote the previous response, the previous response is still generating, the request comes from a different organisation, workspace, user or service account, or the new messages add something the stored conversation cannot take, such as the first image in a text-only thread.\n\nThe failure case worth designing for is the quiet one. A continue request that is retried after a dropped stream can hit `thread_already_continued` or `thread_continue_in_flight`, because the server may have finished and stored the turn after your connection went away. The documentation's answer is that replaying is always safe. Our own [guide to safe retries across providers](https://www.digitalapplied.com/blog/ai-provider-failover-safe-retries) covers the same idempotency problem for non-threaded calls.\n\n##### Expires after *5 minutes*\n\nCounted from the thread's last request. Good for tight tool loops; poor for anything that waits on a person or a slow job between turns.\n\n##### Gone within 1 hour\n\nAnthropic deletes a thread no more than 1 hour after its last use. You cannot see it, extend it or remove it early from your side.\n\n##### 404 means replay\n\nSend the full conversation from your own copy in a new create request, with system and tools, then continue from the new id. The SDK helper does this once for you.\n\n##### Start over after a refusal\n\nDo not continue a thread after a refusal. The API may already hold the refused turn and a continue request cannot remove it. Create a new thread without that turn.\n\n## 04 — Fixed FieldsWhat must *stay the same* for a thread's life\n\nA thread stores a fingerprint of certain request fields and rejects any continue request that changes one. This is where most integration bugs will come from, because agent frameworks routinely vary these fields between turns: switching models for a cheap summarisation step, toggling `tool_choice`, or changing the thinking budget mid-task. Every one of those produces a 400 with the code `thread_fingerprint_mismatch`, and the error message names the fields that differ.\n\n| Field groups as stated in Anthropic's message-threads documentation, \"What to send on each request\", retrieved November 5, 2026. |  |  | \n|---|---|---|\n| Group | Fields | Rule | \n|---|---|---|\n| Create-only | `system` ,`tools` | Sent on the create request only, with any cache breakpoints on them. Sending either on a continue request, even as `null` , returns a 400. | \n| Fixed | `model` ,`tool_choice` ,`thinking` ,`mcp_servers` (except each server's authorisation token),`context_management` ,`output_config` , the`skills` in`container` , top-level`cache_control` , the set of`anthropic-beta` values | Sent on every request with the same values as the create request. A different value returns 400 `thread_fingerprint_mismatch` . | \n| Free | `max_tokens` ,`stop_sequences` ,`stream` ,`metadata` ,`service_tier` , other unnamed fields | May change from turn to turn. | \n\nTwo details matter beyond the table. The API does not store MCP server URLs, MCP authorisation tokens or the container `id`, so `mcp_servers` and `container` must be sent on every request that uses them. And if you use server-side fallback, the `fallbacks` field must be present on every request of a thread or on none; adding or dropping it mid-thread is a fingerprint mismatch.\n\nThe example that will bite teams migrating from Fable 5 or Opus 5: on Fable 5.1, Mythos 5.1, Opus 5.5, Sonnet 5.5 and Haiku 5.5, changing `system` or `tools` invalidates the thinking blocks already in the conversation, so a create request that starts a new thread with different tools can return a 400. Anthropic's workaround is to leave every `thinking` and `redacted_thinking` block out of the conversation you replay, accepting that the model then answers without that earlier reasoning. This is the same block-binding behaviour we documented in [the Fable 5.1 breaking-changes guide](https://www.digitalapplied.com/blog/claude-fable-5-1-cost-and-breaking-changes), now surfacing through a new door.\n\n## 05 — CachingCaching is *still your job*\n\nThe most common misreading of this launch will be that a thread caches the conversation. The documentation says the opposite in plain words: a thread does not cache your prompt for you, and prompt caching works as it does without a thread. A thread saves the upload and the server-side tokenization of the history. It does not by itself change what you pay for input tokens.\n\nTo get both benefits, Anthropic's recommended pattern is a top-level `cache_control` on every request of the thread. The API applies it to the last cacheable block of each request's messages, so each turn reads the earlier conversation from cache and writes the new turn to it. Because top-level `cache_control` is a fixed field, the value must be identical on every request.\n\nThe constraint is the breakpoint budget. A request with `thread` may carry at most four `cache_control` breakpoints. The top-level one counts as one. Breakpoints placed on `system` and `tools` in the create request count again on every continue request. Breakpoints on earlier stored messages do not count. One too many returns a 400 with `thread_unsupported_request` and `unsupported: [\"cache_control\"]`. And because a continue request cannot resend an earlier message, a breakpoint cannot be moved or removed once sent.\n\nThe failure case is the replay. If you placed breakpoints on message blocks yourself, the conversation you replay into a new create request still carries them, and five breakpoints in one request is a hard error. Strip them from earlier messages before replaying and keep one on the last block. The SDK helper does this when it replays on its own. For the economics behind why this is worth the care, our [September prompt-caching update](https://www.digitalapplied.com/blog/prompt-caching-changes-openai-anthropic-september-2026) covers the current cache-read rates.\n\n- Breakpoints per threaded requesttop-level cache_control counts as one\n- 4 max\n- Breakpoints on system and toolsset on create, counted again on every continue\n- Persist\n- Breakpoints on earlier stored messagesalready in the thread\n- Not counted\n- Moving or removing a breakpointcontinue requests cannot resend earlier messages\n- Not possible\n- Change to pricing or rate limitspricing and rate limits, per the documentation\n- None\n\n## 06 — ExclusionsWhere threads are *barred*\n\nThe exclusions list is short but it removes whole categories of customer. First, data retention. Message threads are not eligible for zero data retention. Anthropic's framing is that a thread is held in memory, encrypted under a server-managed key, never written to durable storage, and deleted within an hour; it also states that using threads does not affect your use of other ZDR-eligible features. A team under a strict ZDR commitment should read that as \"not for us yet\" rather than as a loophole. The background on which Claude models and features sit inside ZDR is in our [retention and ZDR guide](https://www.digitalapplied.com/blog/fable-5-30-day-data-retention-zdr-enterprise-2026).\n\nSecond, organisation settings. Organisations with HIPAA readiness enabled, and organisations with inference hooks turned on, get a 400 with `thread_unsupported_request` and an `unsupported` value of `hipaa` or `inference_hooks`. Third, features: Message Batches (a batch item with `thread` fails inside the batch results), token counting (count the full conversation instead), compaction and compaction on demand, and context editing apart from `clear_thinking_20251015` with `keep: \"all\"`.\n\nThe example that follows from the compaction rule: because a thread is append-only, you cannot replace its early turns with a summary. The documented approach is to write the summary in your own code and start a new thread from it, with `system` and `tools`. Teams that already do application-side compaction, the pattern our [context-engineering playbook](https://www.digitalapplied.com/blog/context-engineering-agent-reliability-playbook-2026) recommends, lose nothing. Teams that leaned on the API's compaction parameter must choose between it and threads for a given request.\n\nThe failure case is silent scope creep. Anthropic says the `unsupported` list can grow, and that a request meeting several conditions gets an error naming only one. The safe handling is generic: on any `thread_unsupported_request` value you do not recognise, resend the full conversation without `thread`. The SDK helper offers exactly that behaviour through a `continue_unthreaded` setting; without it, the helper replays on every turn.\n\n## 07 — Error CodesThe five *error codes*, and what each one asks of you\n\nAll five are returned before the model runs, so a rejected request uses no tokens and does not touch the thread's expiry timer. `error.type` is `invalid_request_error` for the 400s and `not_found_error` for the 404. Note that a request for a model that does not exist also returns a 404, so check `error.details.error_code` before replaying.\n\n| Error table as published in Anthropic's message-threads documentation, retrieved November 5, 2026. Some 400s for malformed thread requests carry no error_code at all. |  |  |  | \n|---|---|---|---|\n| Status | error_code | Meaning | What to do | \n|---|---|---|---|\n| 404 | `thread_not_found` | The API cannot continue the thread. | Send the full conversation in a new create request. | \n| 400 | `thread_fingerprint_mismatch` | A fixed field differs from the stored value; the message names the fields. | Keep fixed fields identical, or start a new thread to change one. | \n| 400 | `thread_already_continued` | Each response id can be continued once. | Continue from the latest id; if you never received it, replay. | \n| 400 | `thread_continue_in_flight` | Another continue from this id is still running, usually your own earlier attempt. | Let it finish and continue from its id, or replay. | \n| 400 | `thread_unsupported_request` | The request uses a feature or organisation setting threads do not support; `details.unsupported` names it when present. | Remove the feature, or send the full conversation without `thread` . | \n\nOne behaviour worth testing early: a continue request without `previous_message_id`, or one that includes `system` or `tools`, returns a 400 with no `error_code`. An error handler that switches only on the five named codes will treat those as unknown failures. Match on the absence of a code as well and log the message, which in Anthropic's example spells out the problem in a sentence.\n\n## 08 — DecisionWho should *switch now*, and who should wait\n\nThe question is not whether threads are good. For the workload they target they are a clear improvement with no price attached. The question is whether your workload is that one, and whether your data obligations allow it during the beta. Four routes cover most of the teams our [AI transformation practice](https://www.digitalapplied.com/services/ai-transformation) works with.\n\n`cache_control` on every request, and build the replay path before the first deploy.`thread` field.\nAn example of the first route done well: an SDK-based coding agent that averages forty tool calls per task, keeps its own transcript in a database anyway, and already caches its system prompt. Adding threads is a configuration change and a test of the replay branch. An example of the second route done badly: a customer-support workflow that threads a conversation, waits twenty minutes for an agent handoff, and treats the 404 as a crash instead of a replay. The feature did what the documentation said; the integration did not read it.\n\n## 09 — ConclusionA thread is a *transport*, not a memory\n\n### Keep your own transcript, cache on every turn, and let the thread shave the upload.\n\nMessage threads do one thing: they stop a long agent loop from re-uploading and re-tokenizing its history on every turn. Anthropic states the benefit as a lower, steadier time to first token and publishes no figures for it, so treat it as a latency feature to measure on your own loop rather than a cost cut.\n\nThe constraints are all stated and all firm. Five minutes of life, best-effort storage, a 404 that means replay, a frozen set of request fields, four cache breakpoints, and no entry for ZDR, HIPAA, inference-hook, batch, token-counting or compaction workloads. None of them is a defect; together they describe a feature built for one job.\n\nIf your loop is that job, the SDK helper makes adoption a small change. Build the replay branch first, keep the transcript on your side, and put a top-level cache breakpoint on every request so the thread and the cache work together. If your loop is not that job, nothing about your bill or your rate limits changes by waiting.", "url": "https://wpnews.pro/news/claude-message-threads-smaller-requests-for-long-agents", "canonical_source": "https://www.digitalapplied.com/blog/claude-message-threads-messages-api-beta", "published_at": "2026-11-02 00:00:00+00:00", "updated_at": "2026-11-05 19:24:47.720754+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-agents", "ai-tools", "developer-tools"], "entities": ["Anthropic", "Claude", "Messages API", "Claude Platform on AWS", "Google Cloud", "Microsoft Foundry", "Claude Managed Agents"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/claude-message-threads-smaller-requests-for-long-agents", "markdown": "https://wpnews.pro/news/claude-message-threads-smaller-requests-for-long-agents.md", "text": "https://wpnews.pro/news/claude-message-threads-smaller-requests-for-long-agents.txt", "jsonld": "https://wpnews.pro/news/claude-message-threads-smaller-requests-for-long-agents.jsonld"}}