llms.txt@04-API-Reference/Guides · git:20261001.bf1f66b · 2026-10-01 · sha256 f62ca6fd17ace8da
llms.txt@04-API-Reference/Guides git:20261001.bf1f66bC
Immutable. This exact content never changes and is served at /api/v1/blob/f62ca6fd17ace8da.
# API Reference / Guides
> Every page below, concatenated. Each section gives the page title, its upstream source and its path in this repository.
---
## Admin API overview
Source: https://platform.claude.com/docs/en/build-with-claude/administration-api
Path: 04-API-Reference/Guides/build-with-claude-administration-api.md
# Admin API overview
---
<Tip>
**The Admin API is unavailable for individual accounts.** To collaborate with teammates and add members, set up your organization in **Console → Settings → Organization**.
</Tip>
The [Admin API](../Admin/admin.md) allows you to programmatically manage your organization's resources, including organization members, workspaces, and API keys. This provides programmatic control over administrative tasks that would otherwise require manual configuration in the [Claude Console](../Other/usage-limits.md).
<Check>
**The Admin API requires special access**
The Admin API requires a special Admin API key (starting with `sk-ant-admin...`) that differs from standard API keys. Only organization members with the admin role can provision Admin API keys through the Claude Console.
</Check>
## How the Admin API works
When you use the Admin API:
1. You make requests using your Admin API key in the `x-api-key` header
2. The API allows you to manage:
- Organization members and their roles
- Organization member invites
- Workspaces and their members
- API keys
This is useful for:
- Automating user onboarding/offboarding
- Programmatically managing workspace access
- Monitoring and managing API key usage
## Organization roles and permissions
There are five organization-level roles. See more details in the [API Console roles and permissions](https://platform.claude.com/docs/en/api-console-roles-and-permissions-4c21777af6.md) article.
| Role | Permissions |
|------|-------------|
| user | Can use Workbench |
| claude_code_user | Can use Workbench and [Claude Code](https://platform.claude.com/docs/02-Claude-Code-CLI/claude-code-overview-claude-code-docs-c23f3e7cbb.md) |
| developer | Can use Workbench and manage API keys |
| billing | Can use Workbench and manage billing details |
| admin | Can do all of the above, plus manage users |
## Key concepts
### Organization Members
You can list [organization members](../Admin/beta-organization-users-retrieve.md), update member roles, and remove members.
<CodeGroup>
```bash cURL
# List organization members
curl "https://api.anthropic.com/v1/organizations/users?limit=10" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
# Update member role
curl "https://api.anthropic.com/v1/organizations/users/{user_id}" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY" \
--data '{"role": "developer"}'
# Remove member
curl --request DELETE "https://api.anthropic.com/v1/organizations/users/{user_id}" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
</CodeGroup>
### Organization Invites
You can invite users to organizations and manage those [invites](../Admin/beta-organization-invites-retrieve.md).
<CodeGroup>
```bash cURL
# Create invite
curl --request POST "https://api.anthropic.com/v1/organizations/invites" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY" \
--data '{
"email": "newuser@domain.com",
"role": "developer"
}'
# List invites
curl "https://api.anthropic.com/v1/organizations/invites?limit=10" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
# Delete invite
curl --request DELETE "https://api.anthropic.com/v1/organizations/invites/{invite_id}" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
</CodeGroup>
### Workspaces
For a comprehensive guide to workspaces, including Console and API examples, see [Workspaces](../Other/manage-claude-workspaces.md).
### Workspace Members
Manage [user access to specific workspaces](../Admin/beta-organization-workspaces-members-retrieve.md):
<CodeGroup>
```bash cURL
# Add member to workspace
curl --request POST "https://api.anthropic.com/v1/organizations/workspaces/{workspace_id}/members" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY" \
--data '{
"user_id": "user_xxx",
"workspace_role": "workspace_developer"
}'
# List workspace members
curl "https://api.anthropic.com/v1/organizations/workspaces/{workspace_id}/members?limit=10" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
# Update member role
curl --request POST "https://api.anthropic.com/v1/organizations/workspaces/{workspace_id}/members/{user_id}" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY" \
--data '{
"workspace_role": "workspace_admin"
}'
# Remove member from workspace
curl --request DELETE "https://api.anthropic.com/v1/organizations/workspaces/{workspace_id}/members/{user_id}" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
</CodeGroup>
### API Keys
Monitor and manage [API keys](https://platform.claude.com/docs/en/api/admin-api/apikeys/get-api-key):
<CodeGroup>
```bash cURL
# List API keys
curl "https://api.anthropic.com/v1/organizations/api_keys?limit=10&status=active&workspace_id=wrkspc_xxx" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
# Update API key
curl --request POST "https://api.anthropic.com/v1/organizations/api_keys/{api_key_id}" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY" \
--data '{
"status": "inactive",
"name": "New Key Name"
}'
```
</CodeGroup>
## Accessing organization info
Get information about your organization programmatically with the `/v1/organizations/me` endpoint.
For example:
```bash cURL
curl "https://api.anthropic.com/v1/organizations/me" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ADMIN_API_KEY"
```
```json
{
"id": "12345678-1234-5678-1234-567812345678",
"type": "organization",
"name": "Organization Name"
}
```
This endpoint is useful for programmatically determining which organization an Admin API key belongs to.
For complete parameter details and response schemas, see the [Organization Info API reference](../Admin/beta-organization-retrieve.md).
## Usage and cost reports
Track your organization's usage and costs with the [Usage and Cost API](build-with-claude-usage-cost-api.md).
## Claude Code analytics
Monitor developer productivity and Claude Code adoption with the [Claude Code Analytics API](build-with-claude-claude-code-analytics-api.md).
## Rate limits
Read the rate limits configured for your organization and its workspaces with the [Rate Limits API](build-with-claude-rate-limits-api.md).
## Best practices
To effectively use the Admin API:
- Use meaningful names and descriptions for workspaces and API keys
- Implement proper error handling for failed operations
- Regularly audit member roles and permissions
- Clean up unused workspaces and expired invites
- Monitor API key usage and rotate keys periodically
## FAQ
<section title="What permissions are needed to use the Admin API?">
Only organization members with the admin role can use the Admin API. They must also have a special Admin API key (starting with `sk-ant-admin`).
</section>
<section title="Can I create new API keys through the Admin API?">
No, new API keys can only be created through the Claude Console for security reasons. The Admin API can only manage existing API keys.
</section>
<section title="What happens to API keys when removing a user?">
API keys persist in their current state as they are scoped to the Organization, not to individual users.
</section>
<section title="Can organization admins be removed via the API?">
No, organization members with the admin role cannot be removed via the API for security reasons.
</section>
<section title="How long do organization invites last?">
Organization invites expire after 21 days. There is currently no way to modify this expiration period.
</section>
For workspace-specific questions, see the [Workspaces FAQ](../Other/manage-claude-workspaces.md#faq).
---
## Batch processing - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/batch-processing
Path: 04-API-Reference/Guides/build-with-claude-batch-processing.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fbatch-processing)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Model capabilities
# Batch processing
Copy page
Process large volumes of Messages requests asynchronously with the Message Batches API, cutting costs by 50% and increasing throughput.
Copy page
Batch processing is a powerful approach for handling large volumes of requests efficiently. Instead of processing requests one at a time with immediate responses, batch processing allows you to submit multiple requests together for asynchronous processing. This pattern is particularly useful when:
- You need to process large volumes of data
- Immediate responses are not required
- You want to optimize for cost efficiency
- You're running large-scale evaluations or analyses
The Message Batches API is Anthropic's first implementation of this pattern.
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
# Message Batches API
The Message Batches API is a powerful, cost-effective way to asynchronously process large volumes of [Messages](../Endpoints/messages-create.md) requests. This approach is well-suited to tasks that do not require immediate responses, with most batches finishing in less than 1 hour while reducing costs by 50% and increasing throughput.
You can [explore the API reference directly](../Endpoints/messages-batches-create.md), in addition to this guide.
## How the Message Batches API works
When you send a request to the Message Batches API:
1. The system creates a new Message Batch with the provided Messages requests.
2. The batch is then processed asynchronously, with each request handled independently.
3. You can poll for the status of the batch and retrieve results when processing has ended for all requests.
This is especially useful for bulk operations that don't require immediate results, such as:
- Large-scale evaluations: Process thousands of test cases efficiently.
- Content moderation: Analyze large volumes of user-generated content asynchronously.
- Data analysis: Generate insights or summaries for large datasets.
- Bulk content generation: Create large amounts of text for various purposes (for example, product descriptions, article summaries).
### Batch limitations
- A Message Batch is limited to either 100,000 Message requests or 256 MB in size, whichever is reached first.
- The system processes each batch as fast as possible, with most batches completing within 1 hour. You can access batch results when all messages have completed or after 24 hours, whichever comes first. Batches expire if processing does not complete within 24 hours.
- Batch results are available for 29 days after creation. After that, you may still view the Batch, but its results will no longer be available for download.
- Batches are scoped to a [Workspace](../Other/usage-limits.md). You may view all batches (and their results) that were created within the Workspace your request runs in.
- Rate limits apply to both Batches API HTTP requests and the number of requests within a batch waiting to be processed. See [Message Batches API rate limits](../Endpoints/rate-limits.md#message-batches-api). Additionally, processing may be slowed down based on current demand and your request volume. In that case, you may see more requests expiring after 24 hours.
- Because of high throughput and concurrent processing, batches may go slightly over your Workspace's configured [spend limit](../Other/usage-limits.md).
- Each batched request must have `max_tokens` of at least `1`. `max_tokens: 0` ([cache pre-warming](build-with-claude-prompt-caching.md#pre-warming-the-cache)) is not supported inside a batch, because an ephemeral cache entry written during batch processing would likely expire before the follow-up request runs.
### Supported models
All [active models](../../20-Models/about-claude-models-overview.md) support the Message Batches API.
### What can be batched
Almost any request you can make to the Messages API can be included in a batch. This includes:
- Vision
- Tool use, including all [server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md) (web search, web fetch, code execution, MCP connectors, advisor, and tool search)
- System messages
- Multi-turn conversations
- Extended thinking
- Most beta features
Because each request in the batch is processed independently, you can mix different types of requests within a single batch.
A small number of Messages API parameters are **not** supported in batch requests. Including any of these returns a validation error:
| Parameter | Why |
|-------------------------------------------------------------|--------------------------------------------------------------------------------------------|
| `stream: true` | Batch results come back as a single file, not a stream. |
| `speed` ([Fast mode](build-with-claude-fast-mode.md)) | Fast mode tunes synchronous latency, which doesn't apply to asynchronous batch processing. |
| `max_tokens: 0` | See [Batch limitations](#batch-limitations). |
Because batches can take longer than 5 minutes to process, consider using the [1-hour cache duration](build-with-claude-prompt-caching.md#1-hour-cache-duration) with prompt caching for better cache hit rates when processing batches with shared context.
## Pricing
The Batches API offers significant cost savings. All usage is charged at 50% of the standard API prices.
[TABLE]
## How to use the Message Batches API
### Prepare and create your batch
A Message Batch is composed of a list of requests to create a Message. The shape of an individual request comprises:
- A unique `custom_id` for identifying the Messages request. Must be 1 to 64 characters and contain only alphanumeric characters, hyphens, and underscores (matching `^[a-zA-Z0-9_-]{1,64}$`).
- A `params` object with the standard [Messages API](../Endpoints/messages-create.md) parameters
You can [create a batch](../Endpoints/messages-batches-create.md) by passing this list into the `requests` parameter:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
from anthropic.types.messages.batch_create_params import Request
client = anthropic.Anthropic()
message_batch = client.messages.batches.create(
requests=[
Request(
custom_id="my-first-request",
params=MessageCreateParamsNonStreaming(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Hello, world",
}
],
),
),
Request(
custom_id="my-second-request",
params=MessageCreateParamsNonStreaming(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Hi again, friend",
}
],
),
),
]
)
print(message_batch)
```
In this example, two separate requests are batched together for asynchronous processing. Each request has a unique `custom_id` and contains the standard parameters you'd use for a Messages API call.
**Test your batch requests with the Messages API**
Validation of the `params` object for each message request is performed asynchronously, and validation errors are returned when processing of the entire batch has ended. You can ensure that you are building your input correctly by verifying your request shape with the [Messages API](../Endpoints/messages-create.md) first.
When a batch is first created, the response has a processing status of `in_progress`.
Output
```python
{
"id": "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d",
"type": "message_batch",
"processing_status": "in_progress",
"request_counts": {
"processing": 2,
"succeeded": 0,
"errored": 0,
"canceled": 0,
"expired": 0
},
"ended_at": null,
"created_at": "2024-09-24T18:37:24.100435Z",
"expires_at": "2024-09-25T18:37:24.100435Z",
"cancel_initiated_at": null,
"results_url": null
}
```
### Tracking your batch
The Message Batch's `processing_status` field indicates the stage of processing the batch is in. It starts as `in_progress`, then updates to `ended` once all the requests in the batch have finished processing, and results are ready. You can monitor the state of your batch by visiting the [Console](https://platform.claude.com/settings/workspaces/default/batches), or using the [retrieval endpoint](../Endpoints/messages-batches-retrieve.md).
#### Polling for Message Batch completion
To poll a Message Batch, you'll need its `id`, which is provided in the response when creating a batch or by listing batches. You can implement a polling loop that checks the batch status periodically until processing has ended:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import time
client = anthropic.Anthropic()
MESSAGE_BATCH_ID = "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d"
message_batch = None
while True:
message_batch = client.messages.batches.retrieve(MESSAGE_BATCH_ID)
if message_batch.processing_status == "ended":
break
print(f"Batch {MESSAGE_BATCH_ID} is still processing...")
time.sleep(60)
print(message_batch)
```
### Listing all Message Batches
You can list all Message Batches in your Workspace using the [list endpoint](../Endpoints/messages-batches-list.md). The API supports pagination, automatically fetching additional pages as needed:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Automatically fetches more pages as needed.
for message_batch in client.messages.batches.list(limit=20):
print(message_batch)
```
### Retrieving batch results
Once batch processing has ended, each Messages request in the batch has a result. There are four result types:
| Result type | Description |
|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `succeeded` | Request was successful. Includes the message result. |
| `errored` | Request encountered an error and a message was not created. Possible errors include invalid requests and internal server errors. You will not be billed for these requests. |
| `canceled` | User canceled the batch before this request could be sent to the model. You will not be billed for these requests. |
| `expired` | Batch reached its 24-hour expiration before this request could be sent to the model. You will not be billed for these requests. |
The batch's `request_counts` shows an overview of your results, indicating how many requests reached each of these four states.
Results of the batch are available for download at the `results_url` property on the Message Batch, and if the organization permission allows, in the Console. Because of the potentially large size of the results, it's recommended to [stream results](../Endpoints/messages-batches-results.md) back rather than download them all at once.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Stream results file in memory-efficient chunks, processing one at a time
for result in client.messages.batches.results(
"msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d",
):
outcome = result.result
match outcome.type:
case "succeeded":
print(f"Success! {result.custom_id}")
case "errored":
if outcome.error.error.type == "invalid_request_error":
# Request body must be fixed before re-sending request
print(f"Validation error {result.custom_id}")
else:
# Request can be retried directly
print(f"Server error {result.custom_id}")
case "expired":
print(f"Request expired {result.custom_id}")
```
The results are in `.jsonl` format, where each line is a valid JSON object representing the result of a single request in the Message Batch. For each streamed result, you can do something different depending on its `custom_id` and result type. Here is an example set of results:
.jsonl file
```python
{"custom_id":"my-second-request","result":{"type":"succeeded","message":{"id":"msg_014VwiXbi91y3JMjcpyGBHX5","type":"message","role":"assistant","model":"claude-opus-5-5","content":[{"type":"text","text":"Hello again! It's nice to see you. How can I assist you today? Is there anything specific you'd like to chat about or any questions you have?"}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":11,"output_tokens":36}}}}
{"custom_id":"my-first-request","result":{"type":"succeeded","message":{"id":"msg_01FqfsLoHwgeFbguDgpz48m7","type":"message","role":"assistant","model":"claude-opus-5-5","content":[{"type":"text","text":"Hello! How can I assist you today? Feel free to ask me any questions or let me know if there's anything you'd like to chat about."}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":10,"output_tokens":34}}}}
```
If your result has an error, its `result.error` will be set to the standard [error shape](../Endpoints/errors.md#error-shapes).
**Batch results may not match input order**
Batch results can be returned in any order, and may not match the ordering of requests when the batch was created. In the preceding example, the result for the second batch request is returned before the first. To correctly match results with their corresponding requests, always use the `custom_id` field.
### Canceling a Message Batch
You can cancel a Message Batch that is currently processing using the [cancel endpoint](../Endpoints/messages-batches-cancel.md). Immediately after cancellation, a batch's `processing_status` will be `canceling`. You can use the same polling technique described earlier to wait until cancellation is finalized. Canceled batches end up with a status of `ended` and may contain partial results for requests that were processed before cancellation.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
MESSAGE_BATCH_ID = "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d"
message_batch = client.messages.batches.cancel(
MESSAGE_BATCH_ID,
)
print(message_batch)
```
The response shows the batch in a `canceling` state:
Output
```python
{
"id": "msgbatch_013Zva2CMHLNnXjNJJKqJ2EF",
"type": "message_batch",
"processing_status": "canceling",
"request_counts": {
"processing": 2,
"succeeded": 0,
"errored": 0,
"canceled": 0,
"expired": 0
},
"ended_at": null,
"created_at": "2024-09-24T18:37:24.100435Z",
"expires_at": "2024-09-25T18:37:24.100435Z",
"cancel_initiated_at": "2024-09-24T18:39:03.114875Z",
"results_url": null
}
```
### Using prompt caching with Message Batches
The Message Batches API supports prompt caching, allowing you to potentially reduce costs and processing time for batch requests. The pricing discounts from prompt caching and Message Batches can stack, providing even greater cost savings when both features are used together. However, because batch requests are processed asynchronously and concurrently, cache hits are provided on a best-effort basis. Users typically experience cache hit rates ranging from 30% to 98%, depending on their traffic patterns.
To maximize the likelihood of cache hits in your batch requests:
1. Include identical `cache_control` blocks in every Message request within your batch.
2. Maintain a steady stream of requests to prevent cache entries from expiring after their 5-minute lifetime.
3. Structure your requests to share as much cached content as possible.
Example of implementing prompt caching in a batch:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
from anthropic.types.messages.batch_create_params import Request
client = anthropic.Anthropic()
message_batch = client.messages.batches.create(
requests=[
Request(
custom_id="my-first-request",
params=MessageCreateParamsNonStreaming(
model="claude-opus-5-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n",
},
{
"type": "text",
"text": "<the entire contents of Pride and Prejudice>",
"cache_control": {"type": "ephemeral"},
},
],
messages=[
{
"role": "user",
"content": "Analyze the major themes in Pride and Prejudice.",
}
],
),
),
Request(
custom_id="my-second-request",
params=MessageCreateParamsNonStreaming(
model="claude-opus-5-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n",
},
{
"type": "text",
"text": "<the entire contents of Pride and Prejudice>",
"cache_control": {"type": "ephemeral"},
},
],
messages=[
{
"role": "user",
"content": "Write a summary of Pride and Prejudice.",
}
],
),
),
]
)
```
In this example, both requests in the batch include identical system messages and the full text of Pride and Prejudice marked with `cache_control` to increase the likelihood of cache hits.
### Server tools and the agentic loop
All [server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md) (web search, web fetch, code execution, MCP connectors, advisor, and tool search) work in batch requests. The batch worker runs the same server-side agentic loop as the synchronous Messages API.
Because there is no open connection to maintain, the batch loop runs **more iterations per turn** than a synchronous request before it returns `stop_reason: "pause_turn"`. If a batch result comes back with `pause_turn`, the turn did not finish; you can continue it by submitting the paused assistant content in a follow-up request (batch or synchronous) exactly as shown in the [pause_turn continuation pattern](../Agents-Tools/agents-and-tools-tool-use-server-tools.md#the-server-side-loop-and-pause-turn).
The batch worker additionally throttles `web_search` per organization so that highly concurrent batch processing does not exhaust your organization's web-search rate limit. The batch retries throttled requests automatically; you don't need to handle this yourself, but very large web-search batches might take longer to complete.
### Extended output (beta)
The `output-300k-2026-03-24` beta header raises the `max_tokens` cap to 300,000 for batch requests using Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 5, or Claude Sonnet 4.6. Include the header to generate outputs far longer than the standard 128k `max_tokens` limit in a single turn.
Extended output is available on the Message Batches API only, not the synchronous Messages API. It is supported on the Claude API and Claude Platform on AWS, and is not currently available on Amazon Bedrock, Google Cloud, or Microsoft Foundry.
Use extended output for long-form generation such as book-length drafts and technical documentation, exhaustive structured data extraction, large code-generation scaffolds, and long reasoning chains.
A single 300k-token generation can take over an hour to complete, so plan your batch submissions with the 24-hour processing window in mind. Standard batch pricing (50% of standard API prices) applies.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.types.beta.message_create_params import MessageCreateParamsNonStreaming
from anthropic.types.beta.messages.batch_create_params import Request
client = anthropic.Anthropic()
message_batch = client.beta.messages.batches.create(
betas=["output-300k-2026-03-24"],
requests=[
Request(
custom_id="long-form-request",
params=MessageCreateParamsNonStreaming(
model="claude-opus-5-5",
max_tokens=300_000,
messages=[
{
"role": "user",
"content": "Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices.",
}
],
),
),
],
)
print(message_batch)
```
### Best practices for effective batching
To get the most out of the Batches API:
- Monitor batch processing status regularly and implement appropriate retry logic for failed requests.
- Use meaningful `custom_id` values to easily match results with requests, since order is not guaranteed.
- Consider breaking very large datasets into multiple batches for better manageability.
- Dry run a single request shape with the Messages API to avoid validation errors.
### Troubleshooting common issues
If experiencing unexpected behavior:
- Verify that the total batch request size doesn't exceed 256 MB. If the request size is too large, you may get a 413 `request_too_large` error.
- Check that you're using [supported models](#supported-models) for all requests in the batch.
- Ensure each request in the batch has a unique `custom_id`.
- Ensure that it has been less than 29 days since batch `created_at` (not processing `ended_at`) time. If over 29 days have passed, results will no longer be viewable.
- Confirm that the batch has not been canceled.
Note that the failure of one request in a batch does not affect the processing of other requests.
## Batch storage and privacy
- **Workspace isolation**: Batches are isolated within the Workspace they are created in. They can only be accessed by API requests in that same Workspace, or users with permission to view Workspace batches in the Console.
- **Result availability**: Batch results are available for 29 days after the batch is created, allowing ample time for retrieval and processing.
## Data retention
Batch processing stores request and response data for up to 29 days after batch creation. You can delete a message batch at any time after processing using the `DELETE /v1/messages/batches/{batch_id}` endpoint. To delete an in-progress batch, cancel it first. Asynchronous processing requires server-side storage of both inputs and outputs until batch completion and result retrieval.
For ZDR eligibility across all features, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
## FAQ
### How long does it take for a batch to process?
Batches may take up to 24 hours for processing, but many finish sooner. Actual processing time depends on the size of the batch, current demand, and your request volume. It is possible for a batch to expire and not complete within 24 hours.
### Is the Batches API available for all models?
See [Supported models](#supported-models) for the list of supported models.
### Can I use the Message Batches API with other API features?
Yes, the Message Batches API supports nearly all features available in the Messages API, including most beta features. A small number of parameters (`stream`, `speed`, and `max_tokens: 0`) are not supported. See [What can be batched](#what-can-be-batched) for the full list.
### How does the Message Batches API affect pricing?
The Message Batches API offers a 50% discount on all usage compared to standard API prices. This applies to input tokens, output tokens, and any special tokens. For more on pricing, visit [Pricing](../../17-Billing-Plans/pricing.md#anthropic-api).
### Can I update a batch after it's been submitted?
No, once a batch has been submitted, it cannot be modified. If you need to make changes, you should cancel the current batch and submit a new one. Note that cancellation may not take immediate effect.
### Are there Message Batches API rate limits and do they interact with the Messages API rate limits?
The Message Batches API has HTTP requests-based rate limits in addition to limits on the number of requests in need of processing. See [Message Batches API rate limits](../Endpoints/rate-limits.md#message-batches-api). Usage of the Batches API does not affect rate limits in the Messages API.
### How do I handle errors in my batch requests?
When you retrieve the results, each request has a `result` field indicating whether it `succeeded`, `errored`, was `canceled`, or `expired`. For `errored` results, additional error information is provided. View the error response object in the [API reference](../Endpoints/messages-batches-create.md).
### How does the Message Batches API handle privacy and data separation?
The Message Batches API is designed with strong privacy and data separation measures:
1. Batches and their results are isolated within the Workspace in which they were created. This means they can only be accessed by API requests in that same Workspace.
2. Each request within a batch is processed independently, with no data leakage between requests.
3. Results are only available for a limited time (29 days), and follow Anthropic's [data retention policy](../../13-Enterprise-Admin/how-long-do-you-store-personal-data.md).
4. Downloading batch results in the Console can be disabled on the organization-level or on a per-workspace basis.
### Can I use prompt caching in the Message Batches API?
Yes, it is possible to use prompt caching with Message Batches API. However, because asynchronous batch requests can be processed concurrently and in any order, cache hits are provided on a best-effort basis.
## Next steps
[Search results](build-with-claude-search-results.md)
Enable natural citations for RAG applications by providing search results with source attribution.
[Prompt caching](build-with-claude-prompt-caching.md)
Reduce cost and latency by caching prompt prefixes shared across requests in a batch.
---
## Cache diagnostics - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics
Path: 04-API-Reference/Guides/build-with-claude-cache-diagnostics.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fcache-diagnostics)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Context management
# Cache diagnostics
Copy page
Diagnose unexpected prompt cache misses by comparing consecutive requests and identifying exactly where the prompt prefix diverged.
Copy page
Cache diagnostics
[ZDR](../Other/manage-claude-api-and-data-retention.md)
Eligible
excludes [Covered Models](../Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements)
[Prompt caching](build-with-claude-prompt-caching.md) cuts latency and cost significantly, but only when the beginning of your prompt is byte-for-byte identical to a recent request. A reordered tool, a timestamp interpolated into your system prompt, or an edit to an earlier message can silently invalidate the cache. Without cache diagnostics, the only signal is `usage.cache_read_input_tokens` dropping to zero, with no indication of what changed.
Cache diagnostics closes that gap. Pass the `id` of your previous response, and the API compares the two requests and tells you where they diverged (the model, the system prompt, the tools, or the message history) so you can fix the root cause instead of guessing.
## How cache diagnostics works
For each request that includes the `diagnostics` object, the API stores a lightweight fingerprint keyed by the response `id`. It stores nothing for requests that omit the object. On your next request, include the previous response's `id` as `diagnostics.previous_message_id`. The API rebuilds the fingerprint for the new request, compares it against the stored one, and attaches a `diagnostics` object to the response describing the first point of divergence.
The comparison is about request structure, independent of whether the cache actually hit. See [Reading diagnostics alongside usage](#reading-diagnostics-alongside-usage) for how to combine the `diagnostics` result with `usage.cache_read_input_tokens`.
Fingerprints contain only hashes and token-count estimates (never raw prompt content), are retained for a limited time, are scoped to your organization and workspace, and are not used for any other purpose.
## Basic usage
Include the `diagnostics` object on every turn. The object is the opt-in: the API stores a fingerprint only for requests that include it. On the first turn, pass `"previous_message_id": null` to opt in without a prior message to compare against. On subsequent turns, pass the `id` from the previous response. The `cache-diagnosis-2026-04-07` beta header is no longer required, and requests that still send it work as before.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
SYSTEM = "You are an AI assistant analyzing a large document. <document>...</document>"
# Turn 1: opt in with previous_message_id=None
r1 = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[{"role": "user", "content": "Summarize section 1."}],
diagnostics={"previous_message_id": None},
)
# Turn 2: reference the previous response id
r2 = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[
{"role": "user", "content": "Summarize section 1."},
{"role": "assistant", "content": r1.content},
{"role": "user", "content": "Now summarize section 2."},
],
diagnostics={"previous_message_id": r1.id},
)
diagnostics = r2.diagnostics
if diagnostics is None:
print("No divergence detected.")
elif diagnostics.cache_miss_reason is None:
print("Comparison still pending.")
else:
print(f"cache_miss_reason: {diagnostics.cache_miss_reason.type}")
```
## Streaming
In streaming responses, `diagnostics` appears on the `message_start` event.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
# Turn 2: stream, referencing the previous response id
with client.beta.messages.stream(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[
{"role": "user", "content": "Summarize section 1."},
{"role": "assistant", "content": r1.content},
{"role": "user", "content": "Now summarize section 2."},
],
diagnostics={"previous_message_id": r1.id},
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
print()
r2 = stream.get_final_message()
diagnostics = r2.diagnostics
if diagnostics is None:
print("No divergence detected.")
elif diagnostics.cache_miss_reason is None:
print("Comparison still pending.")
else:
print(f"cache_miss_reason: {diagnostics.cache_miss_reason.type}")
```
The `message_start` event carries the full `diagnostics` field; see [Response format](#response-format) for the possible values.
## Threading diagnostics through a conversation loop
In a multi-turn conversation, carry the latest response `id` forward as `previous_message_id` on every turn. The first iteration passes `null` to opt in; each subsequent iteration passes the `id` from the previous response.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
SYSTEM = "You are an AI assistant analyzing a large document. <document>...</document>"
messages = []
prev_id = None
for i, user_message in enumerate(
["Summarize section 1.", "Now section 2.", "Now section 3."]
):
messages.append({"role": "user", "content": user_message})
r = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=messages,
diagnostics={"previous_message_id": prev_id},
)
if r.diagnostics is not None and r.diagnostics.cache_miss_reason is not None:
print(f"Turn {i + 1} cache_miss_reason: {r.diagnostics.cache_miss_reason.type}")
messages.append({"role": "assistant", "content": r.content})
prev_id = r.id
```
## Response format
The `diagnostics` field on the response `Message` has three possible values:
| Value | Meaning |
|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `null` | The request did not include the `diagnostics` object, `previous_message_id` was `null` (first turn, nothing to compare), or a comparison ran and found no divergence. |
| `{"cache_miss_reason": null}` | The comparison was still running when the response was serialized. This can happen when the response starts very quickly. Treat it as inconclusive and check the next turn. |
| `{"cache_miss_reason": {...}}` | A `cache_miss_reason` is attached. For `*_changed` types this identifies the first divergence point; `previous_message_not_found` and `unavailable` are cases where no comparison was produced. |
When `cache_miss_reason` is non-null, it looks like this:
```python
{
"id": "msg_01Xyz...",
"type": "message",
"role": "assistant",
"content": [{ "type": "text", "text": "..." }],
"usage": {
"input_tokens": 42,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 41850,
"output_tokens": 210
},
"diagnostics": {
"cache_miss_reason": {
"type": "system_changed",
"cache_missed_input_tokens": 41850
}
}
}
```
## Cache miss reason types
`cache_miss_reason` is a discriminated union on `type`. The response reports the earliest divergence only, so fix it first; later ones may be hidden behind it.
| Type | What it means | What to change |
|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `model_changed` | The `model` differs from the previous request (for example, a router, A/B test, or fallback selected a different model). The cache is per-model. | Hold the model constant within a cached conversation. |
| `system_changed` | The `system` parameter differs. Typically a timestamp, request ID, or other per-request value was interpolated into the system prompt. | Make the system prompt a byte-stable constant and move dynamic data into the first `user` message after your cache breakpoint. |
| `tools_changed` | The `tools` array differs: tools were added, removed, or reordered between turns, or tool `input_schema` JSON was serialized non-deterministically. | Send the same tool list on every turn in a fixed order with deterministically serialized schemas (for example, sort keys). |
| `messages_changed` | The model, system, and tools all match, but an earlier entry in `messages` was altered, reordered, or removed rather than appended to. Typically conversation history was truncated or edited, or assistant turns and `tool_result` blocks were re-serialized differently on resend. | Treat the history as append-only; echo assistant `content` and tool results back verbatim. |
| `previous_message_not_found` | No stored fingerprint exists for the supplied `previous_message_id`. This is not evidence that your request changed. Typically the previous request did not include the `diagnostics` object, it came from a different workspace, or too much time has passed since it was sent. | Include the `diagnostics` object on every turn and keep consecutive turns close together in time. |
| `unavailable` | Diagnostic information was not available for this request. This includes the case where `model`, `system`, and `tools` match but another prompt-affecting request parameter (`tool_choice`, `thinking`, `context_management`, `output_config`, `output_format`, or the set of active `anthropic-beta` headers) differs, and very long conversations where the divergence is beyond the comparison horizon. Your request was processed normally. | Keep the prompt-affecting request parameters constant for the lifetime of a cached conversation. If persistent, apply the manual checks under [Troubleshooting common issues](build-with-claude-prompt-caching.md#troubleshooting-common-issues) on the prompt caching page. |
The four `*_changed` types also carry a `cache_missed_input_tokens` integer: an estimate of how many input tokens fell after the divergence point, giving you a sense of how much cacheable prefix was lost. It is derived from byte lengths before tokenization, so treat it as a magnitude indicator rather than a billing number. It can differ from (and occasionally exceed) `usage.input_tokens`.
## Reading diagnostics alongside usage
`diagnostics` answers "did my request change?" while `usage.cache_read_input_tokens` answers "did the cache hit?". Combining them tells you where to look.
This matrix applies to turns where you passed a real `previous_message_id`. On the first turn (`previous_message_id: null`), `diagnostics` is always `null` and `cache_read_input_tokens` is normally zero because the cache is being written, not read; no troubleshooting is needed. The matrix also does not apply when `cache_miss_reason` is `null` (the comparison is still pending; check the next turn) or when its `type` is `previous_message_not_found` or `unavailable` (no comparison was produced).
| Diagnostics result | Cache read tokens | Interpretation |
|-------------------------------------------|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `null` | high | Working as expected. Your prefix is stable and the cache hit. |
| `null` | low or zero | Your requests match but the cache entry was no longer available. Consider shortening gaps between turns or using the [1-hour cache TTL](build-with-claude-prompt-caching.md#1-hour-cache-duration). |
| `cache_miss_reason` is a `*_changed` type | low or zero | Your bug. The request changed; fix the cause indicated by `type`. |
| `cache_miss_reason` is a `*_changed` type | high | Rare. A change occurred late in the prompt but an earlier `cache_control` breakpoint still hit. Worth fixing, but low impact. |
## Limitations
- **Claude API only:** Not available on Amazon Bedrock or Google Cloud.
- **Limited retention:** Fingerprints for `previous_message_id` lookup expire after a short period. Run diagnostic comparisons between closely spaced requests.
- **Same workspace:** The previous request must have run in the same organization and workspace. To check, compare the `anthropic-workspace-id` [response header](../Endpoints/overview.md#response-headers) on the two responses.
- **Comparison horizon:** For very long conversations where the only change is deep in the message list, the response may be `unavailable` rather than a precise location.
- **Best-effort:** Diagnostics never blocks or fails your request. If diagnostic information is not available, the response returns `unavailable`, or `cache_miss_reason: null` when the comparison was still running.
## Data retention
Cache diagnostics is ZDR eligible (qualified). Anthropic does not store the raw text of your prompts or Claude's outputs for this feature.
The API stores a fingerprint only for requests that include the `diagnostics` object. The fingerprint consists only of cryptographic hashes and token-count estimates, keyed by the response `id` and scoped to your organization and workspace. Fingerprints expire after a short period and are not used for any other purpose.
For ZDR eligibility across all features, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
## See also
- [Prompt caching](build-with-claude-prompt-caching.md)
- [Token counting](build-with-claude-token-counting.md)
## Compatibility
Supported platforms
- Claude API
---
## Citations - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/citations
Path: 04-API-Reference/Guides/build-with-claude-citations.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fcitations)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Model capabilities
# Citations
Copy page
Ground Claude's responses in your source documents. Citations return the exact passages that support each claim, so you can verify answers and surface sources to your users.
Copy page
Citations
[ZDR](../Other/manage-claude-api-and-data-retention.md)
Eligible
excludes [Covered Models](../Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements)
Claude can provide detailed citations when answering questions about documents, helping you track and verify the sources behind each response.
All [active models](../../20-Models/about-claude-models-overview.md) support citations.
Share your feedback and suggestions about the citations feature using the [citations feedback form](https://forms.gle/9n9hSrKnKe3rpowH9).
The following example shows how to enable citations on a plain text document with the Messages API:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "text",
"media_type": "text/plain",
"data": "The grass is green. The sky is blue.",
},
"title": "My Document",
"context": "This is a trustworthy document.",
"citations": {"enabled": True},
},
{"type": "text", "text": "What color is the grass and sky?"},
],
}
],
)
print(response)
```
**Comparison with prompt-based approaches**
Compared to prompting Claude to cite sources, the citations feature offers the following advantages:
- **Cost savings:** If your prompt-based approach asks Claude to output direct quotes, you may see cost savings because `cited_text` does not count toward your output tokens.
- **Better citation reliability:** Because the API parses citations into the response formats described in the following sections and extracts `cited_text` directly, citations are guaranteed to contain valid pointers to the provided documents.
- **Improved citation quality:** In Anthropic's evaluations, the citations feature is significantly more likely to cite the most relevant quotes from documents than purely prompt-based approaches.
------------------------------------------------------------------------
## How citations work
Integrate citations with Claude in these steps:
1. 1
### Provide document(s) and enable citations
- Include documents in any of the supported formats: [PDFs](#pdf-documents), [plain text](#plain-text-documents), or [custom content](#custom-content-documents) documents.
- Set `citations.enabled=true` on each of your documents. Currently, citations must be enabled on all or none of the documents within a request.
- Only text citations are currently supported. Image citations are not yet possible.
2. 2
### Documents get processed
- Document contents are "chunked" to define the minimum granularity of possible citations. For example, sentence chunking lets Claude cite a single sentence or chain together multiple consecutive sentences to cite a paragraph or longer passage.
- **For PDFs:** Text is extracted as described in [PDF support](build-with-claude-pdf-support.md) and content is chunked into sentences. Citing images from PDFs is not currently supported.
- **For plain text documents:** Content is chunked into sentences that can be cited from.
- **For custom content documents:** Your provided content blocks are used as-is and no further chunking is done.
3. 3
### Claude provides cited response
- Responses may now include multiple text blocks where each text block can contain a claim that Claude is making and a list of citations that support the claim.
- Citations reference specific locations in source documents. The format of these citations is dependent on the type of document being cited from.
- **For PDFs:** Citations include the page number range (1-indexed).
- **For plain text documents:** Citations include the character index range (0-indexed).
- **For custom content documents:** Citations include the content block index range (0-indexed) corresponding to the original content list provided.
- Document indices are provided to indicate the reference source and are 0-indexed according to the list of all documents in your original request.
**Automatic chunking vs custom content**
By default, plain text and PDF documents are automatically chunked into sentences. If you need more control over citation granularity (for example, for bullet points or transcripts), use custom content documents instead. See [Document types](#document-types) for more details.
For example, if you want Claude to be able to cite specific sentences from your RAG chunks, you should put each RAG chunk into a plain text document. Otherwise, if you do not want any further chunking to be done, or if you want to customize any additional chunking, you can put RAG chunks into custom content document(s).
### Citable versus non-citable content
- Text found within a document's `source` content can be cited from.
- `title` and `context` are optional fields that are passed to the model but not used toward cited content.
- `title` is limited in length, so the `context` field is useful for storing document metadata as text or stringified JSON.
### Citation indices
- Document indices are 0-indexed from the list of all document content blocks in the request (spanning across all messages).
- Character indices are 0-indexed with exclusive end indices.
- Page numbers are 1-indexed with exclusive end page numbers.
- Content block indices are 0-indexed with exclusive end indices from the `content` list provided in the custom content document.
### Token costs
- Enabling citations incurs a slight increase in input tokens because of system prompt additions and document chunking.
- However, the citations feature is very efficient with output tokens. Internally, the model outputs citations in a standardized format that are then parsed into cited text and document location indices. The `cited_text` field is provided for convenience and does not count toward output tokens.
- When passed back in subsequent conversation turns, `cited_text` is also not counted toward input tokens.
### Feature compatibility
Citations work in conjunction with other API features including [prompt caching](build-with-claude-prompt-caching.md), [token counting](build-with-claude-token-counting.md), and [batch processing](build-with-claude-batch-processing.md).
**Citations and structured outputs are incompatible**
Citations cannot be used together with [structured outputs](build-with-claude-structured-outputs.md). If you enable citations on any user-provided document (`document` blocks or `search_result` blocks) and also include the `output_config.format` parameter (or the deprecated `output_format` parameter), the API returns a 400 error.
This is because citations require interleaving citation blocks with text output, which is incompatible with the strict JSON schema constraints of structured outputs.
#### Using prompt caching with citations
Citations and prompt caching can be used together effectively.
The citation blocks generated in responses cannot be cached directly, but the source documents they reference can be cached. To optimize performance, apply `cache_control` to your top-level document content blocks.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Long document content (for example, technical documentation)
long_document = (
"This is a very long document with thousands of words..." + " ... " * 1000
) # Minimum cacheable length
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "text",
"media_type": "text/plain",
"data": long_document,
},
"citations": {"enabled": True},
"cache_control": {
"type": "ephemeral"
}, # Cache the document content
},
{
"type": "text",
"text": "What does this document say about API features?",
},
],
}
],
)
print(response)
```
In this example:
- The document content is cached using `cache_control` on the document block.
- Citations are enabled on the document.
- Claude can generate responses with citations while benefiting from cached document content.
- Subsequent requests using the same document benefit from the cached content.
## Document types
### Choosing a document type
Three document types are supported for citations. Documents can be provided directly in the message (base64, text, or URL) or uploaded through the [Files API](build-with-claude-files.md) and referenced by `file_id`:
| Type | Best for | Chunking | Citation format |
|:---------------|:----------------------------------------------------------------|:-----------------------|:------------------------------|
| Plain text | Simple text documents, prose | Sentence | Character indices (0-indexed) |
| PDF | PDF files with text content | Sentence | Page numbers (1-indexed) |
| Custom content | Lists, transcripts, special formatting, more granular citations | No additional chunking | Block indices (0-indexed) |
For file types that the `document` block doesn't support (for example, .docx and .xlsx), convert the files to plain text and include the content directly in message content. Files that are already plain text, such as .csv and .md files, can also be uploaded with an explicit `text/plain` content type. See [Working with other file formats](build-with-claude-files.md#working-with-other-file-formats).
### Plain text documents
Plain text documents are automatically chunked into sentences. You can provide them inline or by reference with their `file_id`:
Inline text
Files API
The intro example at the top of this page shows a complete plain text request in every SDK. The document block uses a `text` source:
```python
{
"type": "document",
"source": {
"type": "text",
"media_type": "text/plain",
"data": "Plain text content..."
},
"title": "Document Title",
"context": "Context about the document that will not be cited from",
"citations": { "enabled": true }
}
```
### Example plain text citation
```python
{
"type": "char_location",
"cited_text": "The exact text being cited", // not counted toward output tokens
"document_index": 0,
"document_title": "Document Title",
"start_char_index": 0, // 0-indexed
"end_char_index": 50 // exclusive
}
```
### PDF documents
PDF documents can be provided as base64-encoded data, a URL, or by `file_id`. PDF text is extracted and chunked into sentences. As image citations are not yet supported, PDFs that are scans of documents and do not contain extractable text are not citable.
Base64
URL
Files API
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
pdf_base64 = base64.standard_b64encode(
pathlib.Path("/path/to/document.pdf").read_bytes()
).decode()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": pdf_base64,
},
"title": "Document Title",
"context": "Context about the document that will not be cited from",
"citations": {"enabled": True},
},
{"type": "text", "text": "Summarize this document."},
],
}
],
)
print(response)
```
### Example PDF citation
```python
{
"type": "page_location",
"cited_text": "The exact text being cited", // not counted toward output tokens
"document_index": 0,
"document_title": "Document Title",
"start_page_number": 1, // 1-indexed
"end_page_number": 2 // exclusive
}
```
### Custom content documents
Custom content documents give you control over citation granularity. No additional chunking is done and chunks are provided to the model according to the content blocks provided.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "content",
"content": [
{"type": "text", "text": "First chunk"},
{"type": "text", "text": "Second chunk"},
],
},
"title": "Document Title",
"context": "Context about the document that will not be cited from",
"citations": {"enabled": True},
},
{"type": "text", "text": "Summarize this document."},
],
}
],
)
print(response)
```
### Example citation
```python
{
"type": "content_block_location",
"cited_text": "The exact text being cited", // not counted toward output tokens
"document_index": 0,
"document_title": "Document Title",
"start_block_index": 0, // 0-indexed
"end_block_index": 1 // exclusive
}
```
------------------------------------------------------------------------
## Response structure
When citations are enabled, responses include multiple text blocks with citations:
```python
{
"content": [
{ "type": "text", "text": "According to the document, " },
{
"type": "text",
"text": "the grass is green",
"citations": [
{
"type": "char_location",
"cited_text": "The grass is green.",
"document_index": 0,
"document_title": "Example Document",
"start_char_index": 0,
"end_char_index": 20
}
]
},
{ "type": "text", "text": " and " },
{
"type": "text",
"text": "the sky is blue",
"citations": [
{
"type": "char_location",
"cited_text": "The sky is blue.",
"document_index": 0,
"document_title": "Example Document",
"start_char_index": 20,
"end_char_index": 36
}
]
},
{
"type": "text",
"text": ". Information from page 5 states that "
},
{
"type": "text",
"text": "water is essential",
"citations": [
{
"type": "page_location",
"cited_text": "Water is essential for life.",
"document_index": 1,
"document_title": "PDF Document",
"start_page_number": 5,
"end_page_number": 6
}
]
},
{
"type": "text",
"text": ". The custom document mentions "
},
{
"type": "text",
"text": "important findings",
"citations": [
{
"type": "content_block_location",
"cited_text": "These are important findings.",
"document_index": 2,
"document_title": "Custom Content Document",
"start_block_index": 0,
"end_block_index": 1
}
]
}
]
}
```
### Streaming support
For streaming responses, citations arrive as a `citations_delta` delta type inside `content_block_delta` events. Each delta contains a single citation to add to the `citations` list on the current `text` content block.
### Example streaming events
```python
event: message_start
data: {"type": "message_start", ...}
event: content_block_start
data: {"type": "content_block_start", "index": 0, ...}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0,
"delta": {"type": "text_delta", "text": "According to..."}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0,
"delta": {"type": "citations_delta",
"citation": {
"type": "char_location",
"cited_text": "...",
"document_index": 0,
...
}}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 0}
event: message_stop
data: {"type": "message_stop"}
```
## Next steps
[Streaming messages](build-with-claude-streaming.md)
Handle the `citations_delta` delta type alongside text deltas to render cited responses as they stream.
[Search results](build-with-claude-search-results.md)
Pass search results from your RAG pipeline as first-class content blocks with built-in citation support.
[PDF support](build-with-claude-pdf-support.md)
Learn how Claude extracts text from PDFs and how page-based citations map back to your source files.
[Files API](build-with-claude-files.md)
Upload documents once and reference them by `file_id` across multiple citation requests.
## Compatibility
Supported platforms
- Claude API
- Claude Platform on AWS
- Amazon Bedrock
- Google Cloud
- Microsoft Foundry
---
## Claude Code Analytics API - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/claude-code-analytics-api
Path: 04-API-Reference/Guides/build-with-claude-claude-code-analytics-api.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [SDKs, CLI, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fmanage-claude%2Fclaude-code-analytics-api)
SearchCtrlK
Organization
[Admin API](../Other/manage-claude-admin-api.md)[User management](../Other/manage-claude-user-management.md)[Workspaces](../Other/manage-claude-workspaces.md)
Authentication
[Overview](../Other/manage-claude-authentication.md)[Create an Admin API key](../Other/manage-claude-admin-api-keys.md)[App Attest](../Other/manage-claude-app-attest.md)[Workload Identity Federation](../Other/manage-claude-workload-identity-federation.md)[Manage WIF via API](../Other/manage-claude-wif-admin-api.md)[WIF reference](../Other/manage-claude-wif-reference.md)
Identity providers
Monitoring
[Usage and Cost API](../Other/manage-claude-usage-cost-api.md)[Rate Limits API](../Other/manage-claude-rate-limits-api.md)[Analytics APIs](../Other/manage-claude-analytics-api.md)[Claude Code Analytics API](../Other/manage-claude-claude-code-analytics-api.md)[Spend Limits API](../Other/manage-claude-spend-limits-api.md)
Data & compliance
[Data residency](build-with-claude-data-residency.md)[API and data retention](../Other/manage-claude-api-and-data-retention.md)
[Access Transparency](../Other/manage-claude-access-transparency.md)
[Encryption keys](../Other/manage-claude-cmek.md)
[Inference hooks](../Other/manage-claude-inference-hooks.md)
Compliance API
[Overview](../Other/manage-claude-compliance-api.md)[Set up the Compliance API](../Other/manage-claude-compliance-api-access.md)[Activity Feed](../Other/manage-claude-compliance-activity-feed.md)[Chats, files, and projects](../Other/manage-claude-compliance-content-data.md)[Session transcripts](../Other/manage-claude-compliance-sessions.md)[Organizations, users, roles, groups, and settings](../Other/manage-claude-compliance-org-data.md)[Design your integration](../Other/manage-claude-compliance-integration-patterns.md)[Errors](../Other/manage-claude-compliance-errors.md)[FAQ](../Other/manage-claude-compliance-faq.md)
[Console](../Other/usage-limits.md)
[Admin](../Other/manage-claude-admin-api.md)Monitoring
# Claude Code Analytics API
Copy page
Programmatically access your organization's Claude Code usage analytics and productivity metrics with the Claude Code Analytics Admin API.
Copy page
**The Admin API is unavailable for individual accounts.** To collaborate with teammates and add members, set up your organization in **Console → Settings → Organization**.
The Claude Code Analytics Admin API provides programmatic access to daily aggregated usage metrics for Claude Code users, enabling organizations to analyze developer productivity and build custom dashboards. This API provides more detail than the basic [Analytics dashboard](../Other/usage-limits.md) without the complexity of the OpenTelemetry integration.
This API enables you to better monitor, analyze, and optimize your Claude Code adoption:
- **Developer productivity analysis:** Track sessions, lines of code added/removed, commits, and pull requests created using Claude Code
- **Tool usage metrics:** Monitor acceptance and rejection rates for different Claude Code tools (Edit, MultiEdit, Write, NotebookEdit)
- **Cost analysis:** View estimated costs and token usage broken down by Claude model
- **Custom reporting:** Export data to build executive dashboards and reports for management teams
- **Usage justification:** Provide metrics to justify and expand Claude Code adoption internally
**Admin API credentials required.** These endpoints are part of the Admin API. You can access them using an [Admin API key](../Other/manage-claude-admin-api-keys.md), an OAuth token with the `org:admin` scope, or a personal or service account key that isn't scoped to a workspace; workspace API keys don't work. See [Authentication](../Other/manage-claude-admin-api.md#authentication) for details.
**Claude Platform on AWS:** The Claude Code Analytics API is not currently available. View Claude Code usage on the **Usage** page in the Claude Console instead.
**Claude Enterprise organizations:** Claude Code activity for claude.ai users is reported by the Claude Enterprise Analytics API, which uses an Analytics API key instead of an Admin API key. See [Analytics APIs](../Other/manage-claude-analytics-api.md) to find which API and key type your organization needs.
## Quick start
Get your organization's Claude Code analytics for a specific day:
cURL
```python
curl "https://api.anthropic.com/v1/organizations/usage_report/claude_code?\
starting_at=2025-09-08&\
limit=20" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
**Set a User-Agent header for integrations**
If you're building an integration, set your User-Agent header to help Anthropic understand usage patterns:
``` block
User-Agent: YourApp/1.0.0 (https://yourapp.com)
```
## Claude Code Analytics API
Track Claude Code usage, productivity metrics, and developer activity across your organization with the `/v1/organizations/usage_report/claude_code` endpoint.
### Key concepts
- **Daily aggregation:** Returns metrics for a single day specified by the `starting_at` parameter
- **User-level data:** Each record represents one user's activity for the specified day
- **Productivity metrics:** Track sessions, lines of code, commits, pull requests, and tool usage
- **Token and cost data:** Monitor usage and estimated costs broken down by Claude model
- **Cursor-based pagination:** Handle large datasets with stable pagination using opaque cursors
- **Data freshness:** Metrics are available with up to 1-hour delay for consistency
For complete parameter details and response schemas, see the [Claude Code Analytics API reference](../Admin/beta-organization-usage-report-retrieve-claude-code.md).
### Basic examples
#### Get analytics for a specific day
cURL
```python
curl "https://api.anthropic.com/v1/organizations/usage_report/claude_code?\
starting_at=2025-09-08" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
#### Get analytics with pagination
cURL
```python
# First request
curl "https://api.anthropic.com/v1/organizations/usage_report/claude_code?\
starting_at=2025-09-08&\
limit=20" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
# Subsequent request using cursor from response
curl "https://api.anthropic.com/v1/organizations/usage_report/claude_code?\
starting_at=2025-09-08&\
page=page_MjAyNS0wNS0xNFQwMDowMDowMFo=" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
### Request parameters
| Parameter | Type | Required | Description |
|---------------|---------|----------|-------------------------------------------------------------------------|
| `starting_at` | string | Yes | UTC date in YYYY-MM-DD format; returns metrics for this single day only |
| `limit` | integer | No | Number of records per page (default: 20, max: 1000) |
| `page` | string | No | Opaque cursor token from previous response's `next_page` field |
### Available metrics
Each response record contains the following metrics for a single user on a single day:
#### Dimensions
- **date:** Date in RFC 3339 format (UTC timestamp)
- **actor:** The user or API key that performed the Claude Code actions (either `user_actor` with `email_address` or `api_actor` with `api_key_name`)
- **organization_id:** Organization UUID
- **customer_type:** Type of customer account (`api` for API customers, `subscription` for Pro/Team customers)
- **terminal_type:** Type of terminal or environment where Claude Code was used (for example, `vscode`, `iTerm.app`, `tmux`)
#### Core metrics
- **num_sessions:** Number of distinct Claude Code sessions initiated by this actor
- **lines_of_code.added:** Total number of lines of code added across all files by Claude Code
- **lines_of_code.removed:** Total number of lines of code removed across all files by Claude Code
- **commits_by_claude_code:** Number of git commits created through Claude Code's commit functionality
- **pull_requests_by_claude_code:** Number of pull requests created through Claude Code's PR functionality
#### Tool action metrics
Breakdown of tool action acceptance and rejection rates by tool type:
- **edit_tool.accepted/rejected:** Number of Edit tool proposals that the user accepted/rejected
- **multi_edit_tool.accepted/rejected:** Number of MultiEdit tool proposals that the user accepted/rejected
- **write_tool.accepted/rejected:** Number of Write tool proposals that the user accepted/rejected
- **notebook_edit_tool.accepted/rejected:** Number of NotebookEdit tool proposals that the user accepted/rejected
#### Model breakdown
For each Claude model used:
- **model:** Claude model identifier (for example, `claude-opus-5`)
- **tokens.input/output:** Input and output token counts for this model
- **tokens.cache_read/cache_creation:** Cache-related token usage for this model
- **estimated_cost.amount:** Estimated cost in cents USD for this model
- **estimated_cost.currency:** Currency code for the cost amount (currently always `USD`)
### Response structure
The API returns data in the following format:
```python
{
"data": [
{
"date": "2025-09-08T00:00:00Z",
"actor": {
"type": "user_actor",
"email_address": "developer@company.com"
},
"organization_id": "dc9f6c26-b22c-4831-8d01-0446bada88f1",
"customer_type": "api",
"terminal_type": "vscode",
"core_metrics": {
"num_sessions": 5,
"lines_of_code": {
"added": 1543,
"removed": 892
},
"commits_by_claude_code": 12,
"pull_requests_by_claude_code": 2
},
"tool_actions": {
"edit_tool": {
"accepted": 45,
"rejected": 5
},
"multi_edit_tool": {
"accepted": 12,
"rejected": 2
},
"write_tool": {
"accepted": 8,
"rejected": 1
},
"notebook_edit_tool": {
"accepted": 3,
"rejected": 0
}
},
"model_breakdown": [
{
"model": "claude-opus-5-5",
"tokens": {
"input": 100000,
"output": 35000,
"cache_read": 10000,
"cache_creation": 5000
},
"estimated_cost": {
"currency": "USD",
"amount": 113
}
}
]
}
],
"has_more": false,
"next_page": null
}
```
## Pagination
The API supports cursor-based pagination for organizations with large numbers of users:
1. Make your initial request with optional `limit` parameter.
2. If `has_more` is `true` in the response, use the `next_page` value in your next request.
3. Continue until `has_more` is `false`.
The cursor encodes the position of the last record and ensures stable pagination even as new data arrives. Each pagination session maintains a consistent data boundary to ensure you don't miss or duplicate records.
## Common use cases
- **Executive dashboards:** Create high-level reports showing Claude Code impact on development velocity
- **AI tool comparison:** Export metrics to compare Claude Code with other AI coding tools such as Copilot and Cursor
- **Developer productivity analysis:** Track individual and team productivity metrics over time
- **Cost tracking and allocation:** Monitor spending patterns and allocate costs by team or project
- **Adoption monitoring:** Identify which teams and users are getting the most value from Claude Code
- **ROI justification:** Provide concrete metrics to justify and expand Claude Code adoption internally
## Frequently asked questions
### How fresh is the analytics data?
Claude Code analytics data typically appears within 1 hour of user activity completion. To ensure consistent pagination results, only data older than 1 hour is included in responses.
### Can I get real-time metrics?
No, this API provides daily aggregated metrics only. For real-time monitoring, consider using the [OpenTelemetry integration](../../13-Enterprise-Admin/monitoring-usage.md).
### How are users identified in the data?
Users are identified through the `actor` field in two ways:
- **`user_actor`:** Contains `email_address` for users who authenticate through OAuth (most common)
- **`api_actor`:** Contains `api_key_name` for users who authenticate with an API key
The `customer_type` field indicates whether the usage is from `api` customers (pay-as-you-go API) or `subscription` customers (Pro/Team plans).
### What's the data retention period?
Historical Claude Code analytics data is retained and accessible through the API. There is no specified deletion period for this data.
### Which Claude Code deployments are supported?
This API only tracks Claude Code usage on the Claude API. Usage through [Claude in Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md), [Claude in Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md), [Claude on Google Cloud](build-with-claude-claude-on-vertex-ai.md), or [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md) is not included.
### What does it cost to use this API?
The Claude Code Analytics API is free to use for all organizations with access to the Admin API.
### How do I calculate tool acceptance rates?
Tool acceptance rate = `accepted / (accepted + rejected)` for each tool type. For example, if the edit tool shows 45 accepted and 5 rejected, the acceptance rate is 90%.
### What time zone is used for the date parameter?
All dates are in UTC. The `starting_at` parameter should be in YYYY-MM-DD format and represents UTC midnight for that day.
## See also
The Claude Code Analytics API helps you understand and optimize your team's development workflow. Learn more about related features:
- [Admin API](../Other/manage-claude-admin-api.md)
- [Admin API reference](../Admin/http-beta-organization.md)
- [Claude Code Analytics dashboard](../Other/usage-limits.md)
- [Usage and Cost API](../Other/manage-claude-usage-cost-api.md) - Track API usage across all Anthropic services
- [Compliance API](../Other/manage-claude-compliance-api.md) - Retrieve audit and activity data
- [Identity and access management](../../13-Enterprise-Admin/iam.md)
- [Monitoring usage with OpenTelemetry](../../13-Enterprise-Admin/monitoring-usage.md) for custom metrics and alerting
---
## Claude in Amazon Bedrock (Opus 4.7 and later) - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock
Path: 04-API-Reference/Guides/build-with-claude-claude-in-amazon-bedrock.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fclaude-in-amazon-bedrock)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Claude on cloud platforms
# Claude in Amazon Bedrock (Opus 4.7 and later)
Copy page
Access Claude models through Amazon Bedrock with AWS-native authentication, billing, and security boundaries.
Copy page
This guide walks you through setting up and making API calls to Claude in Amazon Bedrock. Claude in Amazon Bedrock runs on AWS-managed infrastructure with zero operator access (Anthropic personnel have no access to the inference infrastructure), letting you build sensitive applications entirely inside the AWS security boundary while using the same Messages API shape you use with Anthropic's first-party API.
This page covers Claude in Amazon Bedrock, which serves Claude through the Messages API at `/anthropic/v1/messages` on AWS-managed infrastructure. The previous Amazon Bedrock integration (the `InvokeModel` and `Converse` APIs with ARN-versioned model identifiers) remains available and is documented at [Claude on Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md). For an Anthropic-operated alternative on AWS with AWS Marketplace billing and typically same-day feature access, see [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md).
## Access
Amazon Bedrock sets access criteria for each Claude model individually. Claude Fable 5.1, Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5, Claude Opus 4.7, and Claude Haiku 4.5 are open to all Amazon Bedrock customers. For any other model's current criteria, check [Amazon Bedrock model access](https://console.aws.amazon.com/bedrock/home#/modelaccess) in the AWS console. Claude Mythos Preview requires an invitation through [Project Glasswing](../../22-Safety-Policy/glasswing.md). For region availability, see [Regions](#regions).
## Prerequisites
Before you begin, ensure you have:
- An AWS account with [Amazon Bedrock model access](https://console.aws.amazon.com/bedrock/home#/modelaccess) enabled for the Claude models you intend to use.
- The [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured (optional, for credential management).
Claude Mythos Preview additionally requires a dedicated AWS account that has been allowlisted by the Bedrock Marketplace team. Your Anthropic account executive can submit your account ID for allowlisting (typically processed within 24 hours), and AWS sends a welcome email once it's complete.
## Authentication
Claude in Amazon Bedrock supports three authentication paths. Choose the one that best fits your security requirements.
### Bedrock service role (recommended)
Use a Bedrock service role with AWS-managed keys for the most secure, long-lived access:
1. 1
### Admin: provision the service role
An AWS administrator provisions a Bedrock service role and grants developers `iam:PassRole` permission on the service role ARN.
2. 2
### Developer: pass the role
When calling the API, Bedrock assumes the service role on your behalf. See the [Amazon Bedrock documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-mantle.html) for how to associate the role with your requests.
### IAM assumed roles
For identity-federated access with a 12-hour maximum session:
1. 1
### Admin: configure the IAM role
Create an IAM role scoped to your Claude models. The trust policy names your identity provider (SAML, OIDC, or AWS Identity Center). The permissions policy grants `bedrock-mantle:CreateInference` only on the allowed model ARNs.
2. 2
### Developer: authenticate and assume
Authenticate through your corporate identity provider, then assume the IAM role. AWS STS issues temporary credentials that the SDK or CLI uses to sign requests.
### Bearer tokens
For short-term access without IAM roles (12-hour maximum, least preferred):
1. 1
### Admin: restrict token types
Block long-term keys by attaching a policy that denies `bedrock:CallWithBearerToken` unless the `bedrock:BearerTokenType` condition matches a short-term token.
2. 2
### Developer: mint a token
Use the `aws-bedrock-token-generator` CLI to mint a bearer token. Pass it in the `x-api-key` header on each request.
## Install an SDK
Anthropic's [client SDKs](../Other/cli-sdks-libraries-overview.md) support Claude in Amazon Bedrock through a Bedrock-specific package or module.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
pip install -U "anthropic[bedrock]"
```
## Making your first request
The endpoint follows the pattern `https://bedrock-mantle.{region}.api.aws/anthropic/v1/messages`. Unlike the `InvokeModel`-based integration, this endpoint uses standard SSE streaming and the same request body shape as Anthropic's first-party API.
The SDK resolves credentials and region using the standard AWS precedence: constructor arguments, then environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`, `AWS_REGION`), then the AWS config file and credential chain (SSO, assumed roles, ECS task role, IMDS).
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicBedrockMantle
client = AnthropicBedrockMantle(aws_region="us-east-1")
message = client.messages.create(
model="anthropic.claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(next(block.text for block in message.content if block.type == "text"))
```
You can also use the standard `Anthropic` client: set `base_url` to `https://bedrock-mantle.{region}.api.aws/anthropic` and pass your bearer token as `api_key`. This path supports bearer-token authentication only. SigV4 signing requires `AnthropicBedrockMantle`.
## Supported models
Model IDs in Claude in Amazon Bedrock carry an `anthropic.` provider prefix. Model capabilities and behaviors are documented on the [Models overview](../../20-Models/about-claude-models-overview.md) page.
| Model | Model ID | Access |
|---------------------------------------------------------------------------------------------------|---------------------------------|:----------------------|
| Claude Fable 5.1 | anthropic.claude-fable-5-1 | Open |
| Claude Mythos 5.1 ([limited availability(opens in new tab)](../../22-Safety-Policy/glasswing.md)) | anthropic.claude-mythos-5-1 | Invitation only |
| Claude Fable 5 | anthropic.claude-fable-5 | Open |
| Claude Mythos 5 ([limited availability(opens in new tab)](../../22-Safety-Policy/glasswing.md)) | anthropic.claude-mythos-5 | Invitation only |
| Claude Mythos Preview ([limited availability(opens in new tab)](../../22-Safety-Policy/glasswing.md)) | anthropic.claude-mythos-preview | Invitation only |
| Claude Opus 5.5 | anthropic.claude-opus-5-5 | [See Access](#access) |
| Claude Opus 5 | anthropic.claude-opus-5 | [See Access](#access) |
| Claude Opus 4.8 | anthropic.claude-opus-4-8 | Open |
| Claude Opus 4.7 | anthropic.claude-opus-4-7 | Open |
| Claude Sonnet 5 | anthropic.claude-sonnet-5 | Open |
| Claude Haiku 4.5 | anthropic.claude-haiku-4-5 | Open |
Use Claude Code 2.1.255 or later with Claude Fable 5.1 on Amazon Bedrock, and 2.1.280 or later with Claude Opus 5.5; run `claude update` to upgrade.
Upgrading to a newer Claude model? In Claude Code, run `/claude-api migrate` to apply model ID swaps and breaking parameter changes across your codebase. The skill detects which cloud platform your code targets and adjusts model ID formats and feature changes for that platform. See [Migrating to a newer Claude model](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md#migrating-to-a-newer-claude-model).
## Feature support
For the full feature list with Amazon Bedrock availability, see [Features overview](build-with-claude-overview.md).
### Supported feature highlights
- [Messages API](../Endpoints/messages-create.md) (`/anthropic/v1/messages`)
- [Prompt caching](build-with-claude-prompt-caching.md)
- [Thinking](build-with-claude-thinking.md)
- [Tool use](../Agents-Tools/agents-and-tools-tool-use-overview.md), including the [Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md), [Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md), [Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md), and [Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)
- [Citations](build-with-claude-citations.md)
### Features not supported
- [Structured outputs](build-with-claude-structured-outputs.md)
- Input sources (URL sources for images and documents, Files API)
- Server-side tools (code execution, web search, web fetch, advisor)
- Agent infrastructure (Agent Skills, MCP connector, programmatic tool calling)
- API endpoints (Message Batches, Models, Admin, Compliance, Usage and Cost)
- Claude Managed Agents
- Server-side fallback (the [`fallbacks` parameter](build-with-claude-refusals-and-fallback.md#server-side-fallback); use the [client-side fallback pattern](build-with-claude-refusals-and-fallback.md#client-side-fallback) instead)
- [Computer use](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md) and [browser use](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md) toolsets (`computer_toolset_20260801` and `browser_toolset_20260801` are not currently available on Amazon Bedrock; the beta computer use tool versions remain available)
## Regions
Claude in Amazon Bedrock is available in the following AWS regions. Amazon Bedrock offers two endpoint types:
- **Global:** dynamic routing across all available regions for maximum availability. No pricing premium.
- **Regional:** the endpoint resolves to the single AWS region you specify, for data-residency requirements. Regional endpoints carry a 10% pricing premium over global endpoints. To route across multiple regions within a geography, use an [inference profile](https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html) (US, EU, JP, or AU). Regions marked **In-region only** in the table support direct single-region routing without an inference profile.
The global endpoint is available for Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, Claude Sonnet 5, and Claude Haiku 4.5. For Claude Fable 5.1, regional endpoints are currently available in `us-east-1` only. Claude Mythos Preview is regional only and is available in `us-east-1`.
| AWS region | Location | Endpoint types |
|------------------|---------------------------|----------------------------|
| `af-south-1` | Africa (Cape Town) | Global |
| `ap-northeast-1` | Asia Pacific (Tokyo) | Global, JP, In-region only |
| `ap-northeast-2` | Asia Pacific (Seoul) | Global |
| `ap-northeast-3` | Asia Pacific (Osaka) | Global, JP |
| `ap-south-1` | Asia Pacific (Mumbai) | Global |
| `ap-south-2` | Asia Pacific (Hyderabad) | Global |
| `ap-southeast-1` | Asia Pacific (Singapore) | Global |
| `ap-southeast-2` | Asia Pacific (Sydney) | Global, AU |
| `ap-southeast-3` | Asia Pacific (Jakarta) | Global |
| `ap-southeast-4` | Asia Pacific (Melbourne) | Global, AU, In-region only |
| `ca-central-1` | Canada (Central) | Global, US |
| `ca-west-1` | Canada West (Calgary) | Global |
| `eu-central-1` | Europe (Frankfurt) | Global, EU |
| `eu-central-2` | Europe (Zurich) | Global, EU |
| `eu-north-1` | Europe (Stockholm) | Global, EU, In-region only |
| `eu-south-1` | Europe (Milan) | Global, EU |
| `eu-south-2` | Europe (Spain) | Global, EU |
| `eu-west-1` | Europe (Ireland) | Global, EU, In-region only |
| `eu-west-2` | Europe (London) | Global, EU |
| `eu-west-3` | Europe (Paris) | Global, EU |
| `il-central-1` | Israel (Tel Aviv) | Global |
| `me-central-1` | Middle East (UAE) | Global |
| `sa-east-1` | South America (São Paulo) | Global |
| `us-east-1` | US East (N. Virginia) | Global, US, In-region only |
| `us-east-2` | US East (Ohio) | Global, US, In-region only |
| `us-west-1` | US West (N. California) | Global, US |
| `us-west-2` | US West (Oregon) | Global, US, In-region only |
## Quotas
Default quota is 2 million input tokens per minute (TPM). You can request up to 5 million input TPM and 500,000 output TPM without additional Anthropic approval. AWS enforces requests-per-minute (RPM) limits on the Bedrock side; contact AWS support for RPM adjustments.
## Data retention
Data handling for this offering is governed by Amazon Bedrock. For details, see [Data protection in Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/data-protection.html).
## Monitoring and logging
Claude in Amazon Bedrock emits logs to both CloudWatch and CloudTrail. Anthropic recommends retaining activity logs on at least a 30-day rolling basis to understand usage patterns and investigate potential issues.
## Support
For support, contact **<bedrock-ant-eap@amazon.com>**. Include your AWS account ID and the `request-id` from any failed API responses.
**Claude Mythos Preview** is a research preview model available to invited customers on Amazon Bedrock. For more information, see [Project Glasswing](../../22-Safety-Policy/glasswing.md).
---
## Claude in Microsoft Foundry - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry
Path: 04-API-Reference/Guides/build-with-claude-claude-in-microsoft-foundry.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fclaude-in-microsoft-foundry)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Claude on cloud platforms
# Claude in Microsoft Foundry
Copy page
Access Claude models through Microsoft Foundry with Azure-native endpoints and authentication.
Copy page
This guide shows you how to set up and make API calls to Claude in Microsoft Foundry using one of Anthropic's client SDKs or direct HTTP requests. When you access Claude in Microsoft Foundry, you are billed for Claude usage in the Azure Marketplace. You can use Claude models including Claude Fable 5.1, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, and Claude Sonnet 5, and features such as the [1M-token context window](build-with-claude-context-windows.md), while managing costs through your Azure subscription.
Claude is available in Global Standard and US Data Zone Standard deployment types in Foundry resources, billed in Claude Consumption Units through the Azure Marketplace. Visit [Claude in Microsoft Foundry pricing](../../17-Billing-Plans/about-claude-pricing.md#claude-in-microsoft-foundry-pricing) for details.
## Hosting options
Claude models in Microsoft Foundry are available in two hosting options. You choose the hosting option when you configure the deployment.
| | Hosted on Azure | Hosted on Anthropic |
|:---------------------|:-----------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------|
| Where inference runs | Anthropic-operated service running on Azure infrastructure | Anthropic-operated service running on Anthropic infrastructure |
| Model availability | The latest models in the Opus, Sonnet, and Haiku families | All Claude models available on Microsoft Foundry |
| Deployment types | Global Standard, US Data Zone Standard | Global Standard |
| Recommended for | Most workloads | [Access to features or models not yet hosted on Azure](#additional-features-not-supported-when-hosted-on-azure) |
Anthropic acts as an independent processor for Microsoft. Customers using Claude through Microsoft Foundry are subject to Anthropic's data use terms. For deployments hosted on Azure, prompts and completions remain within Azure. Only usage metadata and content flagged by Anthropic's safety systems egress to Anthropic. Anthropic continues to provide its safety and data commitments.
## Prerequisites
Before you begin, ensure you have:
- An active Azure subscription
- Access to the [Foundry portal](https://ai.azure.com/)
- The [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) installed (required for the Entra ID cURL example, optional otherwise)
- An Azure RBAC role that allows you to use the resource, such as **Foundry User** (formerly Azure AI User) or **Cognitive Services User**
## Install an SDK
Anthropic's [client SDKs](../Other/cli-sdks-libraries-overview.md) support Foundry through a platform-specific package or client class. The examples on this page also show requests with cURL and the ant CLI. To set up the CLI, see [CLI quickstart](../Other/cli-sdks-libraries-cli-quickstart.md).
Foundry is supported by the C#, Java, PHP, Python, and TypeScript SDKs. Foundry is not currently available in the Go and Ruby SDKs.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
pip install -U "anthropic"
# For Entra ID authentication, also install the Azure Identity library
pip install azure-identity
```
## Provisioning
Foundry uses a two-level hierarchy: **resources** contain your security and billing configuration, while **deployments** are the model instances you call through the API. You'll first create a Foundry resource, then create one or more Claude deployments within it.
### Provisioning Foundry resources
Create a Foundry resource, which is required to use and manage services in Azure. You can follow these instructions to create a [Foundry resource](https://learn.microsoft.com/en-us/azure/ai-services/multi-service-resource?pivots=azportal#create-a-new-azure-ai-foundry-resource). Alternatively, you can start by creating a [Foundry project](https://learn.microsoft.com/en-us/azure/foundry/how-to/create-projects), which involves creating a Foundry resource.
To provision your resource:
1. Navigate to the [Foundry portal](https://ai.azure.com/).
2. Create a new Foundry resource or select an existing one.
3. Configure access management using Azure-issued API keys or Entra ID (formerly Azure Active Directory) for role-based access control.
4. Optionally configure the resource to be part of a private network (Azure Virtual Network) to restrict network access to your resource.
5. Note your resource name. You'll use this as `{resource}` in API endpoints (for example, `https://{resource}.services.ai.azure.com/anthropic/v1/*`).
### Creating Foundry deployments
After creating your resource, deploy a Claude model to make it available for API calls. These steps describe the new Foundry portal (the **New Foundry** toggle is on):
1. Sign in to the Foundry portal. From the portal homepage, select **Discover** in the upper-right navigation, then **Models** in the left pane to open the model catalog.
2. Search for and select a Claude model (for example,
claude-opus-5
). Each model appears once in the catalog regardless of how many hosting options it supports.
3. On the model card, select **Deploy**, then **Custom settings** to open the deployment settings pane. If you choose **Default settings** instead, the deployment is automatically configured as Hosted on Azure for models available in both hosting options.
4. On your first Claude deployment, review the Azure Marketplace terms, select an industry, and select **Agree and Proceed** to accept the terms and subscribe to the Azure Marketplace offer.
5. Configure the deployment:
- **Deployment name:** Defaults to the model ID, but you can customize it (for example, `my-claude-deployment`). The deployment name cannot be changed after creation.
- **Region scope:** Select Global, or for models hosted on Azure, Data Zone. Selecting Data Zone creates a US Data Zone Standard deployment, which keeps inference within the United States and is equivalent to setting [`inference_geo: "us"`](build-with-claude-data-residency.md#inference-geo) on the Claude API.
- **Model version:** Expand **Model version settings** and select a version from the **Model version** dropdown menu. Each [hosting option](#hosting-options) is listed as a separate model version, labeled with its hosting option (for example, version 1 for Hosted on Anthropic, version 2 for Hosted on Azure).
6. Select **Deploy** and wait for provisioning to complete.
7. Once deployed, select **Build** in the upper-right navigation, then **Models** in the left pane, and open your deployment. The **Details** tab shows the **Target URI** (your endpoint URL) and **Key** (your API key).
If the **New Foundry** toggle is off, you are in the classic portal layout. There, open **Model catalog** in the left pane to find and deploy a model, and open **Models + endpoints** (under **My assets**) to view your deployments and their endpoint details.
The deployment name you choose becomes the value you pass in the `model` parameter of your API requests. You can create multiple deployments of the same model with different names to manage separate configurations or rate limits.
## Authentication
Claude in Microsoft Foundry supports two authentication methods: API keys and Entra ID tokens. Both methods use Azure-hosted endpoints in the format `https://{resource}.services.ai.azure.com/anthropic/v1/*`.
### API key authentication
After provisioning your Foundry Claude resource, you can obtain an API key from the Foundry portal:
1. In the Foundry portal, select **Build** in the upper-right navigation, then **Models** in the left pane.
2. Open your Claude deployment and select the **Details** tab.
3. Copy the **Key** value (and note the **Target URI** for your endpoint).
4. Use either the `api-key` or `x-api-key` header in your requests, or provide it to the SDK.
The Foundry SDKs require an API key and either a resource name or base URL. The C#, Java, PHP, Python, and TypeScript SDKs automatically read these from the following environment variables if they are defined:
- `ANTHROPIC_FOUNDRY_API_KEY` - Your API key
- `ANTHROPIC_FOUNDRY_RESOURCE` - Your resource name (for example, `example-resource`)
- `ANTHROPIC_FOUNDRY_BASE_URL` - Alternative to resource name: the full base URL (for example, `https://example-resource.services.ai.azure.com/anthropic/`). The C# SDK does not read this variable: it always constructs the base URL from the resource name.
The `resource` and `base_url` parameters are mutually exclusive. Provide either the resource name (which the SDK uses to construct the URL as `https://{resource}.services.ai.azure.com/anthropic/`) or the full base URL directly.
**Example using API key:**
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import os
from anthropic import AnthropicFoundry
client = AnthropicFoundry(
api_key=os.environ.get("ANTHROPIC_FOUNDRY_API_KEY"),
resource="example-resource", # your resource name
)
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
print(message.content)
```
Keep your API keys secure. Never commit them to version control or share them publicly. Anyone with access to your API key can make requests to Claude through your Foundry resource.
### Microsoft Entra authentication
Entra ID authentication lets you manage access with Azure RBAC, integrate with your organization's identity management, and avoid handling API keys manually. To use Entra ID tokens:
1. Enable [Microsoft Entra ID authentication](https://learn.microsoft.com/en-us/azure/ai-foundry/model-inference/how-to/configure-entra-id) for your Foundry resource.
2. Obtain an access token from Entra ID.
3. Use the token in the `Authorization: Bearer {TOKEN}` header.
**Example using Entra ID:**
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicFoundry
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
# Get Microsoft Entra ID token using token provider pattern
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://ai.azure.com/.default"
)
# Create client with Entra ID authentication
client = AnthropicFoundry(
resource="example-resource", # your resource name
azure_ad_token_provider=token_provider, # Use token provider for Entra ID auth
)
# Make request
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
print(message.content)
```
## Correlation request IDs
Foundry includes request identifiers in HTTP response headers for debugging and tracing. When contacting support, provide both the `request-id` and `apim-request-id` (Azure API Management) values to help teams quickly locate and investigate your request across both Anthropic and Azure systems.
## Feature support
Claude in Microsoft Foundry supports most Claude features. You can find all the features currently supported in [Features overview](build-with-claude-overview.md).
### Context window
Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 5, and Claude Sonnet 4.6 have a [1M-token context window](build-with-claude-context-windows.md) on Microsoft Foundry. Other Claude models, including Claude Sonnet 4.5, have a 200k-token context window.
### Claude features not supported for Claude in Microsoft Foundry
- Admin API
- Advisor tool
- Claude Managed Agents
- Compliance API
- Models API
- Message Batches API
- Server-side fallback (the [`fallbacks` parameter](build-with-claude-refusals-and-fallback.md#server-side-fallback); use the [client-side fallback pattern](build-with-claude-refusals-and-fallback.md#client-side-fallback) instead)
- [Computer use](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md) and [browser use](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md) toolsets (`computer_toolset_20260801` and `browser_toolset_20260801` are not currently available on Microsoft Foundry; the beta computer use tool versions remain available)
### Additional features not supported when hosted on Azure
The following features are available for deployments hosted on Anthropic but are not supported for deployments hosted on Azure:
- [Code execution](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)
- [Web search](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md) and [web fetch](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md) tool versions later than `web_search_20250305` and `web_fetch_20250910`. Deployments hosted on Azure support only these basic versions, so dynamic filtering, response inclusion, and cache bypass are not available.
- [Agent Skills](../Agents-Tools/agents-and-tools-agent-skills-overview.md)
- [Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)
- [Files API](build-with-claude-files.md)
Requests that use these features against a deployment hosted on Azure return a `400 Bad Request` error by design. Claude Code detects deployments hosted on Azure and automatically adapts its feature set.
## API responses
API responses from Claude in Microsoft Foundry follow the standard [Claude API response format](../Endpoints/messages-create.md). This includes the `usage` object in response bodies, which provides detailed token consumption information for your requests. The `usage` object is consistent across all platforms (Claude API, Amazon Bedrock, Claude Platform on AWS, Foundry, and Google Cloud).
For details on response headers specific to Foundry, see [Correlation request IDs](#correlation-request-ids).
## API model IDs and deployments
Lifecycle terms (Deprecated, Retired) are defined in [Model deprecations](../../20-Models/about-claude-model-deprecations.md). Microsoft Foundry follows the Claude API lifecycle schedule.
The following Claude models are available through Foundry:
| Model | Default deployment name | Hosted on Azure | Hosted on Anthropic |
|-----------------------------------------------------------------------------------------------|-------------------------|:---------------:|:-------------------:|
| Claude Fable 5.1 | claude-fable-5-1 | | ✓ |
| Claude Mythos 5.1 ([limited availability(opens in new tab)](../../22-Safety-Policy/glasswing.md)) | claude-mythos-5-1 | | ✓ |
| Claude Fable 5 | claude-fable-5 | | ✓ |
| Claude Mythos 5 ([limited availability(opens in new tab)](../../22-Safety-Policy/glasswing.md)) | claude-mythos-5 | | ✓ |
| Claude Opus 5.5 | claude-opus-5-5 | ✓ | ✓ |
| Claude Opus 5 | claude-opus-5 | ✓ | ✓ |
| Claude Opus 4.8 | claude-opus-4-8 | ✓ | ✓ |
| Claude Opus 4.7 | claude-opus-4-7 | | ✓ |
| Claude Opus 4.6 | claude-opus-4-6 | | ✓ |
| Claude Opus 4.5 | claude-opus-4-5 | | ✓ |
| Claude Sonnet 5 | claude-sonnet-5 | ✓ | ✓ |
| Claude Sonnet 4.6 | claude-sonnet-4-6 | | ✓ |
| Claude Sonnet 4.5 | claude-sonnet-4-5 | | ✓ |
| Claude Haiku 4.5 | claude-haiku-4-5 | ✓ | ✓ |
By default, deployment names match the model IDs shown in the preceding table. However, you can create custom deployments with different names in the Foundry portal to manage different configurations, versions, or rate limits. Use the deployment name (not necessarily the model ID) in your API requests.
[Claude Mythos Preview](../../22-Safety-Policy/glasswing.md) is a research preview available to invited customers on Microsoft Foundry.
Upgrading to a newer Claude model? In Claude Code, run `/claude-api migrate` to apply model ID swaps and breaking parameter changes across your codebase. The skill detects which cloud platform your code targets and adjusts model ID formats and feature changes for that platform. See [Migrating to a newer Claude model](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md#migrating-to-a-newer-claude-model).
## Billing
Claude in Microsoft Foundry bills through the [Azure Marketplace](https://azuremarketplace.microsoft.com/). Usage is denominated in Claude Consumption Units (CCUs), metered hourly, and invoiced monthly in arrears on your Azure bill. CCUs are not prepaid credits. There is no CCU balance or commitment.
For the CCU price, conversion mechanics, and per-model token rates, see [Claude in Microsoft Foundry pricing](../../17-Billing-Plans/about-claude-pricing.md#claude-in-microsoft-foundry-pricing).
## Migrating between hosting options
To move an existing deployment from one hosting option to the other:
1. Create a new deployment of the model's other hosting version (Hosted on Azure or Hosted on Anthropic). This can be in the same Foundry resource, or a new one.
2. Update your application to pass the new deployment name in the `model` parameter.
3. Delete the old deployment once traffic has moved.
If the new deployment is in the same Foundry resource, your endpoint URL and authentication are unchanged. If you created a new resource, update your application's endpoint and credentials to point to it.
## Monitoring and logging
Azure provides monitoring and logging for your Claude usage through standard Azure patterns:
- **Azure Monitor:** Track API usage, latency, and error rates
- **Azure Log Analytics:** Query and analyze request/response logs
- **Cost Management:** Monitor and forecast costs associated with Claude usage
Anthropic recommends logging your activity on at least a 30-day rolling basis to understand usage patterns and investigate any potential issues.
Azure's logging services are configured within your Azure subscription. Enabling logging does not provide Microsoft or Anthropic access to your content beyond what's necessary for billing and service operation.
## Troubleshooting
### Authentication errors
**Error:** `401 Unauthorized` or `Invalid API key`
- **Solution:** Verify your API key is correct. You can find it in the Foundry portal on your deployment's **Details** tab (under **Build** \> **Models**).
- **Solution:** If using Microsoft Entra ID, ensure your access token is valid and hasn't expired. Tokens typically expire after 1 hour.
**Error:** `403 Forbidden`
- **Solution:** Your Azure account may lack the necessary permissions. Ensure you have the appropriate Azure RBAC role assigned (for example, **Foundry User** (formerly Azure AI User) or **Cognitive Services User**).
### Rate limiting
**Error:** `429 Too Many Requests`
- **Solution:** You've exceeded your rate limit. Implement exponential backoff and retry logic in your application.
- **Solution:** Consider requesting rate limit increases through the Azure portal or Azure support.
#### Rate limit headers
Foundry does not include Anthropic's standard rate limit headers (`anthropic-ratelimit-tokens-limit`, `anthropic-ratelimit-tokens-remaining`, `anthropic-ratelimit-tokens-reset`, `anthropic-ratelimit-input-tokens-limit`, `anthropic-ratelimit-input-tokens-remaining`, `anthropic-ratelimit-input-tokens-reset`, `anthropic-ratelimit-output-tokens-limit`, `anthropic-ratelimit-output-tokens-remaining`, and `anthropic-ratelimit-output-tokens-reset`) in responses. Manage rate limiting through Azure's monitoring tools instead.
### Model and deployment errors
**Error:** `Model not found` or `Deployment not found`
- **Solution:** Verify you're using the correct deployment name. If you haven't created a custom deployment, use the default model ID (for example,
claude-opus-5
).
- **Solution:** Ensure the model/deployment is available in your Azure region.
**Error:** `Invalid model parameter`
- **Solution:** The model parameter should contain your deployment name, which can be customized in the Foundry portal. Verify the deployment exists and is properly configured.
## Next steps
[Features overview](build-with-claude-overview.md)
Explore Claude's advanced features and capabilities.
[Pricing](../../17-Billing-Plans/about-claude-pricing.md#claude-in-microsoft-foundry-pricing)
Learn about Anthropic's pricing structure for models and features.
[Model deprecations](../../20-Models/about-claude-model-deprecations.md)
As safer and more capable models launch, Anthropic regularly retires older ones. See all API deprecations, along with recommended replacements.
## Additional resources
[Foundry model catalog](https://ai.azure.com/catalog/publishers/anthropic)
Browse Anthropic models in the Foundry catalog.
[Azure AI Foundry pricing](https://azure.microsoft.com/en-us/pricing/details/ai-foundry/#pricing)
View Microsoft's pricing details for Azure AI Foundry.
[Model pricing](../../17-Billing-Plans/about-claude-pricing.md#model-pricing)
View Anthropic's per-model pricing details.
[Azure portal](https://portal.azure.com/)
Manage your Azure resources.
---
## Claude on Amazon Bedrock (Opus 4.6 and earlier) - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy
Path: 04-API-Reference/Guides/build-with-claude-claude-on-amazon-bedrock-legacy.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fclaude-on-amazon-bedrock-legacy)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Claude on cloud platforms
# Claude on Amazon Bedrock (Opus 4.6 and earlier)
Copy page
The legacy Amazon Bedrock integration for Claude models, using InvokeModel and Converse APIs with ARN-versioned model identifiers.
Copy page
This page covers the legacy Amazon Bedrock integration: the `InvokeModel` and `Converse` APIs with ARN-versioned model identifiers and AWS event-stream encoding. For models available on the Messages-API Bedrock endpoint, see [Claude in Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md), which uses the Messages API at `/anthropic/v1/messages` with SSE streaming. For an Anthropic-operated alternative with AWS Marketplace billing and typically same-day feature access, see [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md). Existing Bedrock users can follow the [migration guide](build-with-claude-claude-platform-on-aws.md#migrating-from-amazon-bedrock).
Calling Claude through Bedrock slightly differs from how you would call Claude on the Claude API directly. This guide walks you through completing an API call to Claude on Bedrock using one of Anthropic's [client SDKs](../Other/cli-sdks-libraries-overview.md).
Note that this guide assumes you have already signed up for an [AWS account](https://portal.aws.amazon.com/billing/signup) and configured programmatic access.
## Install and configure the AWS CLI
1. [Install a version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) at or newer than version `2.13.23`.
2. Configure your AWS credentials using the AWS configure command (see [Configure the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)) or find your credentials by navigating to "Command line or programmatic access" within your AWS dashboard and following the directions in the modal window.
3. Verify that your credentials are working:
AWS CLI
```python
aws sts get-caller-identity
```
## Install an SDK for accessing Bedrock
Anthropic's [client SDKs](../Other/cli-sdks-libraries-overview.md) support Bedrock. You can also use an AWS SDK like `boto3` directly.
Python
TypeScript
C#
Go
Java
PHP
Ruby
Boto3 (Python)
```python
pip install -U "anthropic[bedrock]"
```
## Accessing Bedrock
### Subscribe to Anthropic models
Go to the [AWS Console \> Bedrock \> Model Access](https://console.aws.amazon.com/bedrock/home?region=us-west-2#/modelaccess) and request access to Anthropic models. Note that Anthropic model availability varies by region. See [AWS documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html) for latest information.
#### API model IDs
Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5, Claude Opus 4.8, and Claude Opus 4.7 are reachable through `InvokeModel` on `bedrock-runtime`. These requests are served by the same infrastructure as the [Claude in Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md) endpoint. For the native Messages API request shape and full feature parity, use that page. These models are omitted from the model table on this page because they do not have ARN-versioned model IDs.
Lifecycle terms (Deprecated, Retired) are defined in [Model deprecations](../../20-Models/about-claude-model-deprecations.md). Lifecycle dates on partner-operated platforms are set by the partner and can differ from the Claude API schedule. For the current retirement date of any model on Amazon Bedrock, see [Amazon Bedrock's model lifecycle page](https://docs.aws.amazon.com/bedrock/latest/userguide/model-lifecycle.html).
AWS offers newer Claude models through [cross-region inference](https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html) rather than on-demand throughput. For these models, a request that passes the base model ID fails with an HTTP 400 error like the following:
```python
Invocation of model ID anthropic.claude-sonnet-4-5-20250929-v1:0 with on-demand throughput isn't supported. Retry your request with the ID or ARN of an inference profile that contains this model.
```
To invoke these models, pass an inference profile instead of the base model ID. The inference profile ID is the base model ID with a prefix from a column marked "Yes" in the following table, for example us.anthropic.claude-sonnet-4-5-20250929-v1:0. You can also pass the full inference profile ARN, in the form `arn:aws:bedrock:{region}:{account-id}:inference-profile/{inference-profile-id}`. For AWS's authoritative list of available inference profiles, see [Supported Regions and models for inference profiles](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html). To learn how the prefixes affect routing and pricing, see the [Global versus regional endpoints](#global-vs-regional-endpoints) section.
| Model | Base Bedrock model ID | `global` | `us` | `eu` | `jp` | `apac` |
|---------------------------------------------------------------------------|-------------------------------------------|:---------|:-----|:-----|:-----|:-------|
| Claude Opus 4.6 | anthropic.claude-opus-4-6-v1 | Yes | Yes | Yes | Yes | Yes |
| Claude Opus 4.5 | anthropic.claude-opus-4-5-20251101-v1:0 | Yes | Yes | Yes | No | No |
| Claude Opus 4.1 ([deprecated](../../20-Models/about-claude-model-deprecations.md)) | anthropic.claude-opus-4-1-20250805-v1:0 | No | Yes | No | No | No |
| Claude Sonnet 4.6 | anthropic.claude-sonnet-4-6 | Yes | Yes | Yes | Yes | No |
| Claude Sonnet 4.5 | anthropic.claude-sonnet-4-5-20250929-v1:0 | Yes | Yes | Yes | Yes | No |
| Claude Sonnet 4 ([deprecated](../../20-Models/about-claude-model-deprecations.md)) | anthropic.claude-sonnet-4-20250514-v1:0 | Yes | Yes | Yes | No | Yes |
| Claude Haiku 4.5 | anthropic.claude-haiku-4-5-20251001-v1:0 | Yes | Yes | Yes | No | No |
| Claude Haiku 3.5 ([deprecated](../../20-Models/about-claude-model-deprecations.md)) | anthropic.claude-3-5-haiku-20241022-v1:0 | No | Yes | No | No | No |
### List available models
The following examples show how to print a list of all the Claude models available through Bedrock:
AWS CLI
Boto3 (Python)
TypeScript
C#
Go
Java
PHP
Ruby
```python
import boto3
bedrock = boto3.client(service_name="bedrock")
response = bedrock.list_foundation_models(byProvider="anthropic")
for summary in response["modelSummaries"]:
print(summary["modelId"])
```
### Making requests
The following examples show how to generate text from Claude on Bedrock:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
Boto3 (Python)
```python
from anthropic import AnthropicBedrock
client = AnthropicBedrock(
# Authenticate by either providing the keys below or use the default AWS credential providers, such as
# using ~/.aws/credentials or the "AWS_SECRET_ACCESS_KEY" and "AWS_ACCESS_KEY_ID" environment variables.
aws_access_key="<access key>",
aws_secret_key="<secret key>",
# Temporary credentials can be used with aws_session_token.
# Read more at https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html.
aws_session_token="<session_token>",
# aws_region changes the aws region to which the request is made. If it is not provided, the SDK reads
# AWS_REGION / AWS_DEFAULT_REGION, then the region configured for your boto3 session or AWS profile
# (including ~/.aws/config), and raises ValueError if no region can be resolved.
aws_region="us-west-2",
)
message = client.messages.create(
model="global.anthropic.claude-opus-4-6-v1",
max_tokens=256,
messages=[{"role": "user", "content": "Hello, world"}],
)
print(message.content)
```
See the [client SDKs](../Other/cli-sdks-libraries-overview.md) for more details, and the [official Bedrock documentation](https://docs.aws.amazon.com/bedrock/).
### Bearer token authentication
You can authenticate with Bedrock using bearer tokens instead of AWS credentials. This is useful in corporate environments where teams need access to Bedrock without managing AWS credentials, IAM roles, or account-level permissions.
The simplest approach is to set the `AWS_BEARER_TOKEN_BEDROCK` environment variable, which each SDK detects automatically when resolving credentials from the environment.
To provide a token programmatically:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicBedrock
client = AnthropicBedrock(
api_key="your-bearer-token",
aws_region="us-west-2",
)
message = client.messages.create(
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
print(message.content)
```
## Activity logging
Bedrock provides an [invocation logging service](https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html) that allows you to log the prompts and completions associated with your usage.
Anthropic recommends that you log your activity on at least a 30-day rolling basis to understand your activity and investigate any potential misuse.
Turning on this service does not give AWS or Anthropic any access to your content.
## Feature support
For the full feature list with Amazon Bedrock availability, see [Features overview](build-with-claude-overview.md).
### Supported feature highlights
- [Messages API](../Endpoints/messages-create.md)
- [Prompt caching](build-with-claude-prompt-caching.md)
- [Thinking](build-with-claude-thinking.md)
- [Tool use](../Agents-Tools/agents-and-tools-tool-use-overview.md), including the [Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md), [Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md), [Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md), and [Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)
- [Citations](build-with-claude-citations.md)
- [Structured outputs](build-with-claude-structured-outputs.md)
### Features not supported
- Input sources (URL sources for images and documents, Files API)
- Server-side tools (code execution, web search, web fetch, advisor)
- Agent infrastructure (Agent Skills, MCP connector, programmatic tool calling)
- API endpoints (Message Batches, Models, Admin, Compliance, Usage and Cost)
- Claude Managed Agents
- Server-side fallback (the [`fallbacks` parameter](build-with-claude-refusals-and-fallback.md#server-side-fallback); use the [client-side fallback pattern](build-with-claude-refusals-and-fallback.md#client-side-fallback) instead)
- Automatic prompt caching (the [top-level `cache_control` field](build-with-claude-prompt-caching.md#automatic-caching); use [explicit cache breakpoints](build-with-claude-prompt-caching.md#explicit-cache-breakpoints) instead)
- [Computer use](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md) and [browser use](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md) toolsets (`computer_toolset_20260801` and `browser_toolset_20260801` are not currently available on Amazon Bedrock; the beta computer use tool versions remain available)
### PDF support on Bedrock
PDF support is available on Bedrock through both the Converse API and InvokeModel API. For detailed information about PDF processing capabilities and limitations, see [Amazon Bedrock PDF support](build-with-claude-pdf-support.md#amazon-bedrock-pdf-support).
**Important considerations for Converse API users:**
- Visual PDF analysis (charts, images, layouts) requires citations to be enabled
- Without citations, only basic text extraction is available
- For full control without forced citations, use the InvokeModel API
### Mid-conversation system messages on Bedrock
[Mid-conversation system messages](build-with-claude-mid-conversation-system-messages.md) are available through the InvokeModel API for Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, and Claude Opus 4.8. As described in the note under [API model IDs](#api-model-ids), these requests are served by the same infrastructure as the [Claude in Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md) endpoint. No beta header is required. This feature is not available on Claude Sonnet 5. Use the top-level `system` field instead. It is not available for the ARN-versioned models in the model table on this page.
**For Converse API users:** the Converse API accepts system instructions through its top-level [`system` parameter](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html). To add system instructions mid-conversation, use the InvokeModel API.
### Context window
Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 5, and Claude Sonnet 4.6 have a [1M-token context window](build-with-claude-context-windows.md) on Amazon Bedrock. Other Claude models, including Sonnet 4.5 and Sonnet 4 (deprecated), have a 200k-token context window.
Bedrock limits request payloads to 20 MB. When sending large documents or many images, you may reach this limit before the token limit.
## Global versus regional endpoints
Starting with **Claude Sonnet 4.5 and all future models**, Bedrock offers two endpoint types:
- **Global endpoints:** Dynamic routing for maximum availability
- **Regional endpoints:** Guaranteed data routing through specific geographic regions
Regional endpoints include a 10% pricing premium over global endpoints.
This applies to Claude Sonnet 4.5 and future models only. Older models (Claude Sonnet 4 (deprecated) and earlier) maintain their existing pricing structures.
### When to use each option
**Global endpoints (recommended):**
- Provide maximum availability and uptime
- Dynamically route requests to regions with available capacity
- No pricing premium
- Best for applications where data residency is flexible
**Regional endpoints (CRIS):**
- Route traffic through specific geographic regions
- Required for data residency and compliance requirements
- Available for US, EU, Japan, and Asia-Pacific
- 10% pricing premium reflects infrastructure costs for dedicated regional capacity
### Implementation
**Using global endpoints (default for Opus 4.6, Sonnet 4.6, and Sonnet 4.5):**
The model IDs for Claude Opus 4.6, Sonnet 4.6, and Sonnet 4.5 already include the `global.` prefix:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicBedrock
client = AnthropicBedrock(aws_region="us-west-2")
message = client.messages.create(
model="global.anthropic.claude-opus-4-6-v1",
max_tokens=256,
messages=[{"role": "user", "content": "Hello, world"}],
)
```
**Using regional endpoints (CRIS):**
To use regional endpoints, replace the `global.` prefix with a regional prefix such as `us.`:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicBedrock
client = AnthropicBedrock(aws_region="us-west-2")
# Using US regional endpoint (CRIS)
message = client.messages.create(
model="us.anthropic.claude-opus-4-6-v1", # Regional prefix
max_tokens=256,
messages=[{"role": "user", "content": "Hello, world"}],
)
```
**Claude Mythos Preview** is a research preview model available to invited customers on Amazon Bedrock. For more information, see [Project Glasswing](../../22-Safety-Policy/glasswing.md).
## Additional resources
- **Bedrock pricing:** [Amazon Bedrock pricing page](https://aws.amazon.com/bedrock/pricing/)
- **AWS pricing documentation:** [Bedrock pricing guide](https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-pricing.html)
- **AWS blog post:** [Introducing Claude Sonnet 4.5 in Amazon Bedrock](https://aws.amazon.com/blogs/aws/introducing-claude-sonnet-4-5-in-amazon-bedrock-anthropics-most-intelligent-model-best-for-coding-and-complex-agents/)
- **Anthropic pricing details:** [Cloud platform pricing](../../17-Billing-Plans/about-claude-pricing.md#cloud-platform-pricing)
---
## Claude on Amazon Bedrock - Claude API Docs
Source: https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock
Path: 04-API-Reference/Guides/build-with-claude-claude-on-amazon-bedrock.md
# Claude on Amazon Bedrock
Anthropic's Claude models are now generally available through Amazon Bedrock.
Calling Claude through Bedrock slightly differs from how you would call Claude when using Anthropic's client SDKs. This guide walks you through completing an API call to Claude on Bedrock using one of Anthropic's [client SDKs](../Endpoints/client-sdks.md).
Note that this guide assumes you have already signed up for an [AWS account](https://portal.aws.amazon.com/billing/signup) and configured programmatic access.
Install and configure the AWS CLI
1. [Install a version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) at or newer than version `2.13.23`
2. Configure your AWS credentials using the AWS configure command (see [Configure the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)) or find your credentials by navigating to "Command line or programmatic access" within your AWS dashboard and following the directions in the popup modal.
3. Verify that your credentials are working:
Shell
```python
aws sts get-caller-identity
```
Install an SDK for accessing Bedrock
Anthropic's [client SDKs](../Endpoints/client-sdks.md) support Bedrock. You can also use an AWS SDK like `boto3` directly.
Python
Python
TypeScript
TypeScript
C#
C#
Go
Go
Java
Java
PHP
PHP
Ruby
Ruby
Boto3 (Python)
Boto3 (Python)
```python
pip install -U "anthropic[bedrock]"
```
Accessing Bedrock
Subscribe to Anthropic models
Go to the [AWS Console \> Bedrock \> Model Access](https://console.aws.amazon.com/bedrock/home?region=us-west-2#/modelaccess) and request access to Anthropic models. Note that Anthropic model availability varies by region. See [AWS documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html) for latest information.
API model IDs
| Model | Base Bedrock model ID | `global` | `us` | `eu` | `jp` | `apac` |
|----|----|----|----|----|----|----|
| Claude Opus 4.6 | anthropic.claude-opus-4-6-v1 | Yes | Yes | Yes | Yes | Yes |
| Claude Sonnet 4.6 | anthropic.claude-sonnet-4-6 | Yes | Yes | Yes | Yes | No |
| Claude Sonnet 4.5 | anthropic.claude-sonnet-4-5-20250929-v1:0 | Yes | Yes | Yes | Yes | No |
| Claude Sonnet 4 | anthropic.claude-sonnet-4-20250514-v1:0 | Yes | Yes | Yes | No | Yes |
| Claude Sonnet 3.7 ⚠️ | anthropic.claude-3-7-sonnet-20250219-v1:0 | No | Yes | Yes | No | Yes |
| Claude Opus 4.5 | anthropic.claude-opus-4-5-20251101-v1:0 | Yes | Yes | Yes | No | No |
| Claude Opus 4.1 | anthropic.claude-opus-4-1-20250805-v1:0 | No | Yes | No | No | No |
| Claude Opus 4 | anthropic.claude-opus-4-20250514-v1:0 | No | Yes | No | No | No |
| Claude Haiku 4.5 | anthropic.claude-haiku-4-5-20251001-v1:0 | Yes | Yes | Yes | No | No |
| Claude Haiku 3.5 ⚠️ | anthropic.claude-3-5-haiku-20241022-v1:0 | No | Yes | No | No | No |
| Claude Haiku 3 ⚠️ | anthropic.claude-3-haiku-20240307-v1:0 | No | Yes | Yes | No | Yes |
For more information about regional vs global model IDs, see the [Global vs regional endpoints](#global-vs-regional-endpoints) section below.
List available models
The following examples show how to print a list of all the Claude models available through Bedrock:
AWS CLI
```python
aws bedrock list-foundation-models --region=us-west-2 --by-provider anthropic --query "modelSummaries[*].modelId"
```
Making requests
The following examples show how to generate text from Claude on Bedrock:
Python
```python
from anthropic import AnthropicBedrock
client = AnthropicBedrock(
# Authenticate by either providing the keys below or use the default AWS credential providers, such as
# using ~/.aws/credentials or the "AWS_SECRET_ACCESS_KEY" and "AWS_ACCESS_KEY_ID" environment variables.
aws_access_key="<access key>",
aws_secret_key="<secret key>",
# Temporary credentials can be used with aws_session_token.
# Read more at https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html.
aws_session_token="<session_token>",
# aws_region changes the aws region to which the request is made. By default, we read AWS_REGION,
# and if that's not present, we default to us-east-1. Note that we do not read ~/.aws/config for the region.
aws_region="us-west-2",
)
message = client.messages.create(
model="global.anthropic.claude-opus-4-6-v1",
max_tokens=256,
messages=[{"role": "user", "content": "Hello, world"}],
)
print(message.content)
```
See the [client SDKs](../Endpoints/client-sdks.md) for more details, and the [official Bedrock documentation](https://docs.aws.amazon.com/bedrock/).
Bearer token authentication
You can authenticate with Bedrock using bearer tokens instead of AWS credentials. This is useful in corporate environments where teams need access to Bedrock without managing AWS credentials, IAM roles, or account-level permissions.
Bearer token authentication is supported in the C#, Go, and Java SDKs. The PHP, Python, TypeScript, and Ruby SDKs use AWS SigV4 signing only.
The simplest approach is to set the `AWS_BEARER_TOKEN_BEDROCK` environment variable, which is automatically detected by `fromEnv()` credential resolution.
To provide a token programmatically:
C#
```python
using Anthropic.Bedrock;
using Anthropic.Models.Messages;
var client = new AnthropicBedrockClient(
new AnthropicBedrockApiTokenCredentials
{
BearerToken = "your-bearer-token",
Region = "us-east-1",
}
);
var response = await client.Messages.Create(new MessageCreateParams
{
Model = "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
MaxTokens = 1024,
Messages = [new() { Role = Role.User, Content = "Hello!" }],
});
```
Activity logging
Bedrock provides an [invocation logging service](https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html) that allows customers to log the prompts and completions associated with your usage.
Anthropic recommends that you log your activity on at least a 30-day rolling basis in order to understand your activity and investigate any potential misuse.
Turning on this service does not give AWS or Anthropic any access to your content.
Feature support
For all currently supported features on Bedrock, see [API features overview](../Endpoints/overview.md).
PDF support on Bedrock
PDF support is available on Amazon Bedrock through both the Converse API and InvokeModel API. For detailed information about PDF processing capabilities and limitations, see the [PDF support documentation](build-with-claude-pdf-support.md#amazon-bedrock-pdf-support).
**Important considerations for Converse API users:**
- Visual PDF analysis (charts, images, layouts) requires citations to be enabled
- Without citations, only basic text extraction is available
- For full control without forced citations, use the InvokeModel API
For more details on the two document processing modes and their limitations, refer to the [PDF support guide](build-with-claude-pdf-support.md#amazon-bedrock-pdf-support).
Context window
Claude Opus 4.6, Sonnet 4.6, Sonnet 4.5, and Sonnet 4 have a [1M-token context window](build-with-claude-context-windows.md) on Amazon Bedrock.
For Claude Sonnet 4.5 and Sonnet 4, the 1M-token context window is in beta. To use, include the `context-1m-2025-08-07` beta header in your [Bedrock API requests](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages-request-response.html).
Amazon Bedrock limits request payloads to 20 MB. When sending large documents or many images, you may reach this limit before the token limit.
Global vs regional endpoints
Starting with **Claude Sonnet 4.5 and all future models**, Amazon Bedrock offers two endpoint types:
- **Global endpoints:** Dynamic routing for maximum availability
- **Regional endpoints:** Guaranteed data routing through specific geographic regions
Regional endpoints include a 10% pricing premium over global endpoints.
This applies to Claude Sonnet 4.5 and future models only. Older models (Claude Sonnet 4, Opus 4, and earlier) maintain their existing pricing structures.
When to use each option
**Global endpoints (recommended):**
- Provide maximum availability and uptime
- Dynamically route requests to regions with available capacity
- No pricing premium
- Best for applications where data residency is flexible
**Regional endpoints (CRIS):**
- Route traffic through specific geographic regions
- Required for data residency and compliance requirements
- Available for US, EU, Japan, and Australia
- 10% pricing premium reflects infrastructure costs for dedicated regional capacity
Implementation
**Using global endpoints (default for Opus 4.6, Sonnet 4.5, and Sonnet 4):**
The model IDs for Claude Sonnet 4.5 and 4 already include the `global.` prefix:
Python
```python
from anthropic import AnthropicBedrock
client = AnthropicBedrock(aws_region="us-west-2")
message = client.messages.create(
model="global.anthropic.claude-opus-4-6-v1",
max_tokens=256,
messages=[{"role": "user", "content": "Hello, world"}],
)
```
**Using regional endpoints (CRIS):**
To use regional endpoints, remove the `global.` prefix from the model ID:
Python
```python
from anthropic import AnthropicBedrock
client = AnthropicBedrock(aws_region="us-west-2")
# Using US regional endpoint (CRIS)
message = client.messages.create(
model="anthropic.claude-opus-4-6-v1", # No global. prefix
max_tokens=256,
messages=[{"role": "user", "content": "Hello, world"}],
)
```
Additional resources
- **AWS Bedrock pricing:** [aws.amazon.com/bedrock/pricing](https://aws.amazon.com/bedrock/pricing/)
- **AWS pricing documentation:** [Bedrock pricing guide](https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-pricing.html)
- **AWS blog post:** [Introducing Claude Sonnet 4.5 in Amazon Bedrock](https://aws.amazon.com/blogs/aws/introducing-claude-sonnet-4-5-in-amazon-bedrock-anthropics-most-intelligent-model-best-for-coding-and-complex-agents/)
- **Anthropic pricing details:** [Pricing documentation](../../17-Billing-Plans/about-claude-pricing.md#third-party-platform-pricing)
---
## Claude on Google Cloud - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/claude-on-vertex-ai
Path: 04-API-Reference/Guides/build-with-claude-claude-on-vertex-ai.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fclaude-on-vertex-ai)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Claude on cloud platforms
# Claude on Google Cloud
Copy page
Anthropic's Claude models are available through [Google Cloud's Agent Platform](https://cloud.google.com/vertex-ai).
Copy page
The API for accessing Claude on Google Cloud's Agent Platform is nearly identical to the [Messages API](../Endpoints/messages-create.md), with two key differences in request format:
- On Agent Platform, `model` is not passed in the request body. Instead, it is specified in the Google Cloud endpoint URL.
- On Agent Platform, `anthropic_version` is passed in the request body (rather than as a header), and must be set to the value `vertex-2023-10-16`.
Agent Platform is also supported by Anthropic's official [client SDKs](../Other/cli-sdks-libraries-overview.md). This guide walks you through making a request to Claude on Agent Platform using one of Anthropic's client SDKs.
Note that this guide assumes you already have a Google Cloud project that is able to use Agent Platform. See [Anthropic Claude models on Agent Platform](https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/partner-models/claude) for more information on the setup required and a full walkthrough.
## Install an SDK for accessing Agent Platform
First, install Anthropic's [client SDK](../Other/cli-sdks-libraries-overview.md) for your language of choice.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
pip install -U "anthropic[vertex]"
```
## Accessing Agent Platform
### Model availability
Note that Anthropic model availability varies by region. Search for "Claude" in the [Model Garden](https://cloud.google.com/model-garden) or go to [Anthropic Claude models](https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/partner-models/claude) for the latest information.
#### API model IDs
Lifecycle terms (Deprecated, Retired) are defined in [Model deprecations](../../20-Models/about-claude-model-deprecations.md). Lifecycle dates on partner-operated platforms are set by the partner and can differ from the Claude API schedule. For the current retirement date of any model on Agent Platform, see [Google Cloud's documentation for Claude models on Agent Platform](https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/partner-models/claude).
| Model | Agent Platform API model ID |
|-----------------------------------------------------------------------------------------------|-----------------------------|
| Claude Fable 5.1 | claude-fable-5-1 |
| Claude Mythos 5.1 ([limited availability(opens in new tab)](../../22-Safety-Policy/glasswing.md)) | claude-mythos-5-1 |
| Claude Fable 5 | claude-fable-5 |
| Claude Mythos 5 ([limited availability(opens in new tab)](../../22-Safety-Policy/glasswing.md)) | claude-mythos-5 |
| Claude Opus 5.5 | claude-opus-5-5 |
| Claude Opus 5 | claude-opus-5 |
| Claude Opus 4.8 | claude-opus-4-8 |
| Claude Opus 4.7 | claude-opus-4-7 |
| Claude Opus 4.6 | claude-opus-4-6 |
| Claude Opus 4.5 | claude-opus-4-5@20251101 |
| Claude Opus 4.1 ([deprecated](../../20-Models/about-claude-model-deprecations.md)) | claude-opus-4-1@20250805 |
| Claude Opus 4 ([deprecated](../../20-Models/about-claude-model-deprecations.md)) | claude-opus-4@20250514 |
| Claude Sonnet 5 | claude-sonnet-5 |
| Claude Sonnet 4.6 | claude-sonnet-4-6 |
| Claude Sonnet 4.5 | claude-sonnet-4-5@20250929 |
| Claude Sonnet 4 ([deprecated](../../20-Models/about-claude-model-deprecations.md)) | claude-sonnet-4@20250514 |
| Claude Haiku 4.5 | claude-haiku-4-5@20251001 |
| Claude Haiku 3.5 ([deprecated](../../20-Models/about-claude-model-deprecations.md)) | claude-3-5-haiku@20241022 |
Upgrading to a newer Claude model? In Claude Code, run `/claude-api migrate` to apply model ID swaps and breaking parameter changes across your codebase. The skill detects which cloud platform your code targets and adjusts model ID formats and feature changes for that platform. See [Migrating to a newer Claude model](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md#migrating-to-a-newer-claude-model).
### Making requests
Before running requests you might need to run `gcloud auth application-default login` to authenticate with Google Cloud.
The following examples show how to generate text from Claude on Agent Platform:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicVertex
project_id = "MY_PROJECT_ID"
region = "global"
client = AnthropicVertex(project_id=project_id, region=region)
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=100,
messages=[
{
"role": "user",
"content": "Hey Claude!",
}
],
)
print(message)
```
See the [client SDKs](../Other/cli-sdks-libraries-overview.md) and the official [Agent Platform docs](https://cloud.google.com/vertex-ai/docs) for more details.
Claude is also available through [Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md), [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md), and [Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md).
## Data retention
Data handling for this offering is governed by Google Cloud. For details, see [Agent Platform and zero data retention](https://cloud.google.com/vertex-ai/generative-ai/docs/data-governance).
## Activity logging
Agent Platform provides a [request-response logging service](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/request-response-logging) that allows you to log the prompts and completions associated with your usage.
Anthropic recommends that you log your activity on at least a 30-day rolling basis to understand your activity and investigate any potential misuse.
Turning on this service does not give Google or Anthropic any access to your content.
## Feature support
For the full feature list with Google Cloud availability, see [Features overview](build-with-claude-overview.md).
### Supported feature highlights
- [Messages API](../Endpoints/messages-create.md)
- [Prompt caching](build-with-claude-prompt-caching.md)
- [Thinking](build-with-claude-thinking.md)
- [Tool use](../Agents-Tools/agents-and-tools-tool-use-overview.md), including the [Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md), [Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md), [Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md), [Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md), and [Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)
- [Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)
- [Citations](build-with-claude-citations.md)
- [Structured outputs](build-with-claude-structured-outputs.md)
### Features not supported
- Input sources (URL sources for images and documents, Files API)
- Server-side tools (code execution, web fetch, advisor)
- Agent infrastructure (Agent Skills, MCP connector, programmatic tool calling)
- API endpoints (Message Batches, Models, Admin, Compliance, Usage and Cost)
- Claude Managed Agents
- Server-side fallback (the [`fallbacks` parameter](build-with-claude-refusals-and-fallback.md#server-side-fallback); use the [client-side fallback pattern](build-with-claude-refusals-and-fallback.md#client-side-fallback) instead)
### Context window
Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 5, and Claude Sonnet 4.6 have a [1M-token context window](build-with-claude-context-windows.md) on Agent Platform. Other Claude models, including Sonnet 4.5 and Sonnet 4 (deprecated), have a 200k-token context window.
Agent Platform limits request payloads to 30 MB. When sending large documents or many images, you might reach this limit before the token limit.
## Global, multi-region, and regional endpoints
Agent Platform offers three endpoint types:
- **Global endpoints:** Dynamic routing for maximum availability
- **Multi-region endpoints:** Dynamic routing within a geographic area (for example, the United States or the European Union) for data residency with high availability
- **Regional endpoints:** Guaranteed data routing through specific geographic regions
Regional and multi-region endpoints include a 10% pricing premium over global endpoints.
This applies to Claude Sonnet 4.5 and future models only. Older models (Claude Sonnet 4 (deprecated), Opus 4 (deprecated), and earlier) maintain their existing pricing structures.
### When to use each option
**Global endpoints (recommended):**
- Provide maximum availability and uptime
- Dynamically route requests to regions with available capacity
- No pricing premium
- Best for applications where data residency is flexible
- Only supports pay-as-you-go traffic (provisioned throughput requires regional endpoints)
**Multi-region endpoints:**
- Dynamically route requests across regions within a geographic area (currently `us` and `eu`)
- Useful when you need data residency within a broad geography but want higher availability than a single region
- 10% pricing premium over global endpoints
- Only supports pay-as-you-go traffic (provisioned throughput requires regional endpoints)
**Regional endpoints:**
- Route traffic through specific geographic regions
- Required for single-region data residency, strict compliance mandates, or provisioned throughput
- Support both pay-as-you-go and provisioned throughput
- 10% pricing premium reflects infrastructure costs for dedicated regional capacity
### Implementation
**Using global endpoints (recommended):**
Set the `region` parameter to `"global"` when initializing the client:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicVertex
project_id = "MY_PROJECT_ID"
region = "global"
client = AnthropicVertex(project_id=project_id, region=region)
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=100,
messages=[
{
"role": "user",
"content": "Hey Claude!",
}
],
)
print(message)
```
**Using multi-region endpoints:**
Set the `region` parameter to a multi-region identifier: `"us"` for the United States or `"eu"` for the European Union. The SDK routes requests to the corresponding multi-region endpoint (`https://aiplatform.us.rep.googleapis.com` or `https://aiplatform.eu.rep.googleapis.com`), which dynamically balances traffic across regions within that geography.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicVertex
project_id = "MY_PROJECT_ID"
region = "us" # Multi-region identifier: "us" or "eu"
client = AnthropicVertex(project_id=project_id, region=region)
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=100,
messages=[
{
"role": "user",
"content": "Hey Claude!",
}
],
)
print(message)
```
**Using regional endpoints:**
Specify a specific region such as `"us-east5"` or `"europe-west1"`:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicVertex
project_id = "MY_PROJECT_ID"
region = "us-east5" # Specify a specific region
client = AnthropicVertex(project_id=project_id, region=region)
message = client.messages.create(
# Specific regional endpoints support Claude Sonnet 4.6 and earlier; newer models use the global or multi-region endpoints
model="claude-sonnet-4-6",
max_tokens=100,
messages=[
{
"role": "user",
"content": "Hey Claude!",
}
],
)
print(message)
```
Claude Mythos Preview is a research preview available to invited customers on Agent Platform. For more information, see [Project Glasswing](../../22-Safety-Policy/glasswing.md).
## Additional resources
- **Agent Platform pricing:** [Generative AI pricing on cloud.google.com](https://cloud.google.com/vertex-ai/generative-ai/pricing)
- **Claude models documentation:** [Claude on Agent Platform](https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/partner-models/claude)
- **Google blog post:** [Global endpoint for Claude models](https://cloud.google.com/blog/products/ai-machine-learning/global-endpoint-for-claude-models-generally-available-on-vertex-ai)
- **Anthropic pricing details:** [Cloud platform pricing](../../17-Billing-Plans/about-claude-pricing.md#cloud-platform-pricing)
---
## Claude Platform on AWS - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws
Path: 04-API-Reference/Guides/build-with-claude-claude-platform-on-aws.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fclaude-platform-on-aws)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Claude on cloud platforms
# Claude Platform on AWS
Copy page
Access Claude's full platform capabilities through AWS with Anthropic-managed infrastructure.
Copy page
Claude Platform on AWS gives you the full Anthropic platform experience, including the Messages API, Agent Skills, code execution, and beta features, accessible through your AWS account. Unlike [Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md), where AWS operates the inference stack, Anthropic operates Claude Platform on AWS. AWS provides the authentication layer (SigV4 or API key), IAM-based access control, and billing integration through AWS Marketplace.
The Anthropic SDKs support Claude Platform on AWS.
## How the platform integration works
Claude models run on Anthropic-managed infrastructure. This is a commercial integration for billing and access through AWS. Anthropic is the data processor for inference inputs and outputs. AWS processes billing and identity metadata under the marketplace model. Customers using Claude through Claude Platform on AWS are subject to Anthropic's [data use terms](https://www.anthropic.com/legal).
Anthropic uses AWS infrastructure to process your API requests, run model inference, and store your workspace content (such as prompts, outputs, files, Skills, and batches). For workspaces created before September 18, 2026, 00:00 UTC, Anthropic might process requests, store data, and run inference outside AWS. In either case, subservices might change without notice. Set the [`inference_geo`](#data-residency) parameter per request to pin inference to a specific geography.
Claude Platform on AWS follows the same data retention policy as the first-party Claude API. Zero Data Retention (ZDR) is available on request. Contact your Anthropic account representative to enable it for your organization.
## Claude Platform on AWS versus Amazon Bedrock
Both offerings let you use Claude through AWS, but they differ in architecture, API surface, and feature availability.
| Aspect | Claude Platform on AWS | [Claude in Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md) | [Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md) |
|:-----------------------------|:------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------|
| **Who operates the stack** | Anthropic | AWS | AWS |
| **API surface** | Claude API (`/v1/{endpoint}`) | Messages API at `/anthropic/v1/messages` | Bedrock Converse / InvokeModel |
| **Feature availability** | Typically same-day as Claude API (see [feature limitations](#features-not-supported)) | Per Amazon Bedrock release schedule | Per Amazon Bedrock release schedule |
| **Agent Skills** | Available | Not available (requires code execution) | Not available |
| **Beta features** | Pass through with `anthropic-beta` headers (see [feature limitations](#features-not-supported)) | `anthropic-beta` header not supported | `anthropic-beta` header not supported |
| **Authentication** | AWS IAM / SigV4 or API key | AWS IAM / SigV4 | AWS IAM / SigV4 or bearer token |
| **Billing** | AWS Marketplace | AWS (native service) | AWS (native service) |
| **Base URL** | `aws-external-anthropic.{region}.api.aws` | `bedrock-mantle.{region}.api.aws` | `bedrock-runtime.{region}.amazonaws.com` |
| **SDK client** | `AnthropicAWS`, in beta | `AnthropicBedrockMantle` | `AnthropicBedrock` / Bedrock SDK |
| **Console** | Claude Console (`platform.claude.com`, access through the AWS Console) | Bedrock Console | Bedrock Console |
| **Rate limits and quotas** | Managed by Anthropic | Managed by AWS | Managed by AWS |
| **Inference data processor** | Anthropic | AWS | AWS |
If you need AWS-operated Claude, see [Claude in Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md). Claude Platform on AWS uses a separate capacity pool from both the first-party Claude API and Amazon Bedrock. You can run workloads on more than one platform and fail over between them.
[AWS PrivateLink](https://docs.aws.amazon.com/vpc/latest/privatelink/what-is-privatelink.html) is supported for connecting your VPC to the Claude Platform on AWS endpoint.
**When to choose Bedrock:** Organizations in regulated industries that require FedRAMP High, IL4, IL5, or HIPAA-ready compliance, or that need AWS to be the sole data processor, should use [Claude in Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md). Bedrock runs entirely on AWS-controlled infrastructure with AWS as the operating party.
**Which offering are you using?** Claude is available through several distinct products:
- **Claude Platform on AWS** (this page): The Claude API platform billed through AWS Marketplace. Managed in the [Claude Console](#using-the-claude-console) and the AWS Console.
- **[Claude in Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md):** An AWS-native service. Managed in the Amazon Bedrock console and billed as AWS service usage.
- **Claude Enterprise procured through AWS Marketplace:** A [claude.ai](https://claude.ai) plan (the Claude chat product), not an API platform. Managed at claude.ai, and its account and migration behavior differ from what this page describes. See the [Claude Help Center](https://support.claude.com).
- **Direct Anthropic accounts:** The first-party Claude API and claude.ai plans billed by Anthropic. Managed in the Claude Console and at claude.ai.
## Set up your account
Setting up Claude Platform on AWS happens in four phases: sign up on the AWS Console service page, complete your Anthropic organization setup, note your workspace ID, and sign in to the Claude Console.
Signing up through the AWS Console provisions a new Anthropic organization tied to your AWS account. This organization is separate from any existing organizations your company has with Anthropic, including Claude Enterprise organizations procured through AWS Marketplace. API keys, workspaces, and Claude Console settings from a first-party Anthropic organization don't carry over.
If you have an existing Amazon Bedrock private offer, contact your Anthropic or AWS account representative before signing up so your discount applies from your first request. Discounts cannot be applied retroactively to usage incurred before your private offer is accepted. See [Private offers](../../17-Billing-Plans/about-claude-pricing.md#private-offers).
1. 1
### Sign up in the AWS Console
1. Open the [AWS Console](https://console.aws.amazon.com/) and navigate to the **Claude Platform on AWS** service page.
2. Choose **Sign up**.
3. On the Sign-up page, review the terms (Anthropic's End User License Agreement, the AWS Privacy Notice, and the AWS Customer Agreement) and select the agreement checkbox.
4. Choose **Continue**.
The page shows a **Sign-up in progress** banner. Stay on the page. Sign-up takes a few minutes while AWS handles the AWS Marketplace subscription for you, then redirects you automatically.
If your organization has a private offer from Anthropic, the Console looks it up and prompts you to accept it in AWS Marketplace. See [Private offers](../../17-Billing-Plans/about-claude-pricing.md#private-offers) for details.
When you use Claude Platform on AWS, Anthropic processes and stores your content (such as prompts and outputs) on AWS infrastructure. For workspaces created before September 18, 2026, 00:00 UTC, Anthropic might process and store that content outside AWS. Anthropic's [data use policies](https://www.anthropic.com/legal) describe how content and metadata are processed and stored.
2. 2
### Set up your Anthropic organization
After sign-up completes, you're redirected to `platform.claude.com/partner-signup`.
1. Enter the email address of your organization's owner and choose **Get started**.
2. Check that email inbox for a setup link and follow it. If your browser shows a **Signed in as a different account** page, choose **Log out and continue**.
3. Complete the organization details form (organization name, entity type, country, intended use) and choose **Complete setup**.
Completing setup creates your Anthropic organization and accepts Anthropic's Commercial Terms of Service and Usage Policy. The AWS Console service page now shows a left navigation with **Home**, **API keys**, **Quickstart**, and **Workspaces**.
3. 3
### Create your workspace and note its ID
After you complete setup, the AWS Console prompts you to create a workspace. See [Workspaces](#workspaces) for details on region binding, IAM resource scoping, and creating additional workspaces.
Find the workspace ID under **Workspaces** on the AWS Console **Claude Platform on AWS** service page or in the [Claude Console](#using-the-claude-console). Workspace IDs use the format `wrkspc_` followed by an alphanumeric identifier.
4. 4
### Sign in to the Claude Console
Access to the Claude Console is federated through AWS IAM:
1. Assume an IAM role with the `aws-external-anthropic:AssumeConsole` permission. See [IAM actions for Claude Platform on AWS](../Endpoints/claude-platform-on-aws-iam-actions.md#console-access).
2. From the **Claude Platform on AWS** service page, choose **Open Claude Console**. The AWS Console issues a JWT and redirects you to `platform.claude.com`.
3. On first sign-in, you're prompted for an email address. Enter your work email. The platform provisions your Claude Console user just-in-time.
When you're signed in through the AWS Console, the Claude Console scopes to your Claude Platform on AWS organization. An **Account managed by AWS** indicator appears in the bottom-left of the Claude Console sidebar.
### Moving from an existing Anthropic organization
Signing up for Claude Platform on AWS always provisions a new Anthropic organization tied to your AWS account. There is no in-place conversion: an existing organization, such as a first-party Claude API organization, can't become a Claude Platform on AWS organization.
Plan a move from an existing organization as a cutover to a new one:
- **Create the new organization first.** Sign up through the AWS Console (see [Set up your account](#set-up-your-account)). If your move involves a private offer, complete sign-up before the offer is accepted: discounts apply from acceptance, not retroactively. See [Private offers](../../17-Billing-Plans/about-claude-pricing.md#private-offers).
- **Recreate access and configuration.** API keys, workspaces, and Claude Console settings don't carry over from an existing organization. Create workspaces in the new organization and switch your applications to [Claude Platform on AWS authentication](#authentication).
- **Update your integration.** Claude Platform on AWS serves the Claude API (`/v1/{endpoint}`), so request and response shapes are unchanged from the first-party Claude API. What changes is the base URL, the authentication method, and the `anthropic-workspace-id` header on inference and resource requests; see [Making requests](#making-requests). Some platform features differ; see [Features not supported](#features-not-supported).
- **Cut over on your own schedule.** The new organization is independent of your existing one, and both can serve traffic in parallel. There's no need for a hard cutover: shift workloads gradually until all of your traffic is on the new organization.
Once the new organization is running, the differences are concentrated in billing and authentication, which are handled through AWS:
- **Billing** moves to AWS Marketplace: usage is billed in Claude Consumption Units rather than prepaid credits (see [Billing](#billing)), and you set spend limits on the Billing page (see [Spend limits](#spend-limits)). During the transition, billing stays separate: the existing organization continues to be billed as it is today.
- **Authentication and access** move to AWS: requests authenticate with AWS credentials or with API keys generated in the AWS Console, not the Claude Console (see [Authentication](#authentication)). Organization membership is managed through AWS IAM rather than the Claude Console (see [Available pages](#available-pages)), and Anthropic's client SDKs provide platform-specific client classes (see [Install an SDK](#install-an-sdk)).
- **Day-to-day API usage** works the way it does on the first-party Claude API, except where noted in the [feature limitations](#features-not-supported). Before shifting production traffic, check your rate limits: new organizations are placed on the Start tier, and limit increases go through your Anthropic account representative (see [Rate limits and quotas](#rate-limits-and-quotas)).
For Claude Enterprise (claude.ai) organizations, which behave differently, see the [offering comparison](#claude-platform-on-aws-vs-amazon-bedrock).
### Troubleshooting account setup
- **"Sign-up failed: Failed to enable OutboundWebIdentityFederation":** If you see this banner on first submit, choose **Continue** again. The IAM enablement can take a moment to take effect.
- **No progress indicator during sign-up:** Sign-up takes a few minutes. The page shows a static **Sign-up in progress** banner without a progress bar while AWS provisions your account.
- **"Signed in as a different account" after following the setup link:** Choose **Log out and continue**. The page reauthenticates you with the email address you entered.
- **"Not found" message during sign-in:** This message might appear briefly during redirect. You can dismiss it.
- **Usage page shows no data after your first API call:** Usage data can take a few minutes to appear in the Claude Console.
- **"Outbound web identity federation is disabled" on your first API call:** Enable federation once per account. See [Enable outbound web identity federation](#enable-outbound-web-identity-federation).
## Before making API calls
Ensure you have:
1. An active AWS account with a subscription to Claude Platform on AWS (see [Set up your account](#set-up-your-account))
2. The [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) installed and configured
3. **Outbound web identity federation enabled** on your AWS account, a one-time setup step (see [Enable outbound web identity federation](#enable-outbound-web-identity-federation))
4. Your workspace ID (see [Obtain your workspace ID](#obtain-your-workspace-id))
5. IAM permission to call the API: the `aws-external-anthropic:CreateInference` action on your workspace, plus `aws-external-anthropic:CallWithBearerToken` if you authenticate with an API key (see [IAM policies](#iam-policies))
### Enable outbound web identity federation
The Claude Platform on AWS gateway calls `sts:GetWebIdentityToken` server-side to mint a JWT it forwards to Anthropic. This STS capability is **disabled by default** on every AWS account. Enable it once per account:
CLI
```python
aws iam enable-outbound-web-identity-federation
```
If the response is `[ERROR] (FeatureEnabled) ... already enabled`, the setting is already on for your account and you can move on. Verify and retrieve your account's issuer URL:
CLI
```python
aws iam get-outbound-web-identity-federation-info
```
Without this step, every request returns `"Outbound web identity federation is disabled for your account"`. This is the most common setup error.
### Obtain your workspace ID
You create a workspace from the AWS Console after completing account setup (see [Set up your account](#set-up-your-account)). Workspaces are bound to a single AWS region. You can find the workspace ID in the [Claude Console](#using-the-claude-console) under **Workspaces** or in the **Workspaces** section of the AWS Console service page.
Set the `ANTHROPIC_AWS_WORKSPACE_ID` and `AWS_REGION` environment variables so the SDK clients read them automatically:
CLI
```python
export ANTHROPIC_AWS_WORKSPACE_ID='wrkspc_01AbCdEf23GhIj'
export AWS_REGION='us-west-2' # Your workspace's AWS region
```
The region is required. The SDK client raises an error if no region is set. Pass `aws_region`/`awsRegion` to the constructor, or set `AWS_REGION` (or `AWS_DEFAULT_REGION`). All AWS commercial regions are supported.
## Authentication
Claude Platform on AWS supports two authentication methods: AWS IAM with Signature Version 4 (SigV4) request signing (primary) and API key authentication. Both use the same base URL and request format.
### SigV4 authentication
SigV4 is the enterprise-native path and integrates with your existing AWS IAM policies, roles, and auditing. Configure AWS credentials using any method supported by the [AWS default credential provider chain](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html):
- Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`)
- Shared credentials file (`~/.aws/credentials`)
- Shared config file (`~/.aws/config`) including SSO and `credential_process`
- Web identity (`AWS_WEB_IDENTITY_TOKEN_FILE` and `AWS_ROLE_ARN`) for IRSA and GitHub Actions
- ECS container credentials
- EC2 instance metadata service (IMDS)
Verify that your credentials are working:
CLI
```python
aws sts get-caller-identity
```
### API key authentication
For simpler integration paths (local development and scripts), you can authenticate with an API key instead of SigV4. Set the `ANTHROPIC_AWS_API_KEY` environment variable or pass `apiKey` to the SDK constructor.
Generate API keys in the **AWS Console** under **Claude Platform on AWS → API keys**. Choose **Generate a key**, then copy the key value. Grant the `aws-external-anthropic:CallWithBearerToken` IAM action to the principals that should be allowed to use API key authentication.
API keys for Claude Platform on AWS are managed in the AWS Console, not the Claude Console. Keys created in the standard [Claude Console](../Other/usage-limits.md) (for first-party API access) don't work with the Claude Platform on AWS endpoint.
#### Short-term API keys
For workloads that need to hand a credential to a separate process (such as an LLM gateway, a serverless function, or a tool that supports bearer-token authentication but not SigV4), generate a short-term API key from your AWS credentials instead of provisioning a long-lived key in the AWS Console.
AWS publishes token-generator libraries for [JavaScript](https://github.com/aws/token-generator-for-aws-external-anthropic-js), [Python](https://github.com/aws/token-generator-for-aws-external-anthropic-python), and [Java](https://github.com/aws/token-generator-for-aws-external-anthropic-java). Each library reads your AWS credentials through the standard provider chain and returns a time-limited token that works with the `x-api-key` header. Token lifetime defaults to 12 hours and is capped at the lesser of your requested duration, your AWS credentials' expiry, and 12 hours. See the linked repository READMEs for installation and full configuration options.
Pass the generated token to the SDK the same way you'd pass an AWS Console-generated API key:
Python
TypeScript
Java
```python
from token_generator_for_aws_external_anthropic import TokenGenerator
from anthropic import AnthropicAWS
token = TokenGenerator(region="us-west-2").get_token()
client = AnthropicAWS(api_key=token, aws_region="us-west-2")
```
If you can generate the token locally, your process already has SigV4 credentials, and SigV4 authentication is usually the simpler choice. Use short-term keys when the process making API calls is separate from the process that holds AWS credentials.
The SDK does not refresh short-term keys automatically. When a token expires, generate a new one and construct a new client. The principal that uses the token still needs the `aws-external-anthropic:CallWithBearerToken` IAM action.
### Credential precedence
The platform-specific client resolves authentication in the following order. Argument names vary by language convention: TypeScript and PHP use camelCase as shown, Python and Ruby use snake_case, Go uses PascalCase with capitalized acronyms, and C# and Java use the language's property or builder idioms.
1. `apiKey` constructor argument → `x-api-key` header
2. `awsAccessKey` + `awsSecretAccessKey` constructor arguments → AWS SigV4
3. `awsProfile` constructor argument → AWS SigV4 with named profile
4. `ANTHROPIC_AWS_API_KEY` environment variable → `x-api-key` header
5. Default AWS credential provider chain → AWS SigV4
### Region resolution
The client reads `AWS_REGION` from the environment if `aws_region`/`awsRegion` is not passed to the constructor, falling back to `AWS_DEFAULT_REGION` for compatibility with the standard AWS SDKs. Region is required and there is no default: the `AnthropicAWS`/`AnthropicAws` client raises an error if neither the constructor argument nor an environment variable is set.
## Install an SDK
Anthropic's [client SDKs](../Other/cli-sdks-libraries-overview.md) support Claude Platform on AWS. Your SDK provides `AnthropicAWS`, which handles SigV4 signing, region-based base URL construction, and the `anthropic-workspace-id` header.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
pip install -U "anthropic[aws]"
```
On macOS with Homebrew Python or other externally managed Python environments, `pip install` can fail with a PEP 668 `externally-managed-environment` error. Create and activate a virtual environment first: `python3 -m venv .venv && source .venv/bin/activate`.
SDK clients for Claude Platform on AWS are in beta.
## Available models
The following models are available on Claude Platform on AWS:
| Model | Model ID |
|-------------------|-------------------|
| Claude Fable 5.1 | claude-fable-5-1 |
| Claude Fable 5 | claude-fable-5 |
| Claude Opus 5.5 | claude-opus-5-5 |
| Claude Opus 5 | claude-opus-5 |
| Claude Opus 4.8 | claude-opus-4-8 |
| Claude Opus 4.7 | claude-opus-4-7 |
| Claude Opus 4.6 | claude-opus-4-6 |
| Claude Opus 4.5 | claude-opus-4-5 |
| Claude Sonnet 5 | claude-sonnet-5 |
| Claude Sonnet 4.6 | claude-sonnet-4-6 |
| Claude Sonnet 4.5 | claude-sonnet-4-5 |
| Claude Haiku 4.5 | claude-haiku-4-5 |
Model IDs are identical to the first-party Claude API. There are no Bedrock-style ARNs or `anthropic.` prefixes.
New models typically launch on Claude Platform on AWS the same day as the first-party Claude API.
Upgrading to a newer Claude model? In Claude Code, run `/claude-api migrate` to apply model ID swaps and breaking parameter changes across your codebase. The skill detects which cloud platform your code targets and adjusts model ID formats and feature changes for that platform. See [Migrating to a newer Claude model](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md#migrating-to-a-newer-claude-model).
## Making requests
Claude Platform on AWS uses the same API endpoints as the first-party Claude API. The differences are the base URL, the authentication method, and the `anthropic-workspace-id` header, which identifies the [workspace](#workspaces) a request targets. The header is required on inference and resource requests, such as calls to the Messages API, Models API, Files API, and Claude Managed Agents endpoints. Requests to the [Admin API](../Other/manage-claude-admin-api.md) workspace and external key endpoints don't require it.
Before running these examples, complete the steps in [Before making API calls](#before-making-api-calls).
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicAWS
client = AnthropicAWS()
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
print(message)
```
The client reads `AWS_REGION` (or `AWS_DEFAULT_REGION`) and `ANTHROPIC_AWS_WORKSPACE_ID` from the environment. You can override either by passing `aws_region` / `awsRegion` or `workspace_id` / `workspaceId` to the constructor. Both region and workspace ID are required. The constructor raises an error if either cannot be resolved.
The `x-amz-security-token` header (cURL) is only required for temporary credentials such as IAM roles, SSO, or STS. Omit it when using long-term IAM user credentials. The SDK clients handle this automatically based on the credential source.
The `--aws-sigv4` value follows the format `aws:amz:<region>:<service>`. The SigV4 service name is `aws-external-anthropic`, and the region must match the region in your endpoint URL. A mismatch in either produces a generic signature-rejection error rather than a specific diagnostic.
### Context window
Context-window sizes on Claude Platform on AWS are identical to the first-party Claude API. See [Context windows](build-with-claude-context-windows.md) for per-model limits.
## Feature support
Claude Platform on AWS uses Claude API endpoints directly, which means you get full feature parity with the first-party Claude API (except where noted in the [feature limitations](#features-not-supported)):
- **Feature access:** Because Anthropic operates both platforms, most new features and beta headers become available on Claude Platform on AWS without a separate integration step. See [feature limitations](#features-not-supported) for exceptions.
- **Beta features:** Pass the standard `anthropic-beta` header to access beta features, just as you would with the Claude API.
- **Agent Skills:** Use pre-built and custom [Agent Skills](../Agents-Tools/agents-and-tools-agent-skills-overview.md) with the same `container.skills` parameter as the Claude API. All pre-built Skills (PowerPoint, Excel, Word, PDF) work out of the box.
- **Code execution:** Run code in Anthropic's managed sandbox using the [code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md).
- **Tool use:** Computer use and all other [tool use capabilities](../Agents-Tools/agents-and-tools-tool-use-overview.md) are available.
- **Extended thinking:** Enable extended thinking with the same parameters as the Claude API.
- **Streaming:** Full SSE streaming support for real-time responses.
- **Batch processing:** Submit batch requests for high-throughput workloads.
- **Prompt caching:** Cache tools, system prompts, and message history to reduce latency and cost. All prompt caching capabilities (5-minute TTL, 1-hour TTL, and automatic caching) are available.
- **Files API:** Upload and reference files across requests.
- **Customer-managed encryption keys (CMEK):** [CMEK](../Other/manage-claude-cmek.md) is available with [AWS KMS](../Other/manage-claude-cmek-aws-kms.md) keys only. Google Cloud KMS and Azure Key Vault keys cannot be registered. The key must be a single-region KMS key in the same AWS account and region as the workspace it is attached to, and its key policy must grant access to the `aws-external-anthropic.amazonaws.com` service principal; see [Set up CMEK on Claude Platform on AWS](../Other/manage-claude-cmek-aws-kms.md#claude-platform-on-aws). Register and attach keys in the [Claude Console](#using-the-claude-console); the external key endpoints are also available, authorized through [IAM actions](../Endpoints/claude-platform-on-aws-iam-actions.md#encryption-keys). There is no separate validation step: the key is implicitly validated when you attach it to a workspace (the attach call performs an encrypt/decrypt round), so a key policy problem surfaces at attach time rather than at registration.
- **Compliance API:** The [Compliance API](../Other/manage-claude-compliance-api.md) is available. Access is authorized through the AWS IAM [`ListComplianceActivities` action](../Endpoints/claude-platform-on-aws-iam-actions.md#compliance).
See the [comparison table](#claude-platform-on-aws-vs-amazon-bedrock) for feature-availability differences from Amazon Bedrock.
### Claude Managed Agents
[Claude Managed Agents](../Other/managed-agents-overview.md) is available on Claude Platform on AWS, including [agents](../Other/managed-agents-agent-setup.md), [environments](../Other/managed-agents-environments.md), [sessions](../Other/managed-agents-sessions.md), [credential vaults](../Other/managed-agents-vaults.md), [memory stores](../Other/managed-agents-memory.md), [webhooks](../Other/managed-agents-webhooks.md), [multiagent orchestration](../Other/managed-agents-multiagent-orchestration.md), and [self-hosted sandboxes](../Other/managed-agents-self-hosted-sandboxes.md).
Session behavior on Claude Platform on AWS differs from first-party Claude Managed Agents in two ways:
- **Autonomous-session reauthentication:** A session can run autonomously, without any [user events](../Other/managed-agents-reference.md#event-types), for up to 6 hours. After 6 hours, the session requires reauthentication before it continues. To reauthenticate, send any user-role event to the session (see [Events and streaming](../Other/managed-agents-events-and-streaming.md)). First-party Claude Managed Agents has no autonomous-session runtime limit.
- **[Memory stores on self-hosted environments](../Other/managed-agents-self-hosted-sandboxes.md#use-memory-stores):** A session that runs on a self-hosted environment cannot attach memory stores; a session that includes one is rejected at creation. Sessions on cloud environments attach memory stores as usual. On first-party Claude Managed Agents, sessions on both cloud and self-hosted environments can attach memory stores.
### Features not supported
The following capabilities are not currently available on Claude Platform on AWS:
- **HIPAA readiness:** Anthropic's HIPAA-ready program is not available. See [API and data retention](../Other/manage-claude-api-and-data-retention.md).
- **Computer use and browser use toolsets:** `computer_toolset_20260801` and `browser_toolset_20260801` are not currently available on Claude Platform on AWS. The beta [computer use](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md#earlier-tool-versions) tool versions remain available.
- **Admin API:** Workspace endpoints (create, get, list, update, and archive on `/v1/organizations/workspaces`) and external key endpoints (register, get, list, update, and delete on `/v1/organizations/external_keys`, for [CMEK](../Other/manage-claude-cmek.md); keys are validated when attached to a workspace rather than through a validate endpoint) are available. Other Admin API endpoints (organization members, workspace members, invites, API keys, usage reports, cost reports, and rate limit reports) are not currently available. View usage and cost data in the [Claude Console](#using-the-claude-console) instead. AWS IAM manages organization membership.
- **Workspace member management:** Adding or removing users from individual workspaces is not available. AWS IAM policies on workspace ARNs control access.
- **Claude Code workspace and Analytics API:** The Claude Code workspace with automatic rate limits is not available. Claude Code usage appears in the general usage view rather than a dedicated screen.
- **OAuth authentication:** Not supported. Use SigV4 or API key authentication.
- **Fast mode:** Not available on Claude Platform on AWS.
- **OpenAI-compatible API endpoints:** Not available on Claude Platform on AWS.
- **MCP tunnels:** Only MCP servers exposed over the public internet are supported.
## Data residency
Claude Platform on AWS supports the following inference geographies:
- **US:** Inference stays within US data centers. A 1.1x pricing multiplier applies.
- **Global:** Inference can route to any Anthropic-operated data center worldwide. Standard pricing applies.
The AWS region your workspace is bound to controls which gateway endpoint you call and where AWS-side resources (IAM, CloudTrail, billing) are scoped. It does not pin where model inference runs. To pin inference to a specific geography, set `inference_geo` on each request or configure a workspace default.
Set the inference geography per request with the `inference_geo` parameter:
The `inference_geo` parameter is supported on Claude 4.6 and later models. Requests with `inference_geo` on Claude Opus 4.5, Claude Sonnet 4.5, or Claude Haiku 4.5 return a 400 error. See [Data residency](build-with-claude-data-residency.md) for model availability details.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicAWS
client = AnthropicAWS()
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
inference_geo="us",
messages=[{"role": "user", "content": "Hello!"}],
)
print(message)
```
If you omit `inference_geo`, the request uses the workspace's `default_inference_geo` if one is configured, otherwise `global`.
Workspace-level inference geography controls (`allowed_inference_geos` and `default_inference_geo`) are also available on Claude Platform on AWS. See [Workspace-level restrictions](build-with-claude-data-residency.md#workspace-level-restrictions).
## Workspaces
Inference and resource requests on Claude Platform on AWS target a workspace. You pass the workspace's ID in the `anthropic-workspace-id` header on these API calls. Workspace IDs use the tagged format `wrkspc_` followed by an alphanumeric identifier (for example, `wrkspc_01AbCdEf23GhIj`). See [Obtain your workspace ID](#obtain-your-workspace-id) if you don't have it yet.
### Workspace scoping
Workspaces are bound to a single AWS region. A workspace created in `us-west-2` can only be accessed through the `us-west-2` endpoint. Usage, quotas, cost, files, batches, and Skills all roll up per workspace, giving you per-region breakdowns in the Claude Console.
Workspaces also serve as the primary IAM resource for Claude Platform on AWS. You grant or deny access to specific workspaces through AWS IAM policies using the workspace ARN. The ARN's resource segment is the same `wrkspc_`-prefixed ID you pass in the `anthropic-workspace-id` header:
``` block
arn:aws:aws-external-anthropic:{region}:{account-id}:workspace/{workspace-id}
```
For example:
``` block
arn:aws:aws-external-anthropic:us-west-2:123456789012:workspace/wrkspc_01AbCdEf23GhIj
```
See [IAM policies](#iam-policies) for policy examples.
### Managing workspaces
Create additional workspaces, rename a workspace, or archive a workspace from the AWS Console **Workspaces** page or with the [Admin API](../Other/manage-claude-admin-api.md) workspace endpoints. These endpoints don't require the `anthropic-workspace-id` header. Create and list act on the organization; get, update, and archive take the workspace ID in the URL path. A new workspace is bound to the AWS region of the endpoint you call to create it (see [Workspace scoping](#workspace-scoping)). With the Admin role, you can also create, rename, and archive workspaces from the Claude Console **Workspaces** page.
## Using the Claude Console
Claude Platform on AWS uses the standard Claude Console at [platform.claude.com](../Other/usage-limits.md). When you sign in from the AWS Console, an **Account managed by AWS** indicator appears in the bottom-left of the Claude Console sidebar and the Console scopes to your Claude Platform on AWS organization. It provides usage analytics, cost breakdowns, rate limit visibility, workspace management, and pages for managing files, Agent Skills, batch jobs, and Claude Managed Agents resources (agents, sessions, environments, credential vaults, memory stores, and webhooks).
### Signing in
Access to the Claude Console is federated through AWS IAM. See [Set up your account](#set-up-your-account) for the full first-time sign-in flow. In short:
1. Assume an IAM role with the `aws-external-anthropic:AssumeConsole` permission. See [IAM actions for Claude Platform on AWS](../Endpoints/claude-platform-on-aws-iam-actions.md#console-access).
2. Navigate to the Claude Platform on AWS page in the [AWS Console](https://console.aws.amazon.com/).
3. Choose **Open Claude Console**. The AWS Console issues a JWT and redirects you to `platform.claude.com`.
4. On first sign-in, you're prompted for an email address. Enter your work email. The platform provisions your Claude Console user just-in-time.
Two Claude Console roles are available: **Admin** and **Developer**. The Admin role grants access to all Claude Console pages and settings available for Claude Platform on AWS. The Developer role grants read access to usage, cost, rate limit, and workspace information. Contact your Anthropic account representative to assign the Admin or Developer role to a principal.
### Available pages
The **Through AWS gateway** column indicates whether the page reads and writes data through the AWS gateway (and is therefore governed by [IAM actions](../Endpoints/claude-platform-on-aws-iam-actions.md)). Pages marked **No** read organization-level metadata directly from Anthropic and bypass IAM action checks.
| Page | Available | Through AWS gateway | Notes |
|:----------------------|:--------------|:--------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Usage** | Yes | No | View token usage by model, workspace, and dimension. Data can take a few minutes to appear after a request. |
| **Cost** | Yes | No | View cost breakdowns by model and workspace. AWS Cost Explorer shows the aggregated [Claude Consumption Unit (CCU)](#billing) line item. |
| **Rate limits** | Yes | No | View rate limits (read-only). Tier increases go through your Anthropic account representative; see [Rate limits and quotas](#rate-limits-and-quotas). |
| **Workspaces** | Yes | Yes (except spend limits) | View per-region workspaces. With the Admin role, you can also create, rename, and archive workspaces, and set per-workspace [spend limits](#spend-limits). |
| **Encryption keys** | Yes | Yes | Under **Settings → Encryption keys**, register AWS KMS keys for [CMEK](../Other/manage-claude-cmek-aws-kms.md#claude-platform-on-aws) (Admin role). To attach a registered key to a workspace, go to [Manage → Security](https://platform.claude.com/settings/workspaces/default/security-compliance) and select the workspace in the workspace picker at the top of the sidebar. |
| **Files** | Yes | Yes | View and manage uploaded files. |
| **Skills** | Yes | Yes | View and manage Agent Skills. |
| **Batches** | Yes | Yes | View and manage batch processing jobs. |
| **Agents** | Yes | Yes | View and manage agent definitions. |
| **Sessions** | Yes | Yes | View agent sessions and event history. |
| **Environments** | Yes | Yes | View and manage cloud sandbox configurations for sessions. |
| **Credential vaults** | Yes | Yes | View and manage credential vaults for session authentication. |
| **Memory stores** | Yes | Yes | View and manage persistent agent memory. |
| **Webhooks** | Yes | Yes | View and manage webhook endpoints under **Settings → Webhooks**. |
| **API keys** | No | N/A | Manage API keys in the AWS Console (**Claude Platform on AWS → API keys**). See [API key authentication](#api-key-authentication). |
| **Members** | No | N/A | Not applicable. AWS IAM manages access. |
| **Billing** | Yes (limited) | No | Set an organization monthly spend limit; see [Spend limits](#spend-limits). AWS Marketplace manages invoicing. View cost breakdowns on the Cost page. |
| **Claude Code** | No | N/A | View Claude Code usage on the Usage page. |
### Switching organizations
The Claude Console does not support organization switching for Claude Platform on AWS. To access a different organization, sign out and reauthenticate through the AWS Console using the IAM role for that organization's AWS account.
## Rate limits and quotas
Organizations on Claude Platform on AWS are placed on the Start tier. Anthropic manages rate limits directly, not through AWS quota systems.
Organizations on Claude Platform on AWS can move to a higher usage tier automatically as they build a history of paid AWS Marketplace invoices. The self-service **Request rate limit increase** flow in the Claude Console is not available: the Rate limits page directs you to your Anthropic account representative instead.
To request higher limits, contact your Anthropic account representative or [Anthropic support](https://support.claude.com). Include the following in your request:
- The models you need raised
- Peak input tokens per minute and output tokens per minute for each model (not daily totals)
- The approximate share of your input that is cached or repeated context (cache reads don't count toward input-token limits for most models; see [cache-aware ITPM](../Endpoints/rate-limits.md#cache-aware-itpm))
Usage tiers are fixed steps: each tier pairs rate limits with a [monthly spend cap](#spend-limits), and moving to a higher tier raises both. For tier details and per-model limits, see [Rate limits](../Endpoints/rate-limits.md).
## Billing
Claude Platform on AWS bills through [AWS Marketplace](https://aws.amazon.com/marketplace). Usage is denominated in Claude Consumption Units (CCUs), metered hourly, and invoiced monthly in arrears on your AWS bill. CCUs are not prepaid credits. There is no CCU balance or commitment.
For the CCU price, conversion mechanics, discount application, and per-model token rates, see [Claude Platform on AWS pricing](../../17-Billing-Plans/about-claude-pricing.md#claude-platform-on-aws-pricing).
### Spend limits
The Start, Build, and Scale usage tiers each carry a monthly spend cap; see the [per-tier spend caps](../Endpoints/rate-limits.md#spend-limits) for current values. When your organization's usage for the calendar month reaches its tier's cap, API requests fail with the [spend-cap error](../Endpoints/rate-limits.md#reaching-your-spend-cap) until 00:00 UTC on the first day of the next month, and retrying sooner doesn't succeed. The spend cap and rate limits belong to the same tier. To raise the cap, or to restore access after reaching it, request a tier increase through your Anthropic account representative or [Anthropic support](https://support.claude.com) (see [Rate limits and quotas](#rate-limits-and-quotas)).
You can also set your own monthly spend limits below the cap, after adding at least one recipient under **Email recipients** on the Billing page:
- **Organization spend limit:** Go to [Settings \> Billing](../Other/usage-limits.md) in the [Claude Console](#using-the-claude-console) to set a monthly spend limit.
- **Workspace spend limits:** Select a workspace under [Settings \> Workspaces](../Other/usage-limits.md) and open its **Spend limits** page.
When usage reaches a limit you set, requests fail with HTTP 400 (see the [spend limit error](../Endpoints/rate-limits.md#setting-your-own-spend-limit)) until 00:00 UTC on the first day of the next month, or until you raise or remove the limit.
Spend is calculated at list prices and can take about 2 hours to reflect recent usage, so usage can exceed the cap or a limit before requests start failing. The overshoot is billed. When the tier cap or an organization spend limit stops your requests, an email notice goes to the recipients listed under **Email recipients** on the Billing page. Role-based recipients, such as all admins, aren't available on Claude Platform on AWS. The tier-cap notice also goes to the email address used at AWS Marketplace sign-up.
## Monitoring and logging
AWS CloudTrail can capture all requests to Claude Platform on AWS. Workspace, external key, compliance, vault, and webhook operations are logged as Management events by default. Inference, batch, file, skill, model, user profile, and Claude Managed Agents operations (other than vaults and webhooks) are classified as Data events and require explicit data event logging configuration, which incurs additional CloudTrail charges. See the [IAM actions reference](../Endpoints/claude-platform-on-aws-iam-actions.md#route-to-action-mapping) for the full event type classification and the [AWS CloudTrail documentation](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/) for configuration details.
### Request IDs
Each response includes two request IDs in the response headers:
- **AWS request ID (`x-amzn-requestid`):** The primary ID, indexed in CloudTrail. Use this when investigating requests through AWS tooling or when contacting AWS support.
- **Anthropic request ID (`request-id`):** The secondary ID. Use this when contacting Anthropic support.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import AnthropicAWS
client = AnthropicAWS()
response = client.messages.with_raw_response.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.headers.get("x-amzn-requestid")) # AWS request ID
print(response.headers.get("request-id")) # Anthropic request ID
message = response.parse()
print(message.content)
```
Anthropic recommends logging your activity on at least a 30-day rolling basis to understand usage patterns and investigate issues.
AWS CloudTrail is configured within your AWS account. Enabling logging does not provide AWS or Anthropic access to your content beyond what is necessary for billing and service operation.
## Migrating from Amazon Bedrock
If you currently use Claude on Bedrock, migrating to Claude Platform on AWS requires changes throughout your integration. SigV4 signing remains supported, but the signing context, base URL, API format, model IDs, SDK client and package, streaming format, request headers, and region availability all change. Claude Platform on AWS also provisions a new Anthropic organization. The following table summarizes the differences.
### What changes
The migration delta depends on which Bedrock integration you're coming from. The following table shows both the [current Bedrock integration](build-with-claude-claude-in-amazon-bedrock.md) (Messages API at `bedrock-mantle.{region}.api.aws`) and the [legacy InvokeModel integration](build-with-claude-claude-on-amazon-bedrock-legacy.md).
[TABLE]
If you're on the current Bedrock integration, the request body format is already the Messages API. The changes are the base URL, SigV4 service name, model IDs, and adding the `anthropic-workspace-id` header. If you're on the legacy InvokeModel or Converse API, you'll also rewrite the request and response shapes to the Messages API format. See [Claude on Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md) for the request-shape mapping.
### What you gain
- Typically same-day access to new models and features (see [feature limitations](#features-not-supported))
- Agent Skills for document generation (PowerPoint, Excel, Word, PDF)
- Code execution in Anthropic's managed sandbox
- Beta features through the `anthropic-beta` header (see [feature limitations](#features-not-supported))
- Claude Console for quota visibility and usage analytics
- Direct Anthropic support
- API key authentication as an alternative to SigV4 (see [API key authentication](#api-key-authentication))
### What stays the same
- AWS IAM authentication (SigV4)
- AWS as the invoicing party. The billing channel changes from native AWS service to AWS Marketplace (see [Commercial considerations](#commercial-considerations)).
- AWS commitment retirement
### Migration pitfalls
**Enable outbound web identity federation first.** If your AWS account has not previously used Claude Platform on AWS, you must [enable outbound web identity federation](#enable-outbound-web-identity-federation) once per account before making requests. Without this step, all requests fail with a federation error (see [Enable outbound web identity federation](#enable-outbound-web-identity-federation) for the exact error and remediation). This step is not required for Bedrock.
**Zero Data Retention (ZDR) is opt-in on Claude Platform on AWS.** On Bedrock, AWS is the data processor and Anthropic does not retain inference inputs or outputs. Anthropic's ZDR program does not apply there. On Claude Platform on AWS, Anthropic processes inference data as an independent data processor, and ZDR follows the first-party Claude API model: it is available on request through your Anthropic account representative. Confirm ZDR enrollment before migrating production workloads that depend on data-retention guarantees.
### Commercial considerations
- **Anthropic terms of service:** Using Claude Platform on AWS requires accepting Anthropic's Commercial Terms of Service and Usage Policy. If your organization hasn't already accepted these (for example, if you've only used Claude through Bedrock), you're prompted during account setup. See [Set up your account](#set-up-your-account).
- **Discounts and private offers:** Negotiated discounts and AWS Marketplace private offers don't transfer automatically between Bedrock and Claude Platform on AWS. Work with your Anthropic account representative to set up commercial terms for Claude Platform on AWS.
## IAM policies
Claude Platform on AWS integrates with AWS IAM for access control. You grant or deny access to specific API actions on specific workspaces using standard IAM policy syntax.
The SigV4 service name and IAM action namespace is `aws-external-anthropic`. Actions follow the pattern `aws-external-anthropic:<Action>` (for example, `aws-external-anthropic:CreateInference`).
### Example: deny batch inference
The following policy allows real-time inference while blocking batch processing:
```python
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"aws-external-anthropic:CreateInference",
"aws-external-anthropic:CountTokens",
"aws-external-anthropic:GetModel",
"aws-external-anthropic:ListModels",
"aws-external-anthropic:GetWorkspace"
],
"Resource": "arn:aws:aws-external-anthropic:*:*:workspace/*"
},
{
"Effect": "Allow",
"Action": "aws-external-anthropic:ListWorkspaces",
"Resource": "*"
},
{
"Effect": "Deny",
"Action": [
"aws-external-anthropic:CreateBatchInference",
"aws-external-anthropic:GetBatchInference",
"aws-external-anthropic:ListBatchInferences"
],
"Resource": "*"
}
]
}
```
The `GetBatchInference` action authorizes both the batch metadata route and the batch results route. Denying it blocks both reads. For a Deny-only policy suitable for ZDR-sensitive workloads, see [Feature lockdown for a ZDR-sensitive workspace](../Endpoints/claude-platform-on-aws-iam-actions.md#feature-lockdown-for-a-zdr-sensitive-workspace).
`ListWorkspaces` is account-scoped, so it appears in a separate Allow statement with `"Resource": "*"`. Specifying a workspace ARN on an account-scoped action has no effect (see [Provisioning automation](../Endpoints/claude-platform-on-aws-iam-actions.md#provisioning-automation)).
This policy assumes AWS SigV4 authentication. If the principal authenticates with an API key, also add `aws-external-anthropic:CallWithBearerToken` to the `"Resource": "*"` Allow statement. `CallWithBearerToken` is a route-less authentication-layer action that does not bind to a workspace ARN. See [Per-customer workspace isolation](../Endpoints/claude-platform-on-aws-iam-actions.md#per-customer-workspace-isolation) for the two-statement pattern.
### Managed policies
AWS provides five managed policies (`AnthropicFullAccess`, `AnthropicReadOnlyAccess`, `AnthropicInferenceAccess`, `AnthropicLimitedAccess`, and `AnthropicSelfHostedEnvironmentAccess`) for common access patterns. For the actions each policy grants, the complete list of IAM actions, the route-to-action mapping, and additional policy examples, see [IAM actions for Claude Platform on AWS](../Endpoints/claude-platform-on-aws-iam-actions.md#managed-policies).
## Next steps
[Features overview](build-with-claude-overview.md)
Explore Claude's advanced features and capabilities.
[Pricing](../../17-Billing-Plans/about-claude-pricing.md#claude-platform-on-aws-pricing)
Learn about Claude Platform on AWS pricing and Claude Consumption Unit rates.
[Model deprecations](../../20-Models/about-claude-model-deprecations.md)
As safer and more capable models launch, Anthropic regularly retires older ones. See all API deprecations, along with recommended replacements.
## Additional resources
[Claude Console](../Other/usage-limits.md)
View usage, cost, and workspaces in the Claude Console. Sign in through the AWS Console.
[Claude in Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md)
Use AWS-operated Claude if you need AWS as the sole data processor.
[AWS Marketplace](https://aws.amazon.com/marketplace)
Manage your AWS Marketplace subscription and billing.
---
## Compaction in the background - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/compaction-background
Path: 04-API-Reference/Guides/build-with-claude-compaction-background.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [SDKs, CLI, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fcompaction-background)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
[Overview](build-with-claude-compaction.md)[Compact on demand](build-with-claude-compaction-on-demand.md)[Keep recent turns](build-with-claude-compaction-keep-recent-turns.md)[Compact in the background](build-with-claude-compaction-background.md)[Keep thinking blocks valid](build-with-claude-compaction-thinking-blocks.md)[Threshold compaction](build-with-claude-compaction-threshold.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Compaction
# Compaction in the background
Copy page
Request an on-demand compaction summary while the conversation continues on its full history, then swap the block in when it arrives.
Copy page
Compaction in the background
[Beta](build-with-claude-overview.md#feature-availability)
[Beta header](../Endpoints/beta-headers.md)
compact-2026-09-04
Background compaction, often called async compaction, changes two things in the [compaction loop](build-with-claude-compaction-on-demand.md#compact-in-a-loop): the compaction request runs while the conversation continues on its full history, and the swap waits until the block arrives. [Continue from the summary](build-with-claude-compaction-on-demand.md#continue-from-the-summary) and [Handle a missing summary or an error](build-with-claude-compaction-on-demand.md#when-no-summary-comes-back) apply unchanged.
## How the swap works while work continues
The compaction request and the block it returns are the same as in the loop. Your history grows between sending the request and using its result, and the swap must leave that growth in place.
1. Send the [compaction request](build-with-claude-compaction-on-demand.md#request-a-summary) with your history as it stands, and record how many messages it held.
2. While that request runs, keep the conversation going on the full history. Append each new turn, don't edit anything already in the history, and don't start another compaction request until this one is swapped in or has failed.
3. When the response arrives with `stop_reason` `"compaction"`, drop exactly the messages you sent from the front of your history and put the returned message in their place. Every turn appended since step 1 stays after it.
4. Send the swapped history on the first request after the block arrives, so that thinking produced while the summary was being written stays valid.
For example, if the compaction request held messages 1 to 5 and the conversation gained messages 6 to 8 while it ran, after the swap your history is the block followed by messages 6 to 8.
If the response has any other `stop_reason`, no summary was produced, which counts as a failure in step 2. Keep the full history; [Handle a missing summary or an error](build-with-claude-compaction-on-demand.md#when-no-summary-comes-back) lists the causes and what to do for each.
## Request the summary in the background
The compaction request counts against your rate limits like any other request, and while it runs your application has two requests open at once. The conversation keeps growing on its full history until the swap, so start the compaction request while the context window still has room for the turns that arrive meanwhile.
The following program is the loop from [Compact in a loop](build-with-claude-compaction-on-demand.md#compact-in-a-loop) with the compaction request taken off the conversation's path. It has no PHP version, because the example depends on running two requests at once. The highlighted lines show where it differs from the loop, and the following list takes them in the order the program runs them.
Python
TypeScript
C#
Go
Java
Ruby
```python
from concurrent.futures import Future, ThreadPoolExecutor
import anthropic
from anthropic.types.beta import BetaMessage, BetaMessageParam
client = anthropic.Anthropic()
executor = ThreadPoolExecutor(max_workers=1)
# Set this near your real input budget. It is low here so a short conversation compacts.
COMPACT_AT_TOKENS = 2500
SYSTEM = "You help design a recipe app's data model. Keep answers short."
QUESTIONS = [
"What are the main entities in the data model?",
"Which fields should Recipe have?",
"Which fields should Ingredient have?",
"Which fields should RecipeIngredient have?",
"Which fields should Step have?",
"Which indexes should these tables have?",
"Which fields should be required?",
"Which fields should have default values?",
]
def swap_in(history: list[BetaMessageParam], summary: BetaMessage, sent: int) -> None:
if summary.stop_reason == "compaction":
# Replace exactly the messages the compaction request held.
# Later turns stay after the block.
history[:sent] = [{"role": "assistant", "content": summary.content}]
print(f"Swapped {sent} messages")
history: list[BetaMessageParam] = []
pending: Future[BetaMessage] | None = None
sent = 0
for turn, question in enumerate(QUESTIONS, start=1):
if pending is not None and pending.done():
swap_in(history, pending.result(), sent)
pending = None
history.append({"role": "user", "content": question})
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=8192,
system=SYSTEM,
betas=["compact-2026-09-04"],
messages=history,
)
history.append({"role": "assistant", "content": response.content})
# The next request sends this reply too, so count it.
conversation_tokens = response.usage.input_tokens + response.usage.output_tokens
if (
conversation_tokens > COMPACT_AT_TOKENS
and turn < len(QUESTIONS)
and pending is None
):
sent = len(history)
pending = executor.submit(
client.beta.messages.create,
model="claude-opus-5-5",
max_tokens=4096,
system=SYSTEM,
betas=["compact-2026-09-04"],
messages=history.copy(),
compaction={"type": "summarize"},
)
# Swap in a summary that is still on its way before you save
# or continue the conversation.
if pending is not None:
swap_in(history, pending.result(), sent)
executor.shutdown()
```
- **Deciding when to compact:** The size check also requires that no compaction request is pending.
- **Starting the request:** Where the loop waits for the compaction response, this version records how many messages the history holds, starts the request on a copy of the history with each language's own concurrency tool, and goes on to the next turn without waiting.
- **Checking for the result:** At the top of each turn, the program checks whether the pending request has finished. If it has, the program makes the swap before it sends that turn's request.
- **Making the swap:** Where the loop replaces the whole history with the returned message, this version's swap function replaces only the messages the request held, counted from the front, and keeps everything appended since.
- **Ending the loop:** If the compaction request is still pending when the loop ends, the program waits for it and makes the swap, so a summary that is still on its way isn't lost before you save or continue the conversation.
The `stop_reason` check is unchanged from the loop: a response without a block leaves the history as it was. Because nothing is pending any more, the program can then start a new compaction request.
## Keep thinking valid while the summary is built
Turns that arrive while the summary is being written are kept turns. If you send thinking blocks back on a model with [preserved thinking](build-with-claude-preserved-thinking.md), the thinking in those turns stays valid only while the [conditions for kept thinking](build-with-claude-compaction-thinking-blocks.md#conditions-for-kept-thinking-to-stay-valid) hold.
## Compatibility
Supported models
- Fable 5 and 5.1
- Mythos 5, 5.1, and Preview
- Opus 4.6, 4.7, 4.8, 5, and 5.5
- Sonnet 4.6, 5, and 5.5
Supported platforms
- Claude APIBeta
- Claude Platform on AWSBeta
- Google CloudBeta
- Microsoft FoundryBeta
---
## Compaction that keeps recent turns - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/compaction-keep-recent-turns
Path: 04-API-Reference/Guides/build-with-claude-compaction-keep-recent-turns.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [SDKs, CLI, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fcompaction-keep-recent-turns)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
[Overview](build-with-claude-compaction.md)[Compact on demand](build-with-claude-compaction-on-demand.md)[Keep recent turns](build-with-claude-compaction-keep-recent-turns.md)[Compact in the background](build-with-claude-compaction-background.md)[Keep thinking blocks valid](build-with-claude-compaction-thinking-blocks.md)[Threshold compaction](build-with-claude-compaction-threshold.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Compaction
# Compaction that keeps recent turns
Copy page
Summarize the older turns of a conversation with on-demand compaction and send the most recent turns after the summary, word for word.
Copy page
Compaction that keeps recent turns
[Beta](build-with-claude-overview.md#feature-availability)
[Beta header](../Endpoints/beta-headers.md)
compact-2026-09-04
Keep-tail compaction keeps the last few turns of a conversation word for word after the summary. It changes two things in the [compaction loop](build-with-claude-compaction-on-demand.md#compact-in-a-loop): which messages go into the compaction request, and what you send after the block. Everything in [Continue from the summary](build-with-claude-compaction-on-demand.md#continue-from-the-summary) applies unchanged.
## Choose which turns to keep
No parameter sets which turns are kept. You pick a cut point in your history: the messages before it go into the compaction request, and the messages from it on are kept.
Kept turns go back to Claude at full length, so the more you keep, the less room the compaction frees.
Put the cut where no tool call is left open, with each tool call and its result on the same side. If the messages you send end in an `assistant` turn whose tool call has no result yet, the API rejects the compaction request.
## Compact the older turns and send the rest after the block
To keep a tail of recent turns word for word, leave those turns out of the compaction request. The API summarizes every message it is sent, so send only the older turns, then put the block in front of the turns you kept.
Send the kept turns exactly as they are in your history, thinking blocks included. Both requests carry the beta header, as in [Request a summary](build-with-claude-compaction-on-demand.md#request-a-summary).
In the following example, the history holds two turns, and the cut keeps the second. The compaction request carries the first turn:
```python
{
"model": "claude-opus-5-5",
"max_tokens": 4096,
"messages": [
{
"role": "user",
"content": "I am building a recipe app. Help me name the main entities in the data model."
},
{
"role": "assistant",
"content": "Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe."
}
],
"compaction": { "type": "summarize" }
}
```
The next request sends the returned block first, then the kept turn exactly as it was, then the new `user` message. [Continue from the summary](build-with-claude-compaction-on-demand.md#continue-from-the-summary) shows a request that starts with a block.
The following program is the loop from [Compact in a loop](build-with-claude-compaction-on-demand.md#compact-in-a-loop), changed to keep the last two turns. The highlighted lines show where it differs from the loop.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.types.beta import BetaMessageParam
client = anthropic.Anthropic()
# Set this near your real input budget. It is low here so a short conversation compacts.
COMPACT_AT_TOKENS = 2500
SYSTEM = "You help design a recipe app's data model. Keep answers short."
KEEP_TURNS = 2
QUESTIONS = [
"What are the main entities in the data model?",
"Which fields should Recipe have?",
"Which fields should Ingredient have?",
"Which fields should RecipeIngredient have?",
"Which fields should Step have?",
"Which indexes should these tables have?",
"Which fields should be required?",
"Which fields should have default values?",
]
history: list[BetaMessageParam] = []
for turn, question in enumerate(QUESTIONS, start=1):
history.append({"role": "user", "content": question})
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=8192,
system=SYSTEM,
betas=["compact-2026-09-04"],
messages=history,
)
history.append({"role": "assistant", "content": response.content})
# The next request sends this reply too, so count it.
conversation_tokens = response.usage.input_tokens + response.usage.output_tokens
if conversation_tokens > COMPACT_AT_TOKENS and KEEP_TURNS < turn < len(QUESTIONS):
# A turn is one user message and one assistant reply,
# so the kept turns start with a user message.
split = -2 * KEEP_TURNS
older, recent = history[:split], history[split:]
summary = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
system=SYSTEM,
betas=["compact-2026-09-04"],
messages=older,
compaction={"type": "summarize"},
)
if summary.stop_reason == "compaction":
history = [{"role": "assistant", "content": summary.content}, *recent]
print(f"Kept {len(recent) // 2} turns after the block")
```
- **Picking the cut:** The program keeps the last two turns, where a turn is one `user` message and the reply to it. It splits the history four messages from the end, so the kept turns start with a `user` message.
- **Deciding when to compact:** The size check also requires that the conversation has more turns than the program keeps, so the older part is never empty.
- **The compaction request:** Where the loop sends the whole history, this version sends only the older messages.
- **The swap:** Where the loop replaces the whole history with the returned message, this version's new history is the returned message followed by the kept turns.
The `stop_reason` check and every request after the swap are unchanged from the loop.
## Keep thinking valid in the kept turns
If you send thinking blocks back on a model with [preserved thinking](build-with-claude-preserved-thinking.md), the thinking in the kept turns stays valid only while the [conditions for kept thinking](build-with-claude-compaction-thinking-blocks.md#conditions-for-kept-thinking-to-stay-valid) hold, and one of them limits where the cut can fall.
The program's cut, between a reply and the next `user` message, meets that condition. So does a cut at the end of a request you already made: compact exactly that request's `messages`, and keep everything your history has gained since.
## Compatibility
Supported models
- Fable 5 and 5.1
- Mythos 5, 5.1, and Preview
- Opus 4.6, 4.7, 4.8, 5, and 5.5
- Sonnet 4.6, 5, and 5.5
Supported platforms
- Claude APIBeta
- Claude Platform on AWSBeta
- Google CloudBeta
- Microsoft FoundryBeta
---
## Compaction on demand - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand
Path: 04-API-Reference/Guides/build-with-claude-compaction-on-demand.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [SDKs, CLI, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fcompaction-on-demand)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
[Overview](build-with-claude-compaction.md)[Compact on demand](build-with-claude-compaction-on-demand.md)[Keep recent turns](build-with-claude-compaction-keep-recent-turns.md)[Compact in the background](build-with-claude-compaction-background.md)[Keep thinking blocks valid](build-with-claude-compaction-thinking-blocks.md)[Threshold compaction](build-with-claude-compaction-threshold.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Compaction
# Compaction on demand
Copy page
Ask Claude to summarize a conversation when your application chooses, then continue from the summary.
Copy page
Compaction on demand
[Beta](build-with-claude-overview.md#feature-availability)
[Beta header](../Endpoints/beta-headers.md)
compact-2026-09-04
With on-demand compaction, your application decides when a conversation is summarized: you send one request with the `compaction` parameter, and Claude returns a summary in place of a reply.
## How on-demand compaction works
A compaction request is separate from your conversation turns. You send the conversation as it stands with the `compaction` parameter, and the response contains a single `compaction` block. The block holds the summary as text you can read, and a signature. Send it in future requests exactly as it came.
From then on the block takes the place of the messages it summarizes. It goes first in `messages`, the summarized messages are removed, and your next turn follows it. Claude sees the summary where those messages were.
## Request a summary
Send the `compact-2026-09-04` beta header on the request that asks for the summary and on every later request that carries the signed block. To check whether a model supports on-demand compaction, call the [Models API](../Endpoints/http-beta-models-list.md) with the beta header and read each model's `capabilities.compaction`. You can't combine `compaction` with `context_management` on one request.
Send the conversation as it stands with `"compaction": {"type": "summarize"}`. The API summarizes every message in the request once, generates no reply after it, and returns the block alone with `stop_reason` `"compaction"`. Send the same `system` prompt and `tools` that you use for the rest of the conversation. The summarizer reads them, and if you keep turns after the block on a model with [preserved thinking](build-with-claude-preserved-thinking.md), the thinking in those turns stays valid only if `system` and `tools` match. The conversation in this example has no `system` prompt or tools, so the request sends neither:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.types.beta import BetaMessageParam
client = anthropic.Anthropic()
history: list[BetaMessageParam] = [
{
"role": "user",
"content": "I am building a recipe app. Help me name the main entities in the data model.",
},
{
"role": "assistant",
"content": "Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe.",
},
{"role": "user", "content": "Good. Now suggest field names for Recipe."},
]
response = client.beta.messages.create(
model="claude-opus-5-5",
# max_tokens caps the whole call, including any thinking, so allow several thousand tokens.
max_tokens=4096,
betas=["compact-2026-09-04"],
messages=history,
compaction={"type": "summarize"},
)
print(f"Stop reason: {response.stop_reason}")
```
Response
```python
{
"id": "msg_013Zva2CMHLNnXjNJJKqJ2EF",
"type": "message",
"role": "assistant",
"model": "claude-opus-5-5",
"content": [
{
"type": "compaction",
"content": "Summary of the conversation: the user is designing the data model for a recipe app. The entities agreed so far are Recipe, Ingredient, Step, and RecipeIngredient, which holds the quantity and unit. The user then asked for field names for Recipe.",
"signature": "EuYBCkQY..."
}
],
"stop_reason": "compaction",
"usage": {
"input_tokens": 0,
"output_tokens": 0,
"iterations": [{ "type": "compaction", "input_tokens": 144, "output_tokens": 276 }]
}
}
```
The summarization call uses the request's model, `system`, `tools`, thinking settings, and `max_tokens`. The summarizer reads the tool definitions but never runs a tool, and the response carries no thinking. `max_tokens` caps the whole call, including any thinking the model does before it writes the summary, so allow several thousand tokens. [Count compaction usage](#understanding-usage) shows how the call is billed.
If the last `assistant` turn ends in a tool call with no result yet, the API rejects the request. Send that turn's tool results first. Also leave out `stop_sequences`, structured-output `output_config.format`, and a `tool_choice` of type `any` or `tool`. They would do nothing on a summarization call, and the API rejects them. The conversation must still fit the model's context window, so compact before you outgrow it, not after.
When you stream the response, the block arrives whole. You get one `content_block_start` event carrying the complete block, then `content_block_stop`, with no `content_block_delta` events. `ping` events can arrive before or between them.
## Continue from the summary
In your history, replace the messages you sent with the returned assistant message. Keep the `compaction` block exactly as the API returned it, including its `signature`. Any turns taken after you sent the compaction request follow the block unchanged, which is what [Compaction in the background](build-with-claude-compaction-background.md) builds on. Send the block first on every later request, with the beta header:
```python
{
"model": "claude-opus-5-5",
"max_tokens": 2048,
"messages": [
{
"role": "assistant",
"content": [
{
"type": "compaction",
"content": "Summary of the conversation: the user is designing the data model for a recipe app. The entities agreed so far are Recipe, Ingredient, Step, and RecipeIngredient, which holds the quantity and unit. The user then asked for field names for Recipe.",
"signature": "EuYBCkQY..."
}
]
},
{
"role": "assistant",
"content": "For Recipe, use title, description, servings, prep_minutes, and cook_minutes. Add created_at and updated_at timestamps."
},
{ "role": "user", "content": "Now do the same for Ingredient." }
]
}
```
This example continues the request sample, which ended on a `user` turn; the diagram shows the simpler case, where no turn is taken while the summary is written. Here the second `assistant` message is the reply to the last summarized `user` turn. It arrived while the summary was being written, so it was not among the messages summarized. Two `assistant` messages in a row are fine here, because the block still comes first.
The API puts the summary where the block stands and passes every later message to Claude unchanged. Follow these rules:
- Put the block first in `messages`, either as an `assistant` message of its own or as the first content block of the first message, whether that is a `user` or `assistant` message.
- Remove the summarized messages. If any remain in front of the block, the request returns a 400 error (`compaction_block_misplaced`).
- Send exactly one `compaction` block per request, on every later request.
Two mistakes in the swap raise no error. If summarized messages remain after the block, the API sends them to Claude again. If a later request leaves the block out, Claude gets no summary.
Threshold compaction works the other way around: its block follows the messages it summarizes, and the API drops them for you. See [Passing compaction blocks back](build-with-claude-compaction-threshold.md#passing-compaction-blocks-back).
In Python, use `client.beta.messages`, as the samples on this page do. If you call `client.messages` and serialize blocks yourself, use `to_dict()` or `model_dump(exclude_none=True)`: a plain `model_dump()` adds `citations: null` and `text: null` to the block, and the API rejects it.
If you keep turns after the block and send their thinking blocks back, the conditions that keep that thinking valid are on [Compaction and preserved thinking](build-with-claude-compaction-thinking-blocks.md).
### Compact again
To compact a conversation that already starts with a block, send `compaction` again. The new block summarizes the old summary and everything after it. From then on, send only the newest block.
## Compact in a loop
After each turn, the loop adds the last response's input and output tokens, because the next request sends the reply too. When that total passes a limit and another turn is still to come, it sends a compaction request with the same model and `system` prompt, checks `stop_reason`, replaces its history with the returned message, and prints the turn it compacted before. The sample's limit of 2,500 tokens is deliberately low, so that a short conversation compacts. Set yours near your real input budget.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.types.beta import BetaMessageParam
client = anthropic.Anthropic()
# Set this near your real input budget. It is low here so a short conversation compacts.
COMPACT_AT_TOKENS = 2500
SYSTEM = "You help design a recipe app's data model. Keep answers short."
QUESTIONS = [
"What are the main entities in the data model?",
"Which fields should Recipe have?",
"Which fields should Ingredient have?",
"Which fields should RecipeIngredient have?",
"Which fields should Step have?",
"Which indexes should these tables have?",
"Which fields should be required?",
"Which fields should have default values?",
]
history: list[BetaMessageParam] = []
for turn, question in enumerate(QUESTIONS, start=1):
history.append({"role": "user", "content": question})
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=8192,
system=SYSTEM,
betas=["compact-2026-09-04"],
messages=history,
)
history.append({"role": "assistant", "content": response.content})
# The next request sends this reply too, so count it.
conversation_tokens = response.usage.input_tokens + response.usage.output_tokens
if conversation_tokens > COMPACT_AT_TOKENS and turn < len(QUESTIONS):
summary = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
system=SYSTEM,
betas=["compact-2026-09-04"],
messages=history,
compaction={"type": "summarize"},
)
if summary.stop_reason == "compaction":
history = [{"role": "assistant", "content": summary.content}]
print(f"Compacted before turn {turn + 1}")
```
The check on `stop_reason` comes before the code looks for the block; [Handle a missing summary or an error](#when-no-summary-comes-back) says why. The history is replaced, not appended to: the returned message replaces every message the request carried, under the rules in [Continue from the summary](#continue-from-the-summary). When no summary comes back, the loop keeps its history and asks again after the next turn.
The SDK [tool runner](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md) in Python, TypeScript, C#, Go, Java, PHP, and Ruby can send the compaction request for you. When you decide to compact, call `compact_before_next_turn()` on the runner. Once the current turn and its tool calls finish, the runner sends the compaction request and replaces its history with the returned message. Create the runner with the `compact-2026-09-04` beta, because the runner doesn't add it.
The runner builds the compaction request from its own parameters and leaves `context_management` out. It also leaves out `stop_sequences`, a `tool_choice` of type `any` or `tool`, and a structured-output `output_config.format`, which the API rejects on a compaction request. [Request a summary](#request-a-summary) explains why. The runner sends them again on its later requests. SDK versions before Python 1.8.0, TypeScript 0.128.0, C# 12.50.0, Go 1.75.0, and Java 2.65.0 send them on the compaction request too. On those versions, a runner that sets any of these parameters gets a 400 error. The runner sends a [task budget](build-with-claude-task-budgets.md) unchanged. If `output_config.task_budget` sets `remaining`, the compaction request returns a 400 error, so leave `remaining` unset, as [Limits and interactions with other features](#how-it-fits-with-the-rest-of-the-api) says. The runner refuses to compact while its `context_management` has a compaction edit, so use one kind of compaction on a runner.
### When to compact
You can send a compaction request after any completed turn, so your code decides when.
To estimate how large the next request will be, add `input_tokens` and `output_tokens` from the last response's `usage`, as the loop does. With [prompt caching](build-with-claude-prompt-caching.md#tracking-cache-performance), `input_tokens` counts only the tokens after the last cache breakpoint, so add `cache_read_input_tokens` and `cache_creation_input_tokens` as well. You can also send the same messages to the [token counting](build-with-claude-token-counting.md) endpoint.
Compare that number with a limit you choose, below the model's [context window](build-with-claude-context-windows.md).
## Write your own summarization prompt
Without `instructions`, the API uses its own summarization prompt. A non-blank `instructions` string (up to 16,384 characters) replaces that prompt entirely. For example:
```python
{
"compaction": {
"type": "summarize",
"instructions": "Summarize this recipe app design conversation. Preserve every entity and field name agreed so far, and the user's latest open request. Do not call tools; respond with the summary text only."
}
}
```
The summarizer reads the whole conversation, earlier thinking included, with or without `instructions`. In your `instructions`, say what the summary must retain and tell the model not to call tools. The summarization call runs under the same safeguards as any other request.
## Handle a missing summary or an error
A summary is produced only when the summarization call ends normally with text and no tool call. Otherwise, the response is still a 200 with empty `content`, so check `stop_reason` before you look for the block. The call is still billed and reported in `usage.iterations`, with zero usage when no call could be made. The `stop_reason` is the one the summarization call ended with. In every case you can continue without a summary and compact later.
| `stop_reason` | Cause | What to do |
|:----------------------------------|:--------------------------------------------------------|:------------------------------------------------------------------|
| `"max_tokens"` | The summary was cut off. | Resend with a larger `max_tokens`. |
| `"model_context_window_exceeded"` | There was no room for the summarization prompt. | Resend with shorter `instructions` or fewer messages. |
| `"tool_use"` | The model called a tool instead of writing the summary. | Resend with `instructions` that tell the model not to call tools. |
| `"refusal"` | The request was declined. | Continue without a summary. |
| `"end_turn"` | The call returned no text. | Continue without a summary. |
The summarization call is subject to the same safeguards as your other requests. After a `"refusal"`, [`stop_details`](build-with-claude-handling-stop-reasons.md#refusal) identifies the policy category behind it.
### Errors
A compaction request, or a request that carries a block, can also fail outright. Most 400 errors have a message that says what to remove or resend. Some also carry an `error.details.error_code` that starts with `compaction_`. Parameter errors, such as a field that can't be combined with `compaction`, carry the message only.
| Error | Cause | What to do |
|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------|
| 529 `overloaded_error`, `error.details.error_code` `compaction_unavailable` | A transient server problem while producing a block, or while reading one you sent back. | Retry the request. |
| 400 `compaction_block_misplaced` | Summarized messages remain in front of the block. | Remove them, so the block comes first in `messages`. |
| 400 `compaction_signature_invalid` or `compaction_content_mismatch` | The block's `signature` or `content` was changed after the API returned it. | Send the block exactly as returned, including its `signature`. |
| 400 | The request carries more than one `compaction` block. | Send exactly one, the newest. |
| 400 | The last `assistant` turn ends in a tool call with no result yet. | Send that turn's tool results, then compact. |
| 400 `compaction_nothing_to_summarize` | `messages` has no `user` or `assistant` content, for example an empty list. | Send at least one `user` or `assistant` message. |
| 400 on the compaction request, with a message that says the `compaction` parameter `requires anthropic-beta: compact-2026-09-04` | The compaction request left out the beta header. | Add the beta header; see [Request a summary](#request-a-summary). |
| 400 on a later request that carries the block: a validation error that says `compaction` is not one of the expected content block types. The message doesn't mention the header | That request left out the beta header. | Add the beta header to every request that carries the block; see [Request a summary](#request-a-summary). |
| 400 validation error, such as `messages.0.content.0.compaction.citations: Extra inputs are not permitted` | A block was sent back with fields the API didn't return, such as `citations: null`. | Send the block exactly as returned; see [Continue from the summary](#continue-from-the-summary). |
## Count compaction usage
The summarization call is billed and rate-limited like any other request, and `usage.iterations` reports it as the `compaction` entry. The top-level `input_tokens` and `output_tokens` are zero because no reply was generated. To count what a conversation consumed, sum across `usage.iterations`, not the top-level fields. Sending a block back on later requests adds no compaction cost.
You have a working loop that compacts a conversation and handles a missing summary. Two pages change how it runs, and you can combine them: [Compaction that keeps recent turns](build-with-claude-compaction-keep-recent-turns.md) keeps the last turns word for word, and [Compaction in the background](build-with-claude-compaction-background.md) lets the conversation continue while the summary is written. [Compaction and preserved thinking](build-with-claude-compaction-thinking-blocks.md) applies if you send thinking blocks back and do either.
## Limits and interactions with other features
- **Threshold compaction and context editing.** You can't send `compaction` and `context_management` on the same request. Threshold compaction (`compact_20260112`) can't run on a request that carries a signed block.
- **Prompt caching.** `cache_control` on the block places a breakpoint after the summary.
- **Mid-conversation system messages and tool changes.** `role: "system"` messages inside the summarized range are summarized too, so their text instructions stop applying once the block replaces them. If an instruction still matters, state it again in a `role: "system"` message. Send that message right after your next new `user` turn, and leave it in your history from then on. For [tool changes](build-with-claude-mid-conversation-system-messages.md#mid-conversation-tool-changes), and for where that message goes when you keep turns after the block, see [Change the system prompt or tools](build-with-claude-compaction-thinking-blocks.md#change-the-system-prompt-or-tools).
- **Task budgets.** Don't send the `remaining` value of a [task budget](build-with-claude-task-budgets.md) (`output_config.task_budget.remaining`) with `compaction` or on requests that carry the block. Doing so returns a 400 error.
- **Token counting.** The [token counting](build-with-claude-token-counting.md) endpoint ignores the `compaction` parameter.
- **Content the summary can't carry.** Images, documents, `container_upload` blocks, and fetched URLs inside the summarized messages are gone once the block replaces them. Restate or re-upload anything a later turn still needs.
## Compatibility
Supported models
- Fable 5 and 5.1
- Mythos 5, 5.1, and Preview
- Opus 4.6, 4.7, 4.8, 5, and 5.5
- Sonnet 4.6, 5, and 5.5
Supported platforms
- Claude APIBeta
- Claude Platform on AWSBeta
- Google CloudBeta
- Microsoft FoundryBeta
---
## Compaction and preserved thinking - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks
Path: 04-API-Reference/Guides/build-with-claude-compaction-thinking-blocks.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [SDKs, CLI, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fcompaction-thinking-blocks)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
[Overview](build-with-claude-compaction.md)[Compact on demand](build-with-claude-compaction-on-demand.md)[Keep recent turns](build-with-claude-compaction-keep-recent-turns.md)[Compact in the background](build-with-claude-compaction-background.md)[Keep thinking blocks valid](build-with-claude-compaction-thinking-blocks.md)[Threshold compaction](build-with-claude-compaction-threshold.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Compaction
# Compaction and preserved thinking
Copy page
When thinking blocks in turns kept after on-demand compaction stay valid on models with preserved thinking, and how to check.
Copy page
Compaction and preserved thinking
[Beta](build-with-claude-overview.md#feature-availability)
[Beta header](../Endpoints/beta-headers.md)
compact-2026-09-04
Skip this page unless you send thinking blocks back to a model with [preserved thinking](build-with-claude-preserved-thinking.md) and keep turns after the compaction block. Kept turns are the turns that follow the block: recent turns you left out of the compaction request, as in [Compaction that keeps recent turns](build-with-claude-compaction-keep-recent-turns.md), or turns that arrived while the summary was being written, as in [Compaction in the background](build-with-claude-compaction-background.md).
Models with preserved thinking check earlier thinking blocks against the conversation that produced them. A summary replaces part of that conversation, but the check accepts the swap when the API wrote the summary, so the thinking in kept turns can stay valid.
## Conditions for kept thinking to stay valid
The thinking blocks in kept turns stay valid while all of these hold:
- **The compaction request runs on a model with preserved thinking.** This condition covers every compaction request since a thinking block was produced, not only the most recent one. One way to meet it is to send every compaction request to the model the conversation uses.
- **The kept turns directly follow the summarized messages, and you send them unchanged.** Send each kept message exactly as it is in your history. Don't skip or add a message between the last summarized message and the first kept one. The first kept message must also have a different role from the last summarized message, and it can't be a mid-conversation `role: "system"` message. Otherwise, the API merges it into the last summarized message. One way to get the first kept message right is to compact exactly the `messages` of a request you already sent. The kept turns then start with Claude's reply to it.
- **`system` and the `tools` not marked `defer_loading: true` don't change.** They are the same on the compaction request as on the requests that produced the kept thinking, and they stay the same on the requests that follow. [Change the system prompt or tools](#change-the-system-prompt-or-tools) covers how to change them safely.
If a condition doesn't hold, nothing fails when you compact, and the API accepts the block on later requests either way. The failure comes on the first later request that sends the kept thinking where the API enforces the check: a 400 error by default, or dropped thinking blocks if the request sets `thinking.block_binding.prefix_mismatch_behavior` to `"drop_block"`. In the Message Batches API, an item that leaves the field unset doesn't fail. Where the check applies by default, the API drops the blocks instead. [What the API does with an invalid block](build-with-claude-preserved-thinking.md#mismatch-behavior) describes both outcomes, and [When the API enforces the check](build-with-claude-preserved-thinking.md#enforcement) says which requests are checked.
## Compact again without breaking older thinking
You can [compact again](build-with-claude-compaction-on-demand.md#compact-again) and keep turns: the new block covers the old summary and every message that follows it in the compaction request, and any turns you leave out of that request are kept turns of the new block.
The first of the [conditions for kept thinking](#conditions-for-kept-thinking-to-stay-valid) counts every compaction since a thinking block was produced, so a turn that you keep through two compactions needs both to have run on a model with preserved thinking.
Compactions from before a thinking block was produced don't count against it. Thinking produced after a block is in place is bound to that block, and it stays valid through later compactions that meet the conditions.
## Change the system prompt or tools
A later request can use a different `system`, different `tools`, or a different model than the compaction request, and the API still accepts the block. Such a change can invalidate the thinking in the kept turns, but it has no other effect.
To change `system` or `tools` without invalidating any kept thinking, compact the whole conversation first, so no turns are kept. Then change them on the next request.
To add an instruction or change the available tools without touching `system` or `tools`, append the change to `messages`, as described in [Make changes without editing the prefix](build-with-claude-preserved-thinking.md#replace-prefix-edits).
Mid-conversation system messages inside the summarized turns are summarized too, so their text instructions stop applying after the swap. To keep one in force, state it again in a `role: "system"` message directly after the first new `user` turn that follows the kept turns. Tool changes inside those turns carry over on their own when the compaction request also carries `inline-tools-2026-09-15`: the returned block records their net effect in its `tool_changes` field, so send the block back unmodified. If the block has no `tool_changes` field, restate those tool changes the same way. A system message placed between the block and the kept turns breaks their thinking.
## Check that the kept thinking held
The compaction response doesn't say whether the kept thinking holds. The first request after the swap does. To check in your tests:
1. Have a short conversation with thinking on. Use a model on which the API runs the check (see [When the API enforces the check](build-with-claude-preserved-thinking.md#enforcement)), and use it for every step, because a model that can't read a thinking block drops it with no error.
2. Compact the older turns, and keep at least one turn that holds a thinking block.
3. Send the next request, with the block first, then the kept turn, then a new `user` message, and with `thinking.block_binding.prefix_mismatch_behavior` set to `"error"`.
4. Read the result. A 200 response whose `input_transformations` array is empty means no thinking block failed the check or was dropped. A 400 error that says the block is bound to a different conversation means one did. The message starts with the path of the first block that failed, and [What the API does with an invalid block](build-with-claude-preserved-thinking.md#mismatch-behavior) shows it in full.
The `prefix_mismatch_behavior` field needs the `thinking-binding-controls-2026-08-01` beta header in addition to [the `compact-2026-09-04` beta header](build-with-claude-compaction-on-demand.md#request-a-summary). Setting the field also opts the request into the check on accounts where the check isn't on by default.
The following program runs the four steps. It prints how many thinking blocks the kept turn holds and how many entries `input_transformations` has; no entries means the kept thinking held:
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.types.beta import BetaMessageParam, BetaThinkingConfigParam
client = anthropic.Anthropic()
# Claude Fable 5.1 is the first model that checks sent-back thinking against the conversation.
MODEL = "claude-fable-5-1"
BETAS = ["compact-2026-09-04", "thinking-binding-controls-2026-08-01"]
SYSTEM = "You help plan a recipe app's release. Keep answers short."
# With "error", a thinking block that fails the check makes the request fail with a 400.
THINKING: BetaThinkingConfigParam = {
"type": "adaptive",
"block_binding": {"prefix_mismatch_behavior": "error"},
}
# 1. Have a short conversation with thinking on.
history: list[BetaMessageParam] = [
{"role": "user", "content": "What are the main entities in the app's data model?"}
]
first = client.beta.messages.create(
model=MODEL,
max_tokens=8192,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history,
)
history += [
{"role": "assistant", "content": first.content},
{
"role": "user",
"content": "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?",
},
]
second = client.beta.messages.create(
model=MODEL,
max_tokens=8192,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history,
)
history.append({"role": "assistant", "content": second.content})
thinking_blocks = sum(block.type == "thinking" for block in second.content)
print(f"Thinking blocks in the kept turn: {thinking_blocks}")
# 2. Summarize the first turn. The second turn stays out of the request.
summary = client.beta.messages.create(
model=MODEL,
max_tokens=4096,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history[:2],
compaction={"type": "summarize"},
)
if summary.stop_reason != "compaction":
raise SystemExit(f"No summary: {summary.stop_reason}")
# 3. Put the block in front of the kept turn and ask the next question.
history = [
{"role": "assistant", "content": summary.content},
*history[2:],
{"role": "user", "content": "Which day should the release go out?"},
]
third = client.beta.messages.create(
model=MODEL,
max_tokens=8192,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history,
)
# 4. A 200 with no dropped blocks means the kept thinking held.
print(f"Dropped thinking blocks: {len(third.input_transformations)}")
```
Output
``` block
Thinking blocks in the kept turn: 1
Dropped thinking blocks: 0
```
In production, `"drop_block"` keeps requests succeeding when a condition doesn't hold, and reports each dropped block in `input_transformations` with `reason: "prefix_binding_mismatch"`. An entry whose `path` falls in a kept turn means that turn's thinking didn't hold. [What the API does with an invalid block](build-with-claude-preserved-thinking.md#mismatch-behavior) describes what is dropped and says how to alert on it.
## Compatibility
Supported models
- Fable 5 and 5.1
- Mythos 5, 5.1, and Preview
- Opus 4.6, 4.7, 4.8, 5, and 5.5
- Sonnet 4.6, 5, and 5.5
Supported platforms
- Claude APIBeta
- Claude Platform on AWSBeta
- Google CloudBeta
- Microsoft FoundryBeta
---
## Compaction at a token threshold - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/compaction-threshold
Path: 04-API-Reference/Guides/build-with-claude-compaction-threshold.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [SDKs, CLI, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fcompaction-threshold)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
[Overview](build-with-claude-compaction.md)[Compact on demand](build-with-claude-compaction-on-demand.md)[Keep recent turns](build-with-claude-compaction-keep-recent-turns.md)[Compact in the background](build-with-claude-compaction-background.md)[Keep thinking blocks valid](build-with-claude-compaction-thinking-blocks.md)[Threshold compaction](build-with-claude-compaction-threshold.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Compaction
# Compaction at a token threshold
Copy page
Have the API summarize older context automatically, inside an ordinary request, when the conversation reaches a token threshold you set.
Copy page
Compaction at a token threshold
[Beta](build-with-claude-overview.md#feature-availability)
[Beta header](../Endpoints/beta-headers.md)
compact-2026-01-12
[ZDR](../Other/manage-claude-api-and-data-retention.md)
Eligible
excludes [Covered Models](../Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements)
Threshold compaction is the automatic kind of compaction: you set a token threshold on your ordinary requests, and the API summarizes older context partway through a request once the threshold is reached. It is supported alongside on-demand compaction, where you decide when the summary is written (see [Compaction on demand](build-with-claude-compaction-on-demand.md)). To choose between them, see [Choose how to compact](build-with-claude-compaction.md#choose-how-to-compact).
Compaction extends the effective context length for long-running conversations and tasks by automatically summarizing older context when approaching the context window limit. It also keeps the active context small: as a conversation grows, response quality degrades, so compaction replaces older content with a concise summary.
For a deeper look at why long contexts degrade and how compaction helps, see [Effective context engineering](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents).
This is ideal for:
- Chat-based, multi-turn conversations where you want users to use one chat for a long period of time
- Task-oriented prompts that require a lot of follow-up work (often tool use) that might exceed the context window
## How compaction works
When compaction is enabled, Claude automatically summarizes your conversation when it reaches the configured token threshold. The API:
1. Detects when input tokens reach your specified trigger threshold.
2. Generates a summary of the current conversation.
3. Creates a `compaction` block containing the summary.
4. Continues the response with the compacted context.
On subsequent requests, append the response to your messages. The API automatically drops all content blocks prior to the `compaction` block, continuing the conversation from the summary.
## Basic usage
Enable compaction by adding the `compact_20260112` strategy to `context_management.edits` in your Messages API request.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Help me build a website"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
# Append the response (including any compaction block) to continue the conversation
messages.append({"role": "assistant", "content": response.content})
```
## Parameters
| Parameter | Type | Default | Description |
|:-------------------------|:--------|:--------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
| `type` | string | Required | Must be `"compact_20260112"` |
| `trigger` | object | `{"type": "input_tokens", "value": 150000}` | When to trigger compaction. `input_tokens` is the only supported trigger type. `value` must be at least 50,000 tokens. |
| `pause_after_compaction` | boolean | `false` | Whether to pause after generating the compaction summary |
| `instructions` | string | `null` | Custom summarization prompt. Completely replaces the default prompt when provided. |
### Trigger configuration
Configure when compaction triggers using the `trigger` parameter:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 150000},
}
]
},
)
```
### Custom summarization instructions
The default summarization prompt varies by model. Each default instructs Claude to write a summary inside `<summary></summary>` tags with the information needed to continue the task in a future context window. For example, some models use the following prompt:
``` block
You have written a partial transcript for the initial task above. Please write a summary of the transcript. The purpose of this summary is to provide continuity so you can continue to make progress towards solving the task in a future context, where the raw history above may not be accessible and will be replaced with this summary. Write down anything that would be helpful, including the state, next steps, learnings etc. You must wrap your summary in a <summary></summary> block.
```
You can provide custom instructions through the `instructions` parameter. Custom instructions don't supplement the default prompt. They replace it completely:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"instructions": "Focus on preserving code snippets, variable names, and technical decisions.",
}
]
},
)
```
On Claude 5.1 and later models, a request with custom `instructions` summarizes from the visible conversation only: earlier thinking blocks are not part of the summarizer's input.
### Pausing after compaction
Use `pause_after_compaction` to pause the API after generating the compaction summary. This allows you to add additional content blocks (such as preserving recent messages or specific instruction-oriented messages) before the API continues with the response.
When enabled, the API returns a message with the `compaction` stop reason after generating the compaction block:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={
"edits": [{"type": "compact_20260112", "pause_after_compaction": True}]
},
)
# Check if compaction triggered a pause
if response.stop_reason == "compaction":
# Response contains only the compaction block
messages.append({"role": "assistant", "content": response.content})
# Continue the request
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
```
#### Enforcing a total token budget
When a model works on long tasks with many tool-use iterations, total token consumption can grow significantly. You can combine `pause_after_compaction` with a compaction counter to estimate cumulative usage and gracefully wrap up the task once a budget is reached.
This example appears in the SDK languages only: its value is the budget-tracking logic around the request. The raw request combines the `trigger` from [Trigger configuration](#trigger-configuration) with `pause_after_compaction` from [Pausing after compaction](#pausing-after-compaction).
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
TRIGGER_THRESHOLD = 100_000
TOTAL_TOKEN_BUDGET = 3_000_000
n_compactions = 0
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": TRIGGER_THRESHOLD},
"pause_after_compaction": True,
}
]
},
)
if response.stop_reason == "compaction":
n_compactions += 1
messages.append({"role": "assistant", "content": response.content})
# Estimate total tokens consumed; prompt wrap-up if over budget
if n_compactions * TRIGGER_THRESHOLD >= TOTAL_TOKEN_BUDGET:
messages.append(
{
"role": "user",
"content": "Please wrap up your current work and summarize the final state.",
}
)
```
## Working with compaction blocks
When compaction is triggered, the API returns a `compaction` block at the start of the assistant response.
A long-running conversation might result in multiple compactions. The last compaction block reflects the final state of the prompt, replacing content prior to it with the generated summary.
Output
```python
{
"content": [
{
"type": "compaction",
"content": "Summary of the conversation: The user requested help building a web scraper..."
},
{
"type": "text",
"text": "Based on our conversation so far..."
}
]
}
```
### Passing compaction blocks back
You must pass the `compaction` block back to the API on subsequent requests to continue the conversation with the shortened prompt. The simplest approach is to append the entire response content to your messages:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
# After receiving a response with a compaction block
messages.append({"role": "assistant", "content": response.content})
# Continue the conversation
messages.append({"role": "user", "content": "Now add error handling"})
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
```
In Python, use `client.beta.messages`, as the samples on this page do. If you call `client.messages` and serialize blocks yourself, a plain `model_dump()` adds `text: null` and `citations: null` to the `compaction` block. The API then rejects the request with a 400 error (`Extra inputs are not permitted`). Use `to_dict()` or `model_dump(exclude_none=True)` instead. [Continue from the summary](build-with-claude-compaction-on-demand.md#continue-from-the-summary) gives the same advice for on-demand compaction.
When the API receives a `compaction` block, all content blocks before it are ignored. You can either:
- Keep the original messages in your list and let the API handle removing the compacted content
- Manually drop the compacted messages and only include the compaction block onwards
On Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, and Claude Sonnet 5.5, thinking blocks from before a `compaction` block aren't carried forward, so the summary is all the model has of that earlier work. If you write your own `instructions`, tell the model what the summary must retain; see [Tell the model what to preserve in compaction summaries](../../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-fable-5-1.md#tell-the-model-what-to-preserve-in-compaction-summaries).
### Streaming
The compaction block streams differently from text blocks. You receive a `content_block_start` event, followed by a single `content_block_delta` with the complete summary content (no intermediate streaming), and then a `content_block_stop` event.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
with client.beta.messages.stream(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
) as stream:
for event in stream:
match event.type:
case "content_block_start":
block = event.content_block
match block.type:
case "compaction":
print("Compaction started...")
case "text":
print("Text response started...")
case "content_block_delta":
delta = event.delta
match delta.type:
case "compaction_delta":
print(f"Compaction complete: {len(delta.content or '')} chars")
case "text_delta":
print(delta.text, end="", flush=True)
# Get the final accumulated message
message = stream.get_final_message()
messages.append({"role": "assistant", "content": message.content})
```
### Prompt caching
Compaction works well with [prompt caching](build-with-claude-prompt-caching.md). You can add a `cache_control` breakpoint on compaction blocks to cache the summarized content.
```python
{
"role": "assistant",
"content": [
{
"type": "compaction",
"content": "[summary text]",
"cache_control": { "type": "ephemeral" }
},
{
"type": "text",
"text": "Based on our conversation..."
}
]
}
```
#### Maximizing cache hits with system prompts
When compaction occurs, the summary becomes new content that needs to be written to the cache. Without additional cache breakpoints, this would also invalidate any cached system prompt, requiring it to be re-cached along with the compaction summary.
To maximize cache hit rates, add a `cache_control` breakpoint at the end of your system prompt. This keeps the system prompt cached separately from the conversation, so when compaction occurs:
- The system prompt cache remains valid and is read from cache
- Only the compaction summary needs to be written as a new cache entry
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
system=[
{
"type": "text",
"text": "You are a helpful coding assistant...",
"cache_control": {
"type": "ephemeral"
}, # Cache the system prompt separately
}
],
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
```
This keeps long system prompts cached across multiple compaction events throughout a conversation.
## Understanding usage
Compaction requires an additional sampling step, which contributes to rate limits and billing. The API returns detailed usage information in the response:
Output
```python
{
"usage": {
"input_tokens": 23000,
"output_tokens": 1000,
"iterations": [
{
"type": "compaction",
"input_tokens": 180000,
"output_tokens": 3500
},
{
"type": "message",
"input_tokens": 23000,
"output_tokens": 1000
}
]
}
}
```
The `iterations` array shows usage for each sampling iteration. When compaction occurs, you'll see a `compaction` iteration followed by the main `message` iteration. The top-level `input_tokens` and `output_tokens` match the `message` iteration exactly in this example because there is only one non-compaction iteration. The final iteration's token counts reflect the effective context size after compaction.
The top-level `input_tokens` and `output_tokens` do not include compaction iteration usage. They reflect the sum of all non-compaction iterations. To calculate total tokens consumed and billed for a request, sum across all entries in the `usage.iterations` array.
If you previously relied on `usage.input_tokens` and `usage.output_tokens` for cost tracking or auditing, you'll need to update your tracking logic to aggregate across `usage.iterations` when compaction is enabled. With the compaction beta enabled, every response includes `usage.iterations`, even if no compaction occurred. A `compaction` entry appears only when a new compaction is triggered during the request. Re-applying a previous `compaction` block incurs no additional compaction cost, and the top-level usage fields remain accurate in that case.
## Combining with other features
### Server tools
When using server tools (such as web search), the compaction trigger is checked at the start of each sampling iteration. Compaction might occur multiple times within a single request depending on your trigger threshold and the amount of output generated.
### Token counting
The token counting endpoint (`/v1/messages/count_tokens`) applies existing `compaction` blocks in your prompt but does not trigger new compactions. Use it to check your effective token count after previous compactions:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
count_response = client.beta.messages.count_tokens(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
print(f"Current tokens: {count_response.input_tokens}")
print(f"Original tokens: {count_response.context_management.original_input_tokens}")
```
## Examples
Here's a complete example of a long-running conversation with compaction:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages: list[dict] = []
def chat(user_message: str) -> str:
messages.append({"role": "user", "content": user_message})
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 100000},
}
]
},
)
# Append response (compaction blocks are automatically included)
messages.append({"role": "assistant", "content": response.content})
# Return the text content
return next(block.text for block in response.content if block.type == "text")
# Run a long conversation
print(chat("Help me build a Python web scraper"))
print(chat("Add support for JavaScript-rendered pages"))
print(chat("Now add rate limiting and error handling"))
# Continue calling chat() for as long as the conversation needs
```
On Claude Fable 5.1, Claude Opus 5.5, and Claude Sonnet 5.5, remove the `thinking` and `redacted_thinking` blocks from any assistant turn you re-insert after the compaction block, or send `thinking.block_binding.prefix_mismatch_behavior: "drop_block"` with the `thinking-binding-controls-2026-08-01` [beta header](../Endpoints/beta-headers.md). Those blocks were produced when the full history was present, so they no longer pass the [conversation check](build-with-claude-thinking.md#preserved-in-conversation). Where the check is enforced, the continuation request is rejected with a 400 error. The preserved text and tool blocks can stay as they are. Letting the API summarize everything, without re-inserting earlier turns, avoids this. On Claude Sonnet 5.5, `block_binding` works only with `thinking: {"type": "adaptive"}`. With `between_tools`, remove the blocks instead.
Here's an example that uses `pause_after_compaction` to preserve the prior exchange and the current user message (three messages total) verbatim instead of summarizing them:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from typing import Any
client = anthropic.Anthropic()
messages: list[dict[str, Any]] = []
def chat(user_message: str) -> str:
messages.append({"role": "user", "content": user_message})
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 100000},
"pause_after_compaction": True,
}
]
},
)
# Check if compaction occurred and paused
if response.stop_reason == "compaction":
# Get the compaction block from the response
compaction_block = response.content[0]
# Preserve the prior exchange + current user message (3 messages)
# by including them after the compaction block
preserved_messages = messages[-3:] if len(messages) >= 3 else messages
# Build new message list: compaction + preserved messages
new_assistant_content = [compaction_block]
messages_after_compaction = [
{"role": "assistant", "content": new_assistant_content}
] + preserved_messages
# Continue the request with the compacted context + preserved messages
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-5-5",
max_tokens=4096,
messages=messages_after_compaction,
context_management={"edits": [{"type": "compact_20260112"}]},
)
# Update the message list to reflect the compaction
messages.clear()
messages.extend(messages_after_compaction)
# Append the final response
messages.append({"role": "assistant", "content": response.content})
# Return the text content
return next(block.text for block in response.content if block.type == "text")
# Run a long conversation
print(chat("Help me build a Python web scraper"))
print(chat("Add support for JavaScript-rendered pages"))
print(chat("Now add rate limiting and error handling"))
# Continue calling chat() for as long as the conversation needs
```
## Current limitations
- **Same model for summarization:** The model specified in your request is used for summarization. There is no option to use a different (for example, cheaper) model for the summary.
- **Compaction might fail when tools are defined:** When your request includes `tools`, the model occasionally calls a tool during the internal summarization step instead of writing a summary. When this occurs, the response contains a `compaction` block with `content: null`. To prevent this, set [`instructions`](#custom-summarization-instructions) to a prompt that explicitly tells the model not to call tools, for example:
``` block
Summarize the transcript inside <summary></summary> tags. Include relevant information in the summary for continuing the task in the next context window. Do not call any tools while writing this summary; respond with text only.
```
## Next steps
[Context editing](build-with-claude-context-editing.md)
Automatically manage conversation context as it grows with context editing.
[Context windows](build-with-claude-context-windows.md)
Learn about context window sizes and management strategies.
[Session memory compaction cookbook](https://platform.claude.com/cookbook/misc-session-memory-compaction)
Explore a practical implementation that manages long-running conversations with instant session memory compaction using background threading and prompt caching.
## Compatibility
Supported models
- Fable 5 and 5.1
- Mythos 5, 5.1, and Preview
- Opus 4.6, 4.7, 4.8, 5, and 5.5
- Sonnet 4.6, 5, and 5.5
Supported platforms
- Claude APIBeta
- Claude Platform on AWSBeta
- Amazon BedrockBeta
- Google CloudBeta
- Microsoft FoundryBeta
---
## Compaction overview - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/compaction
Path: 04-API-Reference/Guides/build-with-claude-compaction.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fcompaction)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
[Overview](build-with-claude-compaction.md)[Compact on demand](build-with-claude-compaction-on-demand.md)[Keep recent turns](build-with-claude-compaction-keep-recent-turns.md)[Compact in the background](build-with-claude-compaction-background.md)[Keep thinking blocks valid](build-with-claude-compaction-thinking-blocks.md)[Threshold compaction](build-with-claude-compaction-threshold.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Context management
# Compaction overview
Copy page
Learn what compaction does, how compaction on demand and compaction at a token threshold differ, and which page covers your task.
Copy page
Compaction replaces the older turns of a conversation with a summary that Claude writes on the server, so you need no summarization code of your own. It keeps a long conversation or agent task inside the context window, and it keeps the active context small, because response quality degrades as a conversation grows.
If you want to skip this overview, start with [Compaction on demand](build-with-claude-compaction-on-demand.md) to add compaction to your application. While both it and [Compaction at a token threshold](build-with-claude-compaction-threshold.md) are in beta, Compaction on demand covers more common use cases. To clear old tool results or old thinking blocks by rule instead of summarizing them, see [Context editing](build-with-claude-context-editing.md).
## Choose how to compact
Use on-demand compaction wherever it is available.
| | [Compaction on demand](build-with-claude-compaction-on-demand.md) | [Compaction at a token threshold](build-with-claude-compaction-threshold.md) | Your own summarizer ([Compact on the client](build-with-claude-preserved-thinking.md#custom-compaction-on-the-client)) |
|:-----------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------|
| **Who decides when** | You, by sending a request | The API, when input tokens reach the trigger you set | You |
| **Code you write** | A [compaction loop](build-with-claude-compaction-on-demand.md#compact-in-a-loop) that requests the summary and swaps it in | One parameter on your ordinary requests | The summarization call, its prompt, and the history rewrite |
| **What you send back afterward** | The returned block first in `messages`, in place of the messages it summarizes | The response, appended as usual. The API drops what came before the block | Your summary, as a message of your own |
| **Recent turns stay word for word** | Yes: [Compaction that keeps recent turns](build-with-claude-compaction-keep-recent-turns.md) | Yes, by [pausing after compaction](build-with-claude-compaction-threshold.md#pausing-after-compaction) and re-inserting them | Yes |
| **Runs in the background** | Yes: [Compaction in the background](build-with-claude-compaction-background.md) | No: it runs inside the request that reaches the threshold | Yes, in your own code |
| **Kept turns keep their thinking**, on models with [preserved thinking](build-with-claude-preserved-thinking.md) | Yes, under the conditions in [Compaction and preserved thinking](build-with-claude-compaction-thinking-blocks.md) | No: on Claude Fable 5.1 and Claude Opus 5.5, remove or drop the thinking in turns you re-insert (see the [threshold compaction examples](build-with-claude-compaction-threshold.md#examples)) | No: that thinking [fails the check](build-with-claude-preserved-thinking.md#keep-tail-compaction) |
| **Beta header, parameter, and platforms** | `compact-2026-09-04` and the top-level `compaction` parameter. Platforms: see the [on-demand Compatibility list](build-with-claude-compaction-on-demand.md#compatibility) | See the [threshold Compatibility list](build-with-claude-compaction-threshold.md#compatibility) and [Basic usage](build-with-claude-compaction-threshold.md#basic-usage) | None. It runs in your code |
| **Choose it when** | Your application needs to control when compaction happens, can't pause while a summary is written, or must keep recent turns and their thinking | You want the API to manage context inside ordinary requests | You already run your own summarizer and it replaces the whole history with the summary |
## On-demand compaction options
[Compaction on demand](build-with-claude-compaction-on-demand.md) shows a loop that summarizes the whole conversation while your application waits. The first two pages in this list change how that loop runs, and you can combine them. The third applies if you send thinking blocks back and do either.
- [Compaction that keeps recent turns](build-with-claude-compaction-keep-recent-turns.md): when the last few turns must reach Claude word for word. The summary covers only the older turns.
- [Compaction in the background](build-with-claude-compaction-background.md): when the conversation can't pause for the summary. The request runs while work continues, and you swap the block in when it arrives.
- [Compaction and preserved thinking](build-with-claude-compaction-thinking-blocks.md): if you send thinking blocks back on a model with preserved thinking and you keep recent turns or compact in the background. Otherwise skip it.
- [Write your own summarization prompt](build-with-claude-compaction-on-demand.md#write-your-own-summarization-prompt): when the default summary drops something a later turn needs. Your prompt replaces the default one.
- [Compact again](build-with-claude-compaction-on-demand.md#compact-again): when a conversation that already starts with a compaction block grows long again.
Find these topics on other pages:
- [Request a summary](build-with-claude-compaction-on-demand.md#request-a-summary) is on Compaction on demand.
- [Continue from the summary](build-with-claude-compaction-on-demand.md#continue-from-the-summary) is on Compaction on demand. The conditions that keep thinking valid in the turns you keep are on [Compaction and preserved thinking](build-with-claude-compaction-thinking-blocks.md).
- When no summary comes back: see [Handle a missing summary or an error](build-with-claude-compaction-on-demand.md#when-no-summary-comes-back) on Compaction on demand.
- How it fits with the rest of the API: see [Limits and interactions with other features](build-with-claude-compaction-on-demand.md#how-it-fits-with-the-rest-of-the-api) on Compaction on demand.
- Understanding usage: see [Count compaction usage](build-with-claude-compaction-on-demand.md#understanding-usage) for on-demand compaction, or [Understanding usage](build-with-claude-compaction-threshold.md#understanding-usage) for threshold compaction.
- Compatibility: each kind has its own beta header, so each page has its own list. See the [on-demand Compatibility list](build-with-claude-compaction-on-demand.md#compatibility) or the [threshold Compatibility list](build-with-claude-compaction-threshold.md#compatibility).
Threshold compaction has its own page: [Compaction at a token threshold](build-with-claude-compaction-threshold.md).
---
## Context editing - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/context-editing
Path: 04-API-Reference/Guides/build-with-claude-context-editing.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fcontext-editing)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Context management
# Context editing
Copy page
Automatically manage conversation context as it grows with context editing.
Copy page
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
## Overview
For most use cases, [server-side compaction](build-with-claude-compaction.md) is the primary strategy for managing context in long-running conversations. The strategies on this page are useful for specific scenarios where you need more fine-grained control over what content is cleared.
Context editing allows you to selectively clear specific content from conversation history as it grows. Beyond optimizing costs and staying within limits, this is about actively curating what Claude sees: context is a finite resource with diminishing returns, and irrelevant content degrades model focus. Context editing gives you fine-grained runtime control over that curation. For the broader principles behind context management, see [Effective context engineering](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents). This page covers:
- **Tool result clearing** - Best for agentic workflows with heavy tool use where old tool results are no longer needed
- **Thinking block clearing** - For managing thinking blocks when using extended thinking, with options to preserve recent thinking for context continuity
- **Client-side SDK compaction** - An SDK-based alternative for summary-based context management (server-side compaction is generally preferred)
[TABLE]
## Server-side strategies
Context editing is in beta with support for tool result clearing and thinking block clearing. To enable it, use the beta header `context-management-2025-06-27` in your API requests.
Share feedback on this feature through the [feedback form](https://forms.gle/YXC2EKGMhjN1c4L88).
### Tool result clearing
The `clear_tool_uses_20250919` strategy clears tool results when conversation context grows beyond your configured threshold. This is particularly useful for agentic workflows with heavy tool use. Older tool results (like file contents or search results) are no longer needed once Claude has processed them.
When activated, the API automatically clears the oldest tool results in chronological order. The API replaces each cleared result with placeholder text indicating to Claude that it was removed. By default, only tool results are cleared. You can optionally clear both tool results and tool calls (the tool use parameters) by setting `clear_tool_inputs` to true.
### Thinking block clearing
The `clear_thinking_20251015` strategy manages `thinking` blocks in conversations when extended thinking is enabled. This strategy gives you control over thinking preservation: you can choose to keep more thinking blocks to maintain reasoning continuity, or clear them more aggressively to save context space.
**Default behavior:** The default varies by model class.
| Model class | Keep all prior thinking | Keep only the last turn's thinking |
|------------------|-----------------------------|-------------------------------------|
| Opus | Claude Opus 4.5 and later | Claude Opus 4.1 and earlier |
| Sonnet | Claude Sonnet 4.6 and later | Claude Sonnet 4.5 and earlier |
| Haiku | (none) | All models through Claude Haiku 4.5 |
| Fable and Mythos | All models | (none) |
Use this strategy to override the default. If your code runs across multiple model tiers, set `keep` explicitly rather than relying on the per-model default.
An assistant conversation turn may include multiple content blocks (for example, when using tools) and multiple thinking blocks (for example, with [interleaved thinking](build-with-claude-thinking.md#interleaved-thinking)).
### Context editing happens server-side
Context editing is applied server-side before the prompt reaches Claude. Your client application maintains the full, unmodified conversation history. You do not need to sync your client state with the edited version. Continue managing your full conversation history locally as you normally would.
On Claude Fable 5.1 and Claude Opus 5.5, server-side context management never invalidates thinking blocks. Client-side edits to earlier turns can invalidate the thinking blocks in every later assistant turn. For new accounts created on or after August 31, 2026, a request that replays an invalidated block is rejected unless you opt into dropping it. See [Keeping the prefix unchanged](build-with-claude-preserved-thinking.md#prefix-check).
### Context editing and prompt caching
Context editing's interaction with [prompt caching](build-with-claude-prompt-caching.md) varies by strategy:
- **Tool result clearing:** Invalidates cached prompt prefixes when content is cleared. To account for this, clear enough tokens to make the cache invalidation worthwhile. Use the `clear_at_least` parameter to ensure a minimum number of tokens is cleared each time. You'll incur cache write costs each time content is cleared, but subsequent requests can reuse the newly cached prefix.
- **Thinking block clearing:** When thinking blocks are **kept** in context (not cleared), the prompt cache is preserved, enabling cache hits and reducing input token costs. When thinking blocks are **cleared**, the cache is invalidated at the point where clearing occurs. Configure the `keep` parameter based on whether you want to prioritize cache performance or context window availability.
## Supported models
Context editing is available on all supported Claude models.
## Tool result clearing usage
The simplest way to enable tool result clearing is to specify only the strategy type. All other [configuration options](#configuration-options-for-tool-result-clearing) use their default values:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
messages=[{"role": "user", "content": "Search for recent developments in AI"}],
tools=[{"type": "web_search_20250305", "name": "web_search"}],
betas=["context-management-2025-06-27"],
context_management={"edits": [{"type": "clear_tool_uses_20250919"}]},
)
```
### Advanced configuration
You can customize the tool result clearing behavior with additional parameters:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
messages=[
{
"role": "user",
"content": "Create a simple command line calculator app using Python",
}
],
tools=[
{
"type": "text_editor_20250728",
"name": "str_replace_based_edit_tool",
"max_characters": 10000,
},
{"type": "web_search_20250305", "name": "web_search", "max_uses": 3},
],
betas=["context-management-2025-06-27"],
context_management={
"edits": [
{
"type": "clear_tool_uses_20250919",
# Trigger clearing when threshold is exceeded
"trigger": {"type": "input_tokens", "value": 30000},
# Number of tool uses to keep after clearing
"keep": {"type": "tool_uses", "value": 3},
# Optional: Clear at least this many tokens
"clear_at_least": {"type": "input_tokens", "value": 5000},
# Exclude these tools from being cleared
"exclude_tools": ["web_search"],
}
]
},
)
```
## Thinking block clearing usage
Enable thinking block clearing to manage context and prompt caching effectively when extended thinking is enabled:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
messages=[{"role": "user", "content": "Hello"}],
betas=["context-management-2025-06-27"],
context_management={
"edits": [
{
"type": "clear_thinking_20251015",
"keep": {"type": "thinking_turns", "value": 2},
}
]
},
)
```
### Configuration options for thinking block clearing
The `clear_thinking_20251015` strategy supports the following configuration:
| Configuration option | Default | Description |
|----------------------|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `keep` | Model-specific | Defines how many recent assistant turns with thinking blocks to preserve. Use `{type: "thinking_turns", value: N}` where N must be \> 0 to keep the last N turns, or `"all"` to keep all thinking blocks. Opus 4.5+ and Sonnet 4.6+: all turns. Fable and Mythos models: all turns. Earlier Opus/Sonnet and all Haiku: last turn only. |
**Example configurations:**
Keep thinking blocks from the last 3 assistant turns:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
messages=[{"role": "user", "content": "Hello"}],
betas=["context-management-2025-06-27"],
context_management={
"edits": [
{
"type": "clear_thinking_20251015",
"keep": {"type": "thinking_turns", "value": 3},
}
]
},
)
```
Keep all thinking blocks (maximizes cache hits):
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
messages=[{"role": "user", "content": "Hello"}],
betas=["context-management-2025-06-27"],
context_management={
"edits": [
{
"type": "clear_thinking_20251015",
"keep": "all",
}
]
},
)
```
### Combining strategies
You can use both thinking block clearing and tool result clearing together:
When using multiple strategies, the `clear_thinking_20251015` strategy must be listed first in the `edits` array.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
messages=[
{
"role": "user",
"content": "Search for the latest developments in quantum error correction and summarize the key breakthroughs.",
}
],
tools=[
{
"type": "web_search_20250305",
"name": "web_search",
"max_uses": 5,
}
],
betas=["context-management-2025-06-27"],
context_management={
"edits": [
{
"type": "clear_thinking_20251015",
"keep": {"type": "thinking_turns", "value": 2},
},
{
"type": "clear_tool_uses_20250919",
"trigger": {"type": "input_tokens", "value": 50000},
"keep": {"type": "tool_uses", "value": 5},
},
]
},
)
print(response)
```
## Configuration options for tool result clearing
| Configuration option | Default | Description |
|----------------------|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `trigger` | 100,000 input tokens | Defines when the context editing strategy activates. Once the prompt exceeds this threshold, clearing begins. You can specify this value in either `input_tokens` or `tool_uses`. |
| `keep` | 3 tool uses | Defines how many recent tool use/result pairs to keep after clearing occurs. The API removes the oldest tool interactions first, preserving the most recent ones. |
| `clear_at_least` | None | Ensures a minimum number of tokens is cleared each time the strategy activates. If the API can't clear at least the specified amount, the strategy will not be applied. This helps determine if context clearing is worth breaking your prompt cache. |
| `exclude_tools` | None | List of tool names whose tool uses and results should never be cleared. Useful for preserving important context. |
| `clear_tool_inputs` | `false` | Controls whether the tool call parameters are cleared along with the tool results. By default, only the tool results are cleared while keeping Claude's original tool calls visible. |
## Context editing response
You can see which context edits were applied to your request using the `context_management` response field, along with helpful statistics about the content and input tokens cleared.
Output
```python
{
"id": "msg_013Zva2CMHLNnXjNJJKqJ2EF",
"type": "message",
"role": "assistant",
"content": [
// ...
],
"usage": {
// ...
},
"context_management": {
"applied_edits": [
// When using `clear_thinking_20251015`
{
"type": "clear_thinking_20251015",
"cleared_thinking_turns": 3,
"cleared_input_tokens": 15000
},
// When using `clear_tool_uses_20250919`
{
"type": "clear_tool_uses_20250919",
"cleared_tool_uses": 8,
"cleared_input_tokens": 50000
}
]
}
}
```
For streaming responses, the context edits are included in the final `message_delta` event:
Streaming Response
```python
{
"type": "message_delta",
"delta": {
"stop_reason": "end_turn",
"stop_sequence": null
},
"usage": {
"output_tokens": 1024
},
"context_management": {
"applied_edits": [
// ...
]
}
}
```
## Token counting
The [token counting](build-with-claude-token-counting.md) endpoint supports context management, allowing you to preview how many tokens your prompt will use after context editing is applied.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.beta.messages.count_tokens(
model="claude-opus-5-5",
messages=[{"role": "user", "content": "Continue our conversation..."}],
betas=["context-management-2025-06-27"],
context_management={
"edits": [
{
"type": "clear_tool_uses_20250919",
"trigger": {"type": "input_tokens", "value": 30000},
"keep": {"type": "tool_uses", "value": 5},
}
]
},
)
print(f"Original tokens: {response.context_management.original_input_tokens}")
print(f"After clearing: {response.input_tokens}")
print(
f"Savings: {response.context_management.original_input_tokens - response.input_tokens} tokens"
)
```
Output
```python
{
"input_tokens": 25000,
"context_management": {
"original_input_tokens": 70000
}
}
```
The response shows both the final token count after context management is applied (`input_tokens`) and the original token count before any clearing occurred (`original_input_tokens`).
## Using with the memory tool
Context editing can be combined with the [memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md). When your conversation context approaches the configured clearing threshold, Claude receives an automatic warning to preserve important information. This enables Claude to save tool results or context to its memory files before they're cleared from the conversation history.
This combination allows you to:
- **Preserve important context:** Claude can write essential information from tool results to memory files before those results are cleared
- **Maintain long-running workflows:** Enable agentic workflows that would otherwise exceed context limits by offloading information to persistent storage
- **Access information on demand:** Claude can look up previously cleared information from memory files when needed, rather than keeping everything in the active context window
For example, in a file editing workflow where Claude performs many operations, Claude can summarize completed changes to memory files as the context grows. When tool results are cleared, Claude retains access to that information through its memory system and can continue working effectively.
To use both features together, enable them in your API request:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
messages=[{"role": "user", "content": "Hello"}],
tools=[{"type": "memory_20250818", "name": "memory"}],
betas=["context-management-2025-06-27"],
context_management={"edits": [{"type": "clear_tool_uses_20250919"}]},
)
```
For the full memory tool reference including commands and examples, see [Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md).
## Client-side compaction (SDK)
**Anthropic recommends server-side compaction over SDK compaction.** [Server-side compaction](build-with-claude-compaction.md) handles context management automatically with less integration complexity, better token usage calculation, and no client-side limitations. Use SDK compaction only if you specifically need client-side control over the summarization process.
The `compaction_control` parameter is deprecated in the TypeScript and Ruby SDKs and will be removed in a future version. The SDKs emit a deprecation warning when it is enabled. The Python SDK removed it in v1.0. To use server-side compaction with a tool runner, pass the `compact_20260112` edit in the request's `context_management` parameter.
Compaction is available in the [TypeScript and Ruby SDKs](../Other/cli-sdks-libraries-overview.md) when using the [`tool_runner` method](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md).
Compaction is an SDK feature that automatically manages conversation context by generating summaries when token usage grows too large. Unlike server-side context editing strategies that clear content, compaction instructs Claude to summarize the conversation history, then replaces the full history with that summary. This allows Claude to continue working on long-running tasks that would otherwise exceed the [context window](build-with-claude-context-windows.md).
### How compaction works
When compaction is enabled, the SDK monitors token usage after each model response:
1. **Threshold check:** The SDK calculates total tokens as `input_tokens + cache_creation_input_tokens + cache_read_input_tokens + output_tokens` (see [Prompt caching](build-with-claude-prompt-caching.md) for the cache token fields).
2. **Summary generation:** When the threshold is exceeded, a summary prompt is injected as a user turn, and Claude generates a structured summary wrapped in `<summary></summary>` tags.
3. **Context replacement:** The SDK extracts the summary and replaces the entire message history with it.
4. **Continuation:** The conversation resumes from the summary, with Claude picking up where it left off.
### Using compaction
Add `compaction_control` to your `tool_runner` call to enable automatic summarization when token usage exceeds the threshold.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
In v1.0 and later, the Python SDK's tool runner does not support client-side `compaction_control`. Use [server-side compaction](build-with-claude-compaction-threshold.md) instead: it works with the tool runner by passing the `compact_20260112` edit in the request's `context_management` parameter.
#### What occurs during compaction
As the conversation grows, the message history accumulates:
**Before compaction (approaching 100k tokens):**
```python
[
{ "role": "user", "content": "Analyze all files and write a report..." },
{ "role": "assistant", "content": "I'll help. Let me start by reading..." },
{
"role": "user",
"content": [{ "type": "tool_result", "tool_use_id": "...", "content": "..." }]
},
{ "role": "assistant", "content": "Based on file1.txt, I see..." },
{
"role": "user",
"content": [{ "type": "tool_result", "tool_use_id": "...", "content": "..." }]
},
{ "role": "assistant", "content": "After analyzing file2.txt..." }
// ... 50 more exchanges like this ...
]
```
When tokens exceed the threshold, the SDK injects a summary request and Claude generates a summary. The entire history is then replaced:
**After compaction (back to ~2–3k tokens):**
```python
[
{
"role": "assistant",
"content": "# Task Overview\nThe user requested analysis of directory files to produce a summary report...\n\n# Current State\nAnalyzed 52 files across 3 subdirectories. Key findings documented in report.md...\n\n# Important Discoveries\n- Configuration files use YAML format\n- Found 3 deprecated dependencies\n- Test coverage at 67%\n\n# Next Steps\n1. Analyze remaining files in /src/legacy\n2. Complete final report sections...\n\n# Context to Preserve\nUser prefers markdown format with executive summary first..."
}
]
```
Claude continues working from this summary as if it were the original conversation history.
### Configuration options
| Parameter | Type | Required | Default | Description |
|---------------------------|---------|----------|-------------------------------------------------------|------------------------------------------|
| `enabled` | boolean | Yes | \- | Whether to enable automatic compaction |
| `context_token_threshold` | number | No | 100,000 | Token count at which compaction triggers |
| `model` | string | No | Same as main model | Model to use for generating summaries |
| `summary_prompt` | string | No | See [Default summary prompt](#default-summary-prompt) | Custom prompt for summary generation |
#### Choosing a token threshold
The threshold determines when compaction occurs. A lower threshold means more frequent compactions with smaller context windows. A higher threshold allows more context but risks hitting limits.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
In v1.0 and later, the Python SDK's tool runner does not support client-side `compaction_control`. Use [server-side compaction](build-with-claude-compaction-threshold.md) instead: it works with the tool runner by passing the `compact_20260112` edit in the request's `context_management` parameter.
#### Using a different model for summaries
You can use a faster or cheaper model for generating summaries:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
In v1.0 and later, the Python SDK's tool runner does not support client-side `compaction_control`. Use [server-side compaction](build-with-claude-compaction-threshold.md) instead: it works with the tool runner by passing the `compact_20260112` edit in the request's `context_management` parameter.
#### Custom summary prompts
You can provide a custom prompt for domain-specific needs. Your prompt should instruct Claude to wrap its summary in `<summary></summary>` tags.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
In v1.0 and later, the Python SDK's tool runner does not support client-side `compaction_control`. Use [server-side compaction](build-with-claude-compaction-threshold.md) instead: it works with the tool runner by passing the `compact_20260112` edit in the request's `context_management` parameter.
### Default summary prompt
The built-in summary prompt instructs Claude to create a structured continuation summary including:
1. **Task Overview:** The user's core request, success criteria, and constraints.
2. **Current State:** What has been completed, files modified, and artifacts produced.
3. **Important Discoveries:** Technical constraints, decisions made, errors resolved, and failed approaches.
4. **Next Steps:** Specific actions needed, blockers, and priority order.
5. **Context to Preserve:** User preferences, domain-specific details, and commitments made.
This structure enables Claude to resume work efficiently without losing important context or repeating mistakes.
### View full default prompt
```python
You have been working on the task described above but have not yet completed it. Write a continuation summary that will allow you (or another instance of yourself) to resume work efficiently in a future context window where the conversation history will be replaced with this summary. Your summary should be structured, concise, and actionable. Include:
1. Task Overview
The user's core request and success criteria
Any clarifications or constraints they specified
2. Current State
What has been completed so far
Files created, modified, or analyzed (with paths if relevant)
Key outputs or artifacts produced
3. Important Discoveries
Technical constraints or requirements uncovered
Decisions made and their rationale
Errors encountered and how they were resolved
What approaches were tried that didn't work (and why)
4. Next Steps
Specific actions needed to complete the task
Any blockers or open questions to resolve
Priority order if multiple steps remain
5. Context to Preserve
User preferences or style requirements
Domain-specific details that aren't obvious
Any promises made to the user
Be concise but complete—err on the side of including information that would prevent duplicate work or repeated mistakes. Write in a way that enables immediate resumption of the task.
Wrap your summary in <summary></summary> tags.
```
### Limitations
#### Server-side tools
Compaction requires special consideration when using server-side tools such as [web search](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md) or [web fetch](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md).
When using server-side tools, the SDK may incorrectly calculate token usage, causing compaction to trigger at the wrong time.
For example, after a web search operation, the API response might show:
Output
```python
{
"usage": {
"input_tokens": 63000,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 270000,
"output_tokens": 1400
}
}
```
The SDK calculates total usage as 63,000 + 0 + 270,000 + 1,400 = 334,400 tokens. However, the `cache_read_input_tokens` value includes accumulated reads from multiple internal API calls made by the server-side tool, not your actual conversation context. Your real context length might only be the 63,000 `input_tokens`, but the SDK sees 334k and triggers compaction prematurely.
**Workarounds:**
- Use the [token counting](build-with-claude-token-counting.md) endpoint to get accurate context length
- Avoid compaction when using server-side tools extensively
#### Tool use edge cases
When the SDK triggers compaction while a tool use response is pending, it removes the tool use block from the message history before generating the summary. Claude will re-issue the tool call after resuming from the summary if still needed.
### Monitoring compaction
Understanding when compaction triggers helps you tune thresholds and verify expected behavior.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
In v1.0 and later, the Python SDK's tool runner does not support `compaction_control`. Use [server-side compaction](build-with-claude-compaction.md) instead.
### When to use compaction
**Good use cases:**
- Long-running agent tasks that process many files or data sources
- Research workflows that accumulate large amounts of information
- Multistep tasks with clear, measurable progress
- Tasks that produce artifacts (files, reports) that persist outside the conversation
**Less ideal use cases:**
- Tasks requiring precise recall of early conversation details
- Workflows using server-side tools extensively
- Tasks that need to maintain exact state across many variables
## Next steps
[Compaction](build-with-claude-compaction.md)
Manage long conversations with server-side compaction, the recommended strategy for most use cases.
[Prompt caching](build-with-claude-prompt-caching.md)
Reduce cost and latency by caching prompt prefixes, and learn how context editing interacts with the cache.
---
## Context windows - Claude Platform Docs
Source: https://platform.claude.com/en/docs/build-with-claude/context-windows
Path: 04-API-Reference/Guides/build-with-claude-context-windows.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fcontext-windows)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Context management
# Context windows
Copy page
Understand how the context window works, how extended thinking and tool use count toward it, and how to manage context as conversations grow.
Copy page
As conversations grow, you'll eventually approach context window limits. For long-running conversations and agentic workflows, [server-side compaction](build-with-claude-compaction.md) is the primary strategy for context management.
## How the context window works
The "context window" refers to all the text a language model can reference when generating a response, including the response itself. This is different from the large corpus of data the language model was trained on, and instead represents a "working memory" for the model. A larger context window allows the model to handle more complex and lengthy prompts, but more context isn't automatically better. As token count grows, accuracy and recall degrade, a phenomenon known as *context rot*. This makes curating what's in context just as important as how much space is available.
For more on why long contexts degrade and how to engineer around it, see [Effective context engineering](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents).
The following diagram illustrates the standard context window behavior for API requests¹:
*¹ Chat interfaces such as [claude.ai](https://claude.ai/) can also manage the context window on a rolling "first in, first out" basis.*
- **Progressive token accumulation:** As the conversation advances through turns, each user message and assistant response accumulates within the context window, and previous turns are preserved completely.
- **Context window capacity:** The context window ([up to 1M tokens, depending on the model](#context-window-sizes-by-model)) holds the conversation history plus the new output Claude generates.
- **Input-output flow:** Each turn consists of:
- **Input phase:** Contains all previous conversation history plus the current user message
- **Output phase:** Generates a text response that becomes part of the input for the next turn
Everything in the request counts toward the context window: the system prompt, every message in `messages` (including tool results, images, and documents), and your tool definitions. The output Claude generates for the turn, including its extended thinking, counts too. Every response reports what the request consumed in its `usage` field. If you use [prompt caching](build-with-claude-prompt-caching.md), the input count is split across `input_tokens`, `cache_read_input_tokens`, and `cache_creation_input_tokens`, and all three count toward the window. To estimate a request before you send it, use the [token counting API](build-with-claude-token-counting.md).
## Context window sizes by model
Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 5, Claude Sonnet 4.6, and [Claude Mythos Preview](../../22-Safety-Policy/glasswing.md) have a 1M-token context window. A single request to any of them can generate up to 128k output tokens (`max_tokens`). Other Claude models, including Claude Sonnet 4.5, have a 200k-token context window.
For every model with a 1M-token context window, 1M is the default: you don't need a beta header, and long-context requests are billed at [standard pricing](../../17-Billing-Plans/about-claude-pricing.md#long-context-pricing).
A single request can include up to 600 images or PDF pages (100 for models with a 200k-token context window). If you send many images or large documents, you might reach [request size limits](../Endpoints/overview.md#request-size-limits) before the token limit.
See the [model comparison](../../20-Models/about-claude-models-overview.md#latest-models-comparison) table for a list of context window sizes by model.
## The context window with thinking
With [thinking](build-with-claude-thinking.md), all input and output tokens, including thinking tokens, count toward the context window limit, with a few nuances in multi-turn situations.
Thinking tokens are a subset of your `max_tokens` parameter, are billed as output tokens, and count toward rate limits. With [adaptive thinking](build-with-claude-thinking.md), Claude determines its thinking allocation dynamically, so thinking token usage varies from request to request.
Whether thinking blocks from previous assistant turns stay in the context window depends on the model. On Claude Opus 4.5 and later Opus models, Claude Sonnet 4.6 and later Sonnet models, Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, and Claude Mythos Preview, the API keeps previous thinking blocks by default, and they count toward the context window like any other input tokens. On earlier Opus and Sonnet models and all Haiku models, the API automatically strips previous thinking blocks from the conversation history when you pass them back, which preserves token capacity for conversation content. For the per-model defaults, see [thinking block preservation by model](build-with-claude-thinking.md#thinking-block-preservation-by-model). To override the default in either direction, use [thinking block clearing](build-with-claude-context-editing.md#thinking-block-clearing).
The following diagram shows how tokens are managed when thinking is enabled on a model that strips previous thinking blocks:
- **Stripping thinking blocks:** On models that strip previous thinking blocks, thinking blocks (shown in dark gray) are generated during each turn's output phase but are not carried forward as input tokens for subsequent turns. You do not need to strip the thinking blocks yourself: if you pass them back, the Claude API strips them automatically.
- **Billing:** Thinking tokens are billed as output tokens once, when they are generated. On models that keep previous thinking blocks, the kept blocks are then part of later requests' input and are billed as input tokens, like the rest of the conversation history.
You can read more about the context window and thinking in the [Thinking](build-with-claude-thinking.md) guide.
## The context window with thinking and tool use
The following diagram illustrates how tokens are managed when you combine thinking with tool use on a model that strips previous thinking blocks:
1. 1
### First turn architecture
- **Input components:** Tools configuration and user message
- **Output components:** Thinking + text response + tool use request
- **Token calculation:** All input and output components count toward the context window, and all output components are billed as output tokens.
2. 2
### Tool result handling (turn 2)
- **Input components:** Every block in the first turn and the `tool_result`. You must return the thinking block with the corresponding tool results. This is the only case where you have to return thinking blocks.
- **Output components:** After tool results have been passed back to Claude, Claude responds with only text (no additional thinking until the next `user` message, unless [interleaved thinking](build-with-claude-thinking.md#interleaved-thinking) is enabled).
- **Token calculation:** All input and output components count toward the context window, and all output components are billed as output tokens.
3. 3
### New user turn (turn 3)
- **Input components:** All inputs and the output from the previous turn are carried forward. The thinking block from the completed tool use cycle no longer has to stay in context: on models that strip previous thinking blocks, the API drops it automatically when you pass it back, and on models that keep previous thinking blocks, it stays unless you clear it with [thinking block clearing](build-with-claude-context-editing.md#thinking-block-clearing). This is also where you add the next `user` turn.
- **Output components:** Because there is a new `user` turn outside the tool use cycle, Claude generates a new thinking block and continues from there.
- **Token calculation:** On models that strip previous thinking blocks, the previous thinking tokens no longer count toward the context window. All other previous blocks still count toward the context window, as does the thinking block in the current `assistant` turn.
- **Considerations for tool use with thinking:**
- When you post tool results, you must include the entire unmodified thinking block that accompanies that tool request, including its signature.
- The API uses cryptographic signatures to verify thinking block authenticity. If you modify a thinking block, the API returns an error.
Most current Claude models support [interleaved thinking](build-with-claude-thinking.md#interleaved-thinking), which lets Claude think between tool calls, including after it receives tool results. It is automatic on models with adaptive thinking; Claude Opus 4.5, Claude Sonnet 4.5, and earlier Claude 4 models require the `interleaved-thinking-2025-05-14` beta header, and Claude Haiku 4.5 does not support it.
For more information about using tools with thinking, see [Thinking with tool use](build-with-claude-thinking.md#thinking-with-tool-use).
To reduce the context consumed by the tool definitions themselves, see [Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md), or defer tool definitions with the [tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md).
## Context awareness
Claude Sonnet 5, Claude Sonnet 4.6, Claude Sonnet 4.5, and Claude Haiku 4.5 have **context awareness:** these models track their remaining context window (their "token budget") throughout a conversation. This lets the model manage long-running tasks against the space that remains rather than guess how many tokens are left. Context awareness is automatic: there is nothing for you to enable, and you never send the tags shown in this section yourself. The API injects them.
### How it works
In the system prompt of every request, the API gives Claude its total context window:
```python
<budget:token_budget>200000</budget:token_budget>
```
The budget matches the context window available to your request: 1M tokens for Claude Sonnet 5 and Claude Sonnet 4.6, and 200k tokens for Claude Sonnet 4.5 and Claude Haiku 4.5. The examples in this section show a model with a 200k-token context window.
After each tool call, the API gives Claude an update on its remaining capacity:
```python
<system_warning>Token usage: 35000/200000; 165000 remaining</system_warning>
```
Image tokens are included in these budgets.
Claude Opus 4.7 and later Opus models, Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, and Claude Mythos 5 don't receive these injected tags. On these models, you can give the model an explicit budget with [task budgets](build-with-claude-task-budgets.md), which are in beta.
For agents that span multiple sessions, design your state artifacts so that context recovery is fast when a new session starts. The [memory tool's multisession pattern](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md#multisession-software-development-pattern) walks through a concrete approach. See also [Effective harnesses for long-running agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents).
For prompting guidance on using context awareness, see [Prompting best practices](../../10-Prompting-Guides/build-with-claude-prompt-engineering-claude-prompting-best-practices.md#context-awareness-and-multiwindow-workflows).
## Manage context with compaction
If your conversations regularly approach context window limits, use [server-side compaction](build-with-claude-compaction.md). Compaction automatically summarizes earlier parts of the conversation on the server, so the conversation can continue past the context window limit. It is available in beta for Claude 4.6 and later models and [Claude Mythos Preview](../../22-Safety-Policy/glasswing.md).
For more specialized needs, [context editing](build-with-claude-context-editing.md) offers additional strategies:
- **Tool result clearing:** Clear old tool results in agentic workflows
- **Thinking block clearing:** Manage thinking blocks when you use extended thinking
Cached prompt prefixes still occupy the context window: [prompt caching](build-with-claude-prompt-caching.md) changes what you pay for those tokens, not whether they count.
## Context window overflow behavior
If the input alone already exceeds the model's context window, the API returns a 400 `invalid_request_error` ("prompt is too long") on every model.
On Claude 4.5 models and newer, if input tokens plus `max_tokens` exceeds the context window size, the API accepts the request. If generation then reaches the context window limit, it stops with `stop_reason: "model_context_window_exceeded"`. On earlier models, the API returns a [validation error](../Endpoints/errors.md) instead. To opt in to the `model_context_window_exceeded` behavior on those models, use the `model-context-window-exceeded-2025-08-26` beta header. See [Stop reasons and fallback](build-with-claude-handling-stop-reasons.md) for details.
To stay within context window limits, use the [token counting API](build-with-claude-token-counting.md) to estimate token usage before sending messages to Claude.
## Next steps
[Compaction](build-with-claude-compaction.md)
Server-side context compaction for managing long conversations that approach context window limits.
[Context editing](build-with-claude-context-editing.md)
Automatically manage conversation context as it grows with context editing.
[Model comparison table](../../20-Models/about-claude-models-overview.md#latest-models-comparison)
See the model comparison table for a list of context window sizes and input/output token pricing by model.
[Thinking](build-with-claude-thinking.md)
Give Claude enhanced reasoning for complex tasks and control how thinking content is returned.
---
## Data residency - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/data-residency
Path: 04-API-Reference/Guides/build-with-claude-data-residency.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fmanage-claude%2Fdata-residency)
SearchCtrlK
Organization
[Admin API](../Other/manage-claude-admin-api.md)[User management](../Other/manage-claude-user-management.md)[Workspaces](../Other/manage-claude-workspaces.md)
Authentication
[Overview](../Other/manage-claude-authentication.md)[Create an Admin API key](../Other/manage-claude-admin-api-keys.md)[App Attest](../Other/manage-claude-app-attest.md)[Workload Identity Federation](../Other/manage-claude-workload-identity-federation.md)[Manage WIF via API](../Other/manage-claude-wif-admin-api.md)[WIF reference](../Other/manage-claude-wif-reference.md)
Identity providers
Monitoring
[Usage and Cost API](../Other/manage-claude-usage-cost-api.md)[Rate Limits API](../Other/manage-claude-rate-limits-api.md)[Analytics APIs](../Other/manage-claude-analytics-api.md)[Claude Code Analytics API](../Other/manage-claude-claude-code-analytics-api.md)[Spend Limits API](../Other/manage-claude-spend-limits-api.md)
Data & compliance
[Data residency](build-with-claude-data-residency.md)[API and data retention](../Other/manage-claude-api-and-data-retention.md)[Access Transparency](../Other/manage-claude-access-transparency.md)
[Encryption keys](../Other/manage-claude-cmek.md)
[Inference hooks](../Other/manage-claude-inference-hooks.md)
Compliance API
[Overview](../Other/manage-claude-compliance-api.md)[Set up the Compliance API](../Other/manage-claude-compliance-api-access.md)[Activity Feed](../Other/manage-claude-compliance-activity-feed.md)[Chats, files, and projects](../Other/manage-claude-compliance-content-data.md)[Session transcripts](../Other/manage-claude-compliance-sessions.md)[Organizations, users, roles, groups, and settings](../Other/manage-claude-compliance-org-data.md)[Design your integration](../Other/manage-claude-compliance-integration-patterns.md)[Errors](../Other/manage-claude-compliance-errors.md)[FAQ](../Other/manage-claude-compliance-faq.md)
[Console](../Other/usage-limits.md)
[Admin](../Other/manage-claude-admin-api.md)Data & compliance
# Data residency
Copy page
Manage where model inference runs and where data is stored with geographic controls.
Copy page
Data residency controls let you manage where your data is processed and stored. Two independent settings govern this:
- **Inference geo:** Controls where model inference runs, on a per-request basis. Set through the `inference_geo` API parameter or as a workspace default.
- **Workspace geo:** Controls where data is stored at rest and where endpoint processing (such as image transcoding and code execution) happens. Configured at the workspace level in the [Claude Console](../Other/usage-limits.md).
[Claude Managed Agents](../Other/managed-agents-overview.md) supports geographic pinning at the agent level: `inference_geo` on an [agent's model configuration](../Other/managed-agents-agent-setup.md#pin-the-inference-geo) pins the geography that serves model requests for sessions running that agent, with [per-session overrides](../Other/managed-agents-sessions.md#pin-the-inference-geo-for-a-session) at session create. Agents without a pin follow the workspace's default inference geo on each request. Managed Agents also respects the Workspace geo configured in Console, and with [self-hosted sandboxes](../Other/managed-agents-self-hosted-sandboxes.md), tool execution and the sandbox filesystem stay on infrastructure you control; the contents of attached [memory stores](../Other/managed-agents-self-hosted-sandboxes.md#use-memory-stores) remain stored by Anthropic and are copied to your sandbox for the session.
## Inference geo
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
The `inference_geo` parameter controls where model inference runs for a specific API request. Add it to any `POST /v1/messages` call.
| Value | Description |
|:-----------|:------------------------------------------------------------------------------------------------|
| `"global"` | Default. Inference may run in any available geography for optimal performance and availability. |
| `"us"` | Inference runs only in US-based infrastructure. |
### API usage
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
inference_geo="us",
messages=[
{"role": "user", "content": "Summarize the key points of this document."}
],
)
for block in response.content:
if block.type == "text":
print(block.text)
# Check where inference actually ran
print(f"Inference geo: {response.usage.inference_geo}")
```
### Response
The response `usage` object includes an `inference_geo` field indicating where inference ran:
Output
```python
{
"usage": {
"input_tokens": 25,
"output_tokens": 150,
"inference_geo": "us"
}
}
```
### Model availability
The `inference_geo` parameter is supported on Claude 4.6 and later models. Requests with `inference_geo` on Claude Opus 4.5, Claude Sonnet 4.5, Claude Haiku 4.5, or earlier models return a 400 error.
The `inference_geo` parameter is available on the Claude API (first-party) and [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md). On Amazon Bedrock and Google Cloud, the inference region is determined by the endpoint URL or inference profile, so `inference_geo` is not applicable. On [Claude in Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md), `inference_geo` is likewise not applicable: deployments hosted on Azure can instead use the US Data Zone Standard deployment type, which keeps inference within the United States. The `inference_geo` parameter is also not available through the [OpenAI SDK compatibility endpoint](../Other/cli-sdks-libraries-libraries-openai-sdk.md).
### Workspace-level restrictions
Workspace settings also support restricting which inference geos are available:
- **`allowed_inference_geos`:** Restricts which geos a workspace can use. If a request specifies an `inference_geo` not in this list, the API returns an error.
- **`default_inference_geo`:** Sets the fallback geo when `inference_geo` is omitted from a request. Individual requests can override this by setting `inference_geo` explicitly.
These settings can be configured through the Console or the [Admin API](../Other/manage-claude-admin-api.md) under the `data_residency` field.
## Workspace geo
Workspace geo is set when you create a workspace and can't be changed afterward. Currently, `"us"` is the only available workspace geo.
To set workspace geo, create a new workspace in the [Console](../Other/usage-limits.md):
1. Go to **Settings** \> **Workspaces**.
2. Create a new workspace.
3. Select the workspace geo.
**Claude Platform on AWS:** Workspace geo is not configurable. Claude Managed Agents sessions on this platform run with an effective Workspace geo of `"us"`, which is currently the only available workspace geo. See [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md) for data residency considerations specific to that platform.
## Pricing
Data residency pricing varies by model generation:
- **Claude 4.6 and later models:** US-only inference (`inference_geo: "us"`) is priced at 1.1x the standard rate across all token pricing categories (input tokens, output tokens, cache writes, and cache reads).
- **Global routing** (`inference_geo: "global"`): Standard pricing applies.
- **Older models:** Don't support `inference_geo` (see [Model availability](#model-availability)); standard pricing applies. Requests that include the parameter return a 400 error.
This pricing applies to the Claude API (first-party) and Claude Platform on AWS. On Claude in Microsoft Foundry, the same 1.1x multiplier applies to deployments hosted on Azure that use the US Data Zone Standard deployment type. Partner-operated platforms (Bedrock and Google Cloud) have their own regional pricing. See [Data residency pricing](../../17-Billing-Plans/about-claude-pricing.md#data-residency-pricing) for details.
The same multiplier applies to [Claude Managed Agents](../Other/managed-agents-overview.md): when an agent's [model configuration](../Other/managed-agents-agent-setup.md) pins `inference_geo` to `"us"`, model requests in sessions running that agent are priced at 1.1x the standard rate.
If you have a [Priority Tier](../Endpoints/service-tiers.md) commitment, the 1.1x multiplier for US-only inference also affects how tokens are counted against your Priority Tier capacity. Each token consumed with `inference_geo: "us"` draws down 1.1 tokens from your committed TPM, consistent with how other pricing multipliers (such as prompt caching) affect burndown rates.
## Batch API support
The `inference_geo` parameter is supported on the [Batch API](build-with-claude-batch-processing.md). Each request in a batch can specify its own `inference_geo` value.
## Migration from legacy opt-outs
If your organization previously opted out of global routing to keep inference in the US, your workspace has been automatically configured with `allowed_inference_geos: ["us"]` and `default_inference_geo: "us"`. No code changes are required. Your existing data residency requirements continue to be enforced through the new geo controls.
### What changed
The legacy opt-out was an organization-level setting that restricted all requests to US-based infrastructure. The new data residency controls replace this with two mechanisms:
- **Per-request control:** The `inference_geo` parameter lets you specify `"us"` or `"global"` on each API call, giving you request-level flexibility.
- **Workspace controls:** The `default_inference_geo` and `allowed_inference_geos` settings in the Console let you enforce geo policies across all keys in a workspace.
### What happened to your workspace
Your workspace was migrated automatically:
| Legacy setting | New equivalent |
|:---------------------------------|:----------------------------------------------------------------|
| Global routing opt-out (US only) | `allowed_inference_geos: ["us"]`, `default_inference_geo: "us"` |
All API requests using keys from your workspace continue to run on US-based infrastructure. No action is needed to maintain your current behavior.
### If you want to use global routing
If your data residency requirements have changed and you want to take advantage of global routing for better performance and availability, update your workspace's inference geo settings to include `"global"` in the allowed geos and set `default_inference_geo` to `"global"`. See [Workspace-level restrictions](#workspace-level-restrictions) for details.
### Pricing impact
Legacy models are unaffected by this migration. For current pricing on newer models, see [Pricing](#pricing).
## Current limitations
- **Shared rate limits:** Rate limits are shared across all geos.
- **Inference geo:** Only `"us"` and `"global"` are available.
- **Workspace geo:** Only `"us"` is currently available. Workspace geo can't be changed after workspace creation.
## Next steps
[Pricing](../../17-Billing-Plans/about-claude-pricing.md#data-residency-pricing)
View data residency pricing details.
[Workspaces](../Other/manage-claude-workspaces.md)
Learn about workspace configuration.
[Usage and Cost API](../Other/manage-claude-usage-cost-api.md)
Track usage and costs by data residency.
---
## Effort - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/effort
Path: 04-API-Reference/Guides/build-with-claude-effort.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Feffort)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Model capabilities
# Effort
Copy page
Control how many tokens Claude uses when responding with the effort parameter, trading off between response thoroughness and token efficiency.
Copy page
Effort
[ZDR](../Other/manage-claude-api-and-data-retention.md)
Eligible
excludes [Covered Models](../Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements)
The effort parameter lets you control how many tokens Claude spends when responding to requests. You can trade off between response thoroughness and token efficiency with a single model. The top-level effort parameter is available on all supported models with no beta header required. [Per-message effort](#change-effort-mid-conversation-beta) is in beta.
To learn how effort interacts with thinking and which control to reach for, see [Thinking and effort](build-with-claude-thinking.md#thinking-and-effort). Where adaptive thinking is available, effort is the recommended way to control thinking depth.
## Set the effort level
Set `output_config.effort` on the request. The following example runs one request at `medium` effort and prints the response text.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
messages=[
{
"role": "user",
"content": "Analyze the trade-offs between microservices and monolithic architectures",
}
],
output_config={"effort": "medium"},
)
for block in response.content:
if block.type == "text":
print(block.text)
```
## How effort works
Most Claude models default to high effort, spending as many tokens as needed for excellent results; Claude Opus 5.5 defaults to medium. You can raise the effort level to `max` for the absolute highest capability, or lower it to be more conservative with token usage, optimizing for speed and cost while accepting some reduction in capability.
Setting `effort` to the model's default (`"medium"` on Claude Opus 5.5, `"high"` on other models) produces exactly the same behavior as omitting the `effort` parameter entirely.
The effort parameter affects **all tokens** in the response, including:
- Text responses and explanations
- Tool calls and function arguments
- Thinking (when active)
Because effort applies to every output token, it works whether or not thinking is enabled. Lower effort also means fewer and terser tool calls.
### Effort levels
| Level | Description | Typical use case |
|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
| `max` | Absolute maximum capability with no constraints on token spending. Available on Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, Claude Mythos Preview, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 5, and Claude Sonnet 4.6. | Tasks requiring the deepest possible reasoning and most thorough analysis |
| `xhigh` | Extended capability for long-horizon work. Available on Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, and Claude Sonnet 5. | Long-running agentic and coding tasks (over 30 minutes) with token budgets in the millions |
| `high` | Spends as many tokens as the task needs for excellent results. The default on every model that supports effort except Claude Opus 5.5. | Complex reasoning, difficult coding problems, agentic tasks |
| `medium` | Balanced approach with moderate token savings. The default on Claude Opus 5.5. | Agentic tasks that require a balance of speed, cost, and performance |
| `low` | Most efficient. Significant token savings with some capability reduction. | Simpler tasks that need the best speed and lowest costs, such as subagents |
Not every model that supports `max` supports `xhigh`.
Effort is a behavioral signal, not a strict token budget. At lower effort levels, Claude still thinks on sufficiently difficult problems, but thinks less than it would at higher effort levels for the same problem.
The per-model recommendations that follow override this table where they differ.
### Recommended effort levels for Claude Fable 5.1
Claude Fable 5.1 supports all five effort levels. **Start with `high`, the default.** Step up to `xhigh` or `max` for the most capability-sensitive agentic and coding work, and step down to `medium` or `low` for routine or latency-sensitive work once your evals show quality holds. At `high` and above, set a large `max_tokens`. It's a hard limit on total output (thinking plus response text). The same recommendations apply to Claude Mythos 5.1. See [Prompting Claude Fable 5.1](../../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-fable-5-1.md#consider-all-effort-levels).
Claude Fable 5.1 also supports [changing effort mid-conversation](#change-effort-mid-conversation-beta) with a per-message `output_config`, which preserves the prompt cache.
### Recommended effort levels for Claude Fable 5
Effort is the primary control for trading off intelligence, latency, and cost on Claude Fable 5. **Start with `high`, the default, for most tasks**, use `xhigh` for the most capability-sensitive workloads, and step down to `medium` or `low` for routine work. Lower effort settings on Claude Fable 5 still perform well and often exceed `xhigh` performance on prior models. At `high` and `xhigh`, set a large `max_tokens`. It's a hard limit on total output (thinking plus response text). See [Cost control](build-with-claude-thinking-steering-and-cost.md#cost-control).
Reduce effort if a task completes but takes longer than necessary, or if you want a faster, more interactive working style. The same recommendations apply to Claude Mythos 5. For fuller guidance, see [Prompting Claude Fable 5](../../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-fable-5.md).
### Recommended effort levels for Claude Opus 5.5
Claude Opus 5.5 supports all five effort levels, and `medium` is the default (Claude Opus 5 and earlier Opus models default to `high`, so a request that omits `effort` runs one level lower than it did on Claude Opus 5). Adaptive thinking is always on and can't be turned off, so effort is the primary control for how much the model reasons and what a request costs. Run an effort sweep on your own evals rather than carrying settings over from an earlier model, and set a large `max_tokens` at the higher levels: it's a hard limit on total output (thinking plus response text). Requests that set `thinking: {"type": "disabled"}` return a 400 error at every effort level. Claude Opus 5.5 also supports [changing effort mid-conversation](#change-effort-mid-conversation-beta) with a per-message `output_config`, which preserves the prompt cache. See [Prompting Claude Opus 5.5](../../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-opus-5-5.md).
### Recommended effort levels for Claude Opus 5
Claude Opus 5 supports all five effort levels. **Start with `high`, the default**, and adjust based on your evals: step up to `xhigh` for demanding coding and agentic work, or to `max` when a task justifies unconstrained token spending, and use `low` and `medium` liberally as your primary control for token cost and response time wherever your evals show quality holds. If you carried effort settings over from an earlier model, run a fresh effort sweep on your evals rather than reusing them.
Effort controls thinking volume, not visible response length: on Claude Opus 5, changing effort does not reliably shorten responses, so [prompt for length](../../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-opus-5.md#response-length-and-verbosity) instead.
The API default is `high`. Set `effort` explicitly to use a different level. The value you pass overrides the default.
On Claude Opus 5, thinking cannot be disabled at `xhigh` or `max` effort: requests that set `thinking: {"type": "disabled"}` at those levels return a 400 error. See [Effort with thinking](#effort-with-thinking).
When running Claude Opus 5 at `xhigh` or `max` effort, set a large `max_tokens` so the model has room to think and act across subagents and tool calls. Starting at 64k tokens and tuning from there is a reasonable default.
Claude Opus 5 also supports [changing effort mid-conversation](#change-effort-mid-conversation-beta) with a per-message `output_config`, which preserves the prompt cache.
### Recommended effort levels for Claude Opus 4.8
The guidance for Claude Opus 4.7 also applies to Claude Opus 4.8. **Start with `xhigh` for coding and agentic use cases**, use `high` for most other intelligence-sensitive workloads, and step down to `medium` or `low` only when you've measured that the lower level holds quality on your evals.
The API default is `high`. Set `effort` explicitly to use a different level. The value you pass overrides the default.
When running Claude Opus 4.8 at `xhigh` or `max` effort, set a large `max_tokens` so the model has room to think and act across subagents and tool calls. Starting at 64k tokens and tuning from there is a reasonable default.
### Recommended effort levels for Claude Opus 4.7
**Start with `xhigh` for coding and agentic use cases**, and use `high` as the minimum for most intelligence-sensitive workloads. Step down to `medium` for cost-sensitive workloads, or up to `max` only when your evals show measurable headroom at `xhigh`.
The API default is `high`. To use `xhigh`, set `effort` explicitly. The value you pass overrides the default.
| Effort | Guidance for Claude Opus 4.7 |
|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `low` | Efficient, but best for short, scoped tasks. Pair `low` with explicit checklists if your task has multiple sections. |
| `medium` | The drop-in for the average workflow where you want good results while reducing costs. |
| `high` | Advanced use cases that still need a balance of intelligence and token consumption. This is often the best balance of quality and token efficiency. |
| `xhigh` | The recommended starting point for coding and agentic work, and for exploratory tasks such as repeated tool calling, detailed web search, and knowledge-base search. Expect meaningfully higher token usage than `high`. |
| `max` | Reserve for frontier problems. On most workloads `max` adds significant cost for relatively small quality gains, and on some structured-output or less intelligence-sensitive tasks it can lead to overthinking. |
Claude Opus 4.7 also respects effort levels more strictly than Claude Opus 4.6, especially at `low` and `medium`. At lower effort levels, the model scopes its work to what was asked rather than doing more than requested. If you observe shallow reasoning on complex problems with Claude Opus 4.7, raise effort rather than prompting around it. If you must keep effort low for latency, add targeted guidance like "This task involves multistep reasoning. Think carefully before responding."
When running Claude Opus 4.7 at `xhigh` or `max` effort, set a large `max_tokens` so the model has room to think and act across subagents and tool calls. Starting at 64k tokens and tuning from there is a reasonable default.
### Recommended effort levels for Claude Sonnet 5
Claude Sonnet 5 defaults to `high` effort on the Claude API and Claude Code.
- **High effort (default):** Suitable for complex reasoning, coding, and agentic tasks where quality matters more than speed or cost.
- **Xhigh effort:** For the hardest coding and agentic tasks. See [Prompting Claude Sonnet 5](../../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-sonnet-5.md#calibrating-effort-and-thinking-depth).
- **Medium effort:** Cost-saving step-down from the default. Comparable to Claude Sonnet 4.6 at high effort.
- **Low effort:** For high-volume or latency-sensitive workloads. Suitable for chat and non-coding use cases where faster turnaround is prioritized.
- **Max effort:** For tasks requiring the absolute highest capability with no constraints on token spending.
### Recommended effort levels for Claude Sonnet 4.6
Sonnet 4.6 defaults to `high` effort. Explicitly set effort when using Sonnet 4.6 to avoid unexpected latency:
- **Medium effort** (recommended default): Best balance of speed, cost, and performance for most applications. Suitable for agentic coding, tool-heavy workflows, and code generation.
- **Low effort:** For high-volume or latency-sensitive workloads. Suitable for chat and non-coding use cases where faster turnaround is prioritized.
- **High effort:** For complex reasoning and tasks where quality matters more than speed or cost.
- **Max effort:** For tasks requiring the absolute highest capability with no constraints on token spending.
## Effort with tool use
When using tools, the effort parameter affects both the explanations around tool calls and the tool calls themselves. Lower effort levels tend to:
- Combine multiple operations into fewer tool calls
- Make fewer tool calls
- Proceed directly to action without preamble
- Use terse confirmation messages after completion
Higher effort levels may:
- Make more tool calls
- Explain the plan before taking action
- Provide detailed summaries of changes
- Include more comprehensive code comments
## Effort with thinking
The `thinking` parameter controls whether Claude thinks in [thinking blocks](build-with-claude-thinking.md) before answering; the `effort` parameter controls how much work Claude puts into the whole response, which in adaptive mode includes how often and how deeply it thinks. Don't pass `adaptive` as an `effort` value: `adaptive` is a thinking mode, not an effort level.
At higher effort levels, Claude thinks more readily and at greater length. In a tool-use loop, follow-up requests that only process tool results can still skip thinking at any level. At lower levels, Claude can skip thinking entirely for simpler problems. See [Thinking and effort](build-with-claude-thinking.md#thinking-and-effort) for full guidance on how the two controls work together.
On Claude Opus 4.5, the only extended-thinking-only model that supports effort, it works alongside [`budget_tokens`](build-with-claude-extended-thinking.md): set the effort level for your task, then set the thinking token budget based on how much reasoning depth the task needs.
For per-model thinking availability, see the [per-model configuration table](build-with-claude-thinking-troubleshooting.md#supported-models). Effort works with or without thinking. See [How effort works](#how-effort-works).
## Change effort mid-conversation
You can run later turns of a conversation at a different effort level in two ways. On Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, and Claude Opus 5, use a per-message effort change, which keeps the prompt cache. On other models, set a new top-level value on the next request, which starts the cache over.
### Per-message effort (beta)
Per-message effort is in beta and requires the [beta header](../Endpoints/beta-headers.md) `mid-conversation-output-config-2026-07-01`. Models without per-message effort, including Claude Fable 5, return a 400 error: `output_config.effort requires a model that supports per-turn effort; this model does not`.
Add a `role: "system"` message with empty `content` and the new level in `output_config.effort`. The new level takes effect from the next `user` turn and holds until a later message changes it. Everything before that message is unchanged, so the cached prefix still matches.
The following example starts at `high`, then drops to `low` for a routine follow-up:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=4096,
output_config={"effort": "high"},
messages=[
{
"role": "user",
"content": "Plan a migration from SQLite to PostgreSQL in three short steps.",
},
{
"role": "assistant",
"content": "1. Export the SQLite data. 2. Create the PostgreSQL schema. 3. Import the data and verify row counts.",
},
# Effort-only system message: the new level takes effect from the next user turn.
{"role": "system", "content": [], "output_config": {"effort": "low"}},
{"role": "user", "content": "Summarize the plan in one sentence."},
],
betas=["mid-conversation-output-config-2026-07-01"],
)
for block in response.content:
if block.type == "text":
print(block.text)
```
An effort-only system message carries no text, so the [placement rules for mid-conversation system messages](build-with-claude-mid-conversation-system-messages.md#limitations) don't apply. It can appear anywhere in `messages`, including as the first entry or between an `assistant` turn and the next `user` turn. Values are the level names (`low`, `medium`, `high`, `xhigh`, and `max`).
On Claude Fable 5.1, prefer this form over changing the top-level value between requests. A top-level change restarts the cache and also steers the model less reliably: its earlier replies were written at the previous level, and it tends to stay consistent with them.
### Top-level effort on the next request
The top-level `output_config.effort` applies to the whole request. To run a later part of a conversation at a different level, set the new value on the next request. Because top-level effort shapes the rendered prompt, changing it between requests doesn't preserve cached prefixes from earlier turns. If you rely on [prompt caching](build-with-claude-prompt-caching.md) across a long session and your model doesn't support per-message effort, pick an effort level at the start and keep it constant.
## Best practices
1. **Set effort explicitly:** The API defaults to `high` (`medium` on Claude Opus 5.5), but the right starting point depends on your model and workload.
2. **Use low for speed-sensitive or simple tasks:** When latency matters or tasks are straightforward, low effort can significantly reduce response times and costs.
3. **Test your use case:** The impact of effort levels varies by task type. Evaluate performance on your specific use cases before deploying.
4. **Consider dynamic effort:** Adjust effort based on task complexity. Simple queries may warrant low effort while agentic coding and complex reasoning benefit from high effort. See the next item before varying it within one conversation.
5. **Hold top-level effort constant within cached conversations:** Changing the top-level effort value between requests invalidates [prompt caching](build-with-claude-prompt-caching.md), so vary it across workloads rather than within a conversation that relies on cache hits. On models that support it, use a [per-message effort change](#change-effort-mid-conversation-beta) instead, which preserves the cache. See [Thinking and prompt caching](build-with-claude-thinking.md#thinking-and-prompt-caching).
## Next steps
[Task budgets](build-with-claude-task-budgets.md)
Give Claude an advisory token budget for the full agentic loop to help the model self-regulate on long agentic tasks.
[Steering thinking](build-with-claude-thinking-steering-and-cost.md)
Understand adaptive thinking, where Claude decides when and how much to think, and steer it with effort and prompting.
[Thinking](build-with-claude-thinking.md)
Understand how thinking works, when Claude thinks by default, and how thinking interacts with effort.
## Compatibility
Supported models
- Fable 5 and 5.1
- Mythos 5, 5.1, and Preview
- Opus 4.5, 4.6, 4.7, 4.8, 5, and 5.5
- Sonnet 4.6 and 5
Supported platforms
- Claude API
- Claude Platform on AWS
- Amazon Bedrock
- Google Cloud
- Microsoft Foundry
---
## Embeddings - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/embeddings
Path: 04-API-Reference/Guides/build-with-claude-embeddings.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fembeddings)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Model capabilities
# Embeddings
Copy page
Text embeddings are numerical representations of text that enable measuring semantic similarity. This guide introduces embeddings, their applications, and how to use embedding models for tasks like search, recommendations, and anomaly detection.
Copy page
## Before implementing embeddings
When selecting an embeddings provider, there are several factors you can consider depending on your needs and preferences:
- Dataset size & domain specificity: size of the model training dataset and its relevance to the domain you want to embed. Larger or more domain-specific data generally produces better in-domain embeddings
- Inference performance: embedding lookup speed and end-to-end latency. This is a particularly important consideration for large scale production deployments
- Customization: options for continued training on private data, or specialization of models for very specific domains. This can improve performance on unique vocabularies
## How to get embeddings with Anthropic
Anthropic does not offer its own embedding model. One embeddings provider that has a wide variety of options and capabilities encompassing all of the preceding considerations is Voyage AI.
Voyage AI makes state-of-the-art embedding models and offers customized models for specific industry domains such as finance and healthcare, or bespoke fine-tuned models for individual customers.
The rest of this guide is for Voyage AI, but you should assess a variety of embeddings vendors to find the best fit for your specific use case.
## Available models
Voyage recommends using the following text embedding models:
**Voyage 4 (latest generation)**
| Model | Context length | Embedding dimension | Description |
|------------------|----------------|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `voyage-4-large` | 32,000 | 1024 (default), 256, 512, 2048 | The best general-purpose and multilingual retrieval quality. See the [Voyage 4 blog post](https://blog.voyageai.com/2026/01/15/voyage-4/) for details. |
| `voyage-4` | 32,000 | 1024 (default), 256, 512, 2048 | Optimized for general-purpose and multilingual retrieval quality. Balances quality and efficiency. See the [Voyage 4 blog post](https://blog.voyageai.com/2026/01/15/voyage-4/) for details. |
| `voyage-4-lite` | 32,000 | 1024 (default), 256, 512, 2048 | Optimized for latency and cost. See the [Voyage 4 blog post](https://blog.voyageai.com/2026/01/15/voyage-4/) for details. |
| `voyage-4-nano` | 32,000 | 1024 (default), 256, 512, 2048 | Open-weight model (Apache 2.0 license) available on Hugging Face. See the [Voyage 4 blog post](https://blog.voyageai.com/2026/01/15/voyage-4/) for details. |
**Previous generation**
| Model | Context length | Embedding dimension | Description |
|--------------------|----------------|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `voyage-3-large` | 32,000 | 1024 (default), 256, 512, 2048 | The best general-purpose and multilingual retrieval quality. See the [voyage-3-large blog post](https://blog.voyageai.com/2025/01/07/voyage-3-large/) for details. |
| `voyage-3.5` | 32,000 | 1024 (default), 256, 512, 2048 | Optimized for general-purpose and multilingual retrieval quality. See the [voyage-3.5 blog post](https://blog.voyageai.com/2025/05/20/voyage-3-5/) for details. |
| `voyage-3.5-lite` | 32,000 | 1024 (default), 256, 512, 2048 | Optimized for latency and cost. See the [voyage-3.5 blog post](https://blog.voyageai.com/2025/05/20/voyage-3-5/) for details. |
| `voyage-code-3` | 32,000 | 1024 (default), 256, 512, 2048 | Optimized for **code** retrieval. See the [voyage-code-3 blog post](https://blog.voyageai.com/2024/12/04/voyage-code-3/) for details. |
| `voyage-finance-2` | 32,000 | 1024 | Optimized for **finance** retrieval and RAG. See the [voyage-finance-2 blog post](https://blog.voyageai.com/2024/06/03/domain-specific-embeddings-finance-edition-voyage-finance-2/) for details. |
| `voyage-law-2` | 16,000 | 1024 | Optimized for **legal** and **long-context** retrieval and RAG. Also improved performance across all domains. See the [voyage-law-2 blog post](https://blog.voyageai.com/2024/04/15/domain-specific-embeddings-and-retrieval-legal-edition-voyage-law-2/) for details. |
Additionally, Voyage recommends the following multimodal embedding models:
| Model | Context length | Embedding dimension | Description |
|-------------------------|----------------|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `voyage-multimodal-3.5` | 32,000 | 1024 (default), 256, 512, 2048 | Rich multimodal embedding model that can vectorize interleaved text, images, and videos. Includes video support as the first production-grade video embedding model. See the [voyage-multimodal-3.5 blog post](https://blog.voyageai.com/2026/01/15/voyage-multimodal-3-5/) for details. |
| `voyage-multimodal-3` | 32,000 | 1024 | Rich multimodal embedding model that can vectorize interleaved text and content-rich images, such as screenshots of PDFs, slides, tables, figures, and more. See the [voyage-multimodal-3 blog post](https://blog.voyageai.com/2024/11/12/voyage-multimodal-3/) for details. |
The following contextualized chunk embedding models produce chunk-level vectors that capture full document context without manual metadata augmentation. Call these models with `contextualized_embed()` instead of `embed()`:
| Model | Context length | Embedding dimension | Description |
|--------------------|----------------|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `voyage-context-4` | 120,000 | 1024 (default), 256, 512, 2048 | Contextualized chunk embeddings optimized for general-purpose and multilingual retrieval quality. See the [voyage-context-4 blog post](https://blog.voyageai.com/2026/06/29/voyage-context-4/) for details. |
| `voyage-context-3` | 120,000 | 1024 (default), 256, 512, 2048 | Contextualized chunk embeddings optimized for general-purpose and multilingual retrieval quality. See the [voyage-context-3 blog post](https://blog.voyageai.com/2025/07/23/voyage-context-3/) for details. |
Voyage AI also offers rerankers, which take a query and a list of documents and return them ranked by relevance to the query. Call these models with `rerank()`:
| Model | Context length | Description |
|-------------------|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| `rerank-2.5` | 32,000 | Highest accuracy. Recommended for most applications. See the [rerank-2.5 blog post](https://blog.voyageai.com/2025/08/11/rerank-2-5/) for details. |
| `rerank-2.5-lite` | 32,000 | Optimized for latency and cost. See the [rerank-2.5 blog post](https://blog.voyageai.com/2025/08/11/rerank-2-5/) for details. |
Need help deciding which text embedding model to use? Check out the [Voyage AI FAQ](https://docs.voyageai.com/docs/faq#what-embedding-models-are-available-and-which-one-should-i-use&ref=anthropic).
## Getting started with Voyage AI
To access Voyage embeddings:
1. Sign up on Voyage AI's website.
2. Obtain an API key.
3. Set the API key as an environment variable for convenience:
```python
export VOYAGE_API_KEY="<your secret key>"
```
You can obtain the embeddings by either using the official [`voyageai` Python package](https://github.com/voyage-ai/voyageai-python) or HTTP requests, as described in the following sections.
### Voyage Python library
Install the `voyageai` package using the following command:
```python
pip install -U voyageai
```
Then, you can create a client object and start using it to embed your texts:
```python
import voyageai
vo = voyageai.Client()
# This will automatically use the environment variable VOYAGE_API_KEY.
# Alternatively, you can use vo = voyageai.Client(api_key="<your secret key>")
texts = ["Sample text 1", "Sample text 2"]
result = vo.embed(texts, model="voyage-4", input_type="document")
print(result.embeddings[0])
print(result.embeddings[1])
```
`result.embeddings` is a list of two embedding vectors, each containing 1024 floating-point numbers. After running the preceding code, the two embeddings are printed on the screen:
``` inline-block
[-0.013131560757756233, 0.019828535616397858, ...] # embedding for "Sample text 1"
[-0.0069352793507277966, 0.020878976210951805, ...] # embedding for "Sample text 2"
```
When creating the embeddings, you can specify a few other arguments to the `embed()` function.
For more information on the Voyage Python package, see the [Voyage Python package documentation](https://docs.voyageai.com/docs/embeddings#python-api).
### Voyage HTTP API
You can also get embeddings by requesting Voyage HTTP API. For example, you can send an HTTP request through the `curl` command in a terminal:
cURL
```python
curl https://api.voyageai.com/v1/embeddings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $VOYAGE_API_KEY" \
-d '{
"input": ["Sample text 1", "Sample text 2"],
"model": "voyage-4"
}'
```
The response you would get is a JSON object containing the embeddings and the token usage:
```python
{
"object": "list",
"data": [
{
"embedding": [-0.013131560757756233, 0.019828535616397858 /* ... */],
"index": 0
},
{
"embedding": [-0.0069352793507277966, 0.020878976210951805 /* ... */],
"index": 1
}
],
"model": "voyage-4",
"usage": {
"total_tokens": 10
}
}
```
For more information on the Voyage HTTP API, see the [Voyage HTTP API documentation](https://docs.voyageai.com/reference/embeddings-api).
### AWS Marketplace
Voyage embeddings are available on [AWS Marketplace](https://aws.amazon.com/marketplace/seller-profile?id=c9032c7b-70dd-459f-834f-c1e23cf3d092). Instructions for accessing Voyage on AWS are available in the [Voyage AWS Marketplace documentation](https://docs.voyageai.com/docs/aws-marketplace-mongodb-voyage?ref=anthropic).
## Quickstart example
The following brief example shows how to use embeddings.
Suppose you have a small corpus of six documents to retrieve from
```python
documents = [
"The Mediterranean diet emphasizes fish, olive oil, and vegetables, believed to reduce chronic diseases.",
"Photosynthesis in plants converts light energy into glucose and produces essential oxygen.",
"20th-century innovations, from radios to smartphones, centered on electronic advancements.",
"Rivers provide water, irrigation, and habitat for aquatic species, vital for ecosystems.",
"Apple's conference call to discuss fourth fiscal quarter results and business updates is scheduled for Thursday, November 2, 2023 at 2:00 p.m. PT / 5:00 p.m. ET.",
"Shakespeare's works, like 'Hamlet' and 'A Midsummer Night's Dream,' endure in literature.",
]
```
First, use Voyage to convert each document into an embedding vector.
```python
import voyageai
vo = voyageai.Client()
# Embed the documents
doc_embds = vo.embed(documents, model="voyage-4", input_type="document").embeddings
```
The embeddings allow you to do semantic search / retrieval in the vector space. Given an example query,
```python
query = "When is Apple's conference call scheduled?"
```
Next, convert it into an embedding and conduct a nearest neighbor search to find the most relevant document based on the distance in the embedding space.
```python
import numpy as np
# Embed the query
query_embd = vo.embed([query], model="voyage-4", input_type="query").embeddings[0]
# Compute the similarity
# Voyage embeddings are normalized to length 1, therefore dot-product
# and cosine similarity are the same.
similarities = np.dot(doc_embds, query_embd)
retrieved_id = np.argmax(similarities)
print(documents[retrieved_id])
```
Note that `input_type="document"` and `input_type="query"` are used for embedding the document and query, respectively. More specification can be found in [Voyage Python library](#voyage-python-library).
The output is the fifth document, which is indeed the most relevant to the query:
``` block
Apple's conference call to discuss fourth fiscal quarter results and business updates is scheduled for Thursday, November 2, 2023 at 2:00 p.m. PT / 5:00 p.m. ET.
```
If you are looking for a detailed set of recipes on how to do RAG with embeddings, including vector databases, check out the [RAG recipe](https://platform.claude.com/cookbook/third-party-pinecone-rag-using-pinecone).
## FAQ
### Why do Voyage embeddings have superior quality?
Embedding models rely on powerful neural networks to capture and compress semantic context, similar to generative models. Voyage's team of experienced AI researchers optimizes every component of the embedding process, including:
- Model architecture
- Data collection
- Loss functions
- Optimizer selection
Learn more about Voyage's technical approach on the [Voyage AI blog](https://blog.voyageai.com/).
### What embedding models are available and which should I use?
For general-purpose embedding, the recommended models are:
- `voyage-4-large`: Best quality
- `voyage-4-lite`: Lowest latency and cost
- `voyage-4`: Balanced performance
For retrieval, use the `input_type` parameter to specify whether the text is a query or document type.
Domain-specific models:
- Legal tasks: `voyage-law-2`
- Code and programming documentation: `voyage-code-3`
- Finance-related tasks: `voyage-finance-2`
For chunk-level and document-level retrieval: `voyage-context-4`
### Which similarity function should I use?
You can use Voyage embeddings with either dot-product similarity, cosine similarity, or Euclidean distance. For an explanation of embedding similarity, see this [vector similarity guide](https://www.pinecone.io/learn/vector-similarity/).
Voyage AI embeddings are normalized to length 1, which means that:
- Cosine similarity is equivalent to dot-product similarity, while the latter can be computed more quickly.
- Cosine similarity and Euclidean distance result in identical rankings.
### What is the relationship between characters, words, and tokens?
See the [Voyage tokenization guide](https://docs.voyageai.com/docs/tokenization?ref=anthropic).
### When and how should I use the input_type parameter?
For all retrieval tasks and use cases (for example, RAG), use the `input_type` parameter to specify whether the input text is a query or document. Do not omit `input_type` or set `input_type=None`. Specifying whether input text is a query or document can create better dense vector representations for retrieval, which can lead to better retrieval quality.
When using the `input_type` parameter, special prompts are prepended to the input text prior to embedding. Specifically:
> 📘 **Prompts associated with `input_type`**
>
> - For a query, the prompt is “Represent the query for retrieving supporting documents: “.
> - For a document, the prompt is “Represent the document for retrieval: “.
> - Example
> - When `input_type="query"`, a query like "When is Apple's conference call scheduled?" will become "**Represent the query for retrieving supporting documents:** When is Apple's conference call scheduled?"
> - When `input_type="document"`, a query like "Apple's conference call to discuss fourth fiscal quarter results and business updates is scheduled for Thursday, November 2, 2023 at 2:00 p.m. PT / 5:00 p.m. ET." will become "**Represent the document for retrieval:** Apple's conference call to discuss fourth fiscal quarter results and business updates is scheduled for Thursday, November 2, 2023 at 2:00 p.m. PT / 5:00 p.m. ET."
`voyage-large-2-instruct`, as the name suggests, is trained to be responsive to additional instructions that are prepended to the input text. For classification, clustering, or other [MTEB](https://huggingface.co/mteb) subtasks, use the [voyage-large-2-instruct instructions](https://github.com/voyage-ai/voyage-large-2-instruct).
### What quantization options are available?
Quantization in embeddings converts high-precision values, such as 32-bit single-precision floating-point numbers, to lower-precision formats such as 8-bit integers or 1-bit binary values, reducing storage, memory, and costs by 4x and 32x, respectively. Supported Voyage models enable quantization by specifying the output data type with the `output_dtype` parameter:
- `float`: Each returned embedding is a list of 32-bit (4-byte) single-precision floating-point numbers. This is the default and provides the highest precision / retrieval accuracy.
- `int8` and `uint8`: Each returned embedding is a list of 8-bit (1-byte) integers ranging from -128 to 127 and 0 to 255, respectively.
- `binary` and `ubinary`: Each returned embedding is a list of 8-bit integers that represent bit-packed, quantized single-bit embedding values: `int8` for `binary` and `uint8` for `ubinary`. The length of the returned list of integers is 1/8 of the actual dimension of the embedding. The binary type uses the offset binary method, which you can learn more about in the [embeddings FAQ](#faq).
> **Binary quantization example**
>
> Consider the following eight embedding values: -0.03955078, 0.006214142, -0.07446289, -0.039001465, 0.0046463013, 0.00030612946, -0.08496094, and 0.03994751. With binary quantization, values less than or equal to zero will be quantized to a binary zero, and positive values to a binary one, resulting in the following binary sequence: 0, 1, 0, 0, 1, 1, 0, 1. These eight bits are then packed into a single 8-bit integer, 01001101 (with the leftmost bit as the most significant bit).
>
> - `ubinary`: The binary sequence is directly converted and represented as the unsigned integer (`uint8`) 77.
> - `binary`: The binary sequence is represented as the signed integer (`int8`) -51, calculated using the offset binary method (77 - 128 = -51).
### How can I truncate Matryoshka embeddings?
Matryoshka learning creates embeddings with coarse-to-fine representations within a single vector. Voyage models, such as `voyage-code-3`, that support multiple output dimensions generate such Matryoshka embeddings. You can truncate these vectors by keeping the leading subset of dimensions. For example, the following Python code demonstrates how to truncate 1024-dimensional vectors to 256 dimensions:
```python
import voyageai
import numpy as np
def embd_normalize(v: np.ndarray) -> np.ndarray:
"""
Normalize the rows of a 2D numpy array to unit vectors by dividing each row by its Euclidean
norm. Raises a ValueError if any row has a norm of zero to prevent division by zero.
"""
row_norms = np.linalg.norm(v, axis=1, keepdims=True)
if np.any(row_norms == 0):
raise ValueError("Cannot normalize rows with a norm of zero.")
return v / row_norms
vo = voyageai.Client()
# Generate voyage-code-3 vectors, which by default are 1024-dimensional floating-point numbers
embd = vo.embed(["Sample text 1", "Sample text 2"], model="voyage-code-3").embeddings
# Set shorter dimension
short_dim = 256
# Resize and normalize vectors to shorter dimension
resized_embd = embd_normalize(np.array(embd)[:, :short_dim]).tolist()
```
## Pricing
Visit Voyage's [pricing page](https://docs.voyageai.com/docs/pricing?ref=anthropic) for the most up to date pricing details.
---
## Extended thinking - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/extended-thinking
Path: 04-API-Reference/Guides/build-with-claude-extended-thinking.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fextended-thinking)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
[Overview](build-with-claude-thinking.md)[Steering and cost control](build-with-claude-thinking-steering-and-cost.md)[Tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md)[Preserved thinking](build-with-claude-preserved-thinking.md)[Troubleshooting](build-with-claude-thinking-troubleshooting.md)[Extended thinking (legacy)](build-with-claude-extended-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Thinking
# Extended thinking
Copy page
Configure manual extended thinking with a fixed budget_tokens budget on Claude models that support it, and migrate to adaptive thinking.
Copy page
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
Extended thinking (`thinking.type: "enabled"` with `budget_tokens`) is deprecated on the Claude 4.6 models (requests using it still succeed). Claude 4.7 and later models do not support it and reject requests that use it, returning a 400 error. On Claude 4.5 and earlier models that support thinking, extended thinking is the only available thinking mode. Claude Mythos Preview supports both modes. Where both modes are available, use [adaptive thinking](build-with-claude-thinking.md) instead.
See [Migrating to adaptive thinking](#migrating-to-adaptive-thinking) to move to adaptive thinking. If your model supports only extended thinking, this page describes the supported configuration; no change is needed until you move to a newer model.
If a request fails with a 400 error whose message starts with `"thinking.type.enabled" is not supported`, your model uses adaptive thinking instead. See [Troubleshooting thinking](build-with-claude-thinking-troubleshooting.md#error-thinking-type-enabled), or jump to [Migrating to adaptive thinking](#migrating-to-adaptive-thinking).
Extended thinking in manual mode gives you direct control over how much Claude thinks. You set a thinking token budget on each request with `thinking: {type: "enabled", budget_tokens: N}`, and Claude thinks against that budget before it starts its final answer. Manual mode remains useful when your workload requires predictable latency or precise control over thinking costs. This page covers how to set and tune the budget, how manual mode interacts with interleaved thinking and prompt caching, and how to migrate to adaptive thinking.
To learn how thinking itself works, including thinking blocks and the response shape, the `display` parameter, streaming, thinking with tool use, and encryption, see the [thinking overview](build-with-claude-thinking.md).
## Supported models
Extended thinking availability per model, including the models where extended thinking is the only mode, is listed in the [per-model configuration table](build-with-claude-thinking-troubleshooting.md#supported-models).
## How to use extended thinking
Here is an example of using extended thinking in the Messages API:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 10000},
messages=[
{
"role": "user",
"content": "Are there an infinite number of prime numbers such that n mod 4 == 3?",
}
],
)
# The response contains summarized thinking blocks and text blocks
for block in response.content:
match block.type:
case "thinking":
print(f"\nThinking summary: {block.thinking}")
case "text":
print(f"\nResponse: {block.text}")
```
To turn on manual extended thinking, add a `thinking` object with `type` set to `enabled` and a `budget_tokens` value.
The `budget_tokens` parameter sets a target for how many tokens Claude can use for its internal reasoning process. Larger budgets can improve response quality by enabling more thorough analysis for complex problems.
## Budget rules and tuning
`budget_tokens` must satisfy these constraints:
- **Minimum of 1,024 tokens.** The API rejects smaller values.
- **Less than `max_tokens`.** Thinking tokens count toward the `max_tokens` limit for the turn, so the budget must leave room for the final response. The one exception is [interleaved thinking](#interleaved-thinking), where `budget_tokens` can exceed `max_tokens` because the budget spans all thinking blocks within one assistant turn.
- **No cache pre-warming.** Because `budget_tokens` must be less than `max_tokens`, extended thinking cannot be combined with `max_tokens: 0` ([cache pre-warming](build-with-claude-prompt-caching.md#pre-warming-the-cache)).
The budget is a target rather than a strict cap. Actual token usage varies with the task, and Claude may stop reasoning well before the budget is exhausted; `max_tokens` remains the hard ceiling on total output.
On Claude Opus 4.5, the only extended-thinking-only model that supports [effort](build-with-claude-effort.md), effort shapes the overall response while `budget_tokens` sets thinking depth; set both.
To tune the budget:
- Match the starting point to the task. For simple tasks, start near the 1,024-token minimum and increase incrementally to find the optimal range for your use case. For complex tasks, start with a larger budget of 16,000 tokens or more and adjust to your latency and quality needs. Higher budgets enable more comprehensive reasoning, with diminishing returns that depend on the task, and at the cost of increased latency. For critical tasks, test different settings to find the right balance.
- For thinking budgets above 32k, use [batch processing](build-with-claude-batch-processing.md) to avoid networking issues. Pushing the model to think beyond 32k tokens produces long-running requests that can hit system timeouts and open-connection limits.
To track what a budget actually costs you, monitor the `usage.output_tokens_details.thinking_tokens` field in the response, which reports how many of the billed output tokens were internal reasoning. When streaming, this breakdown appears only on the final `message_delta` event.
When you are ready to move off manual budgets, see [Migrating to adaptive thinking](#migrating-to-adaptive-thinking).
## Interleaved thinking in manual mode
Interleaved thinking lets Claude think between tool calls within a single assistant turn, reasoning about each tool result before deciding what to do next. For the concept, the turn structure, and how it behaves on adaptive-thinking models, see [interleaved thinking](build-with-claude-thinking.md#interleaved-thinking) in the thinking overview. This section covers how to enable it when you use manual `type: "enabled"` thinking.
On Claude Opus 4.5, Claude Sonnet 4.5, and earlier Claude 4 models, add the `interleaved-thinking-2025-05-14` [beta header](../Endpoints/beta-headers.md) to your API request.
The 4.6 generation splits in manual mode:
- **Claude Sonnet 4.6**: the beta header with manual `type: "enabled"` is still functional but deprecated. Prefer [adaptive thinking](build-with-claude-thinking.md), which interleaves automatically with no header.
- **Claude Opus 4.6**: manual mode has no interleaved thinking at all. Only its adaptive mode interleaves, so switch to `thinking: {type: "adaptive"}` if you need reasoning between tool calls on this model.
Claude Haiku 4.5 does not support interleaved thinking. On the Claude API, the beta header is accepted but ignored.
Two more considerations for interleaved thinking in manual mode:
- `budget_tokens` can exceed `max_tokens` here; the [budget rules](#budget-rules-and-tuning) explain this exception.
- Interleaved thinking is only supported for [tools used through the Messages API](../Agents-Tools/agents-and-tools-tool-use-overview.md).
How platforms treat the beta header differs. The Claude API and [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md) accept `interleaved-thinking-2025-05-14` on any model and ignore it where unsupported. Acceptance is not the same as effect: on models that reject `type: "enabled"` (4.7 and later) or lack manual-mode interleaving (Claude Opus 4.6), the header has no manual-mode effect; adaptive thinking interleaves automatically there.
Partner-operated platforms ([Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md) and [Google Cloud](build-with-claude-claude-on-vertex-ai.md)) likewise accept the header on any model without returning an error, and ignore it on models that don't support interleaved thinking.
## Turn structure in manual mode
The general turn-structure rules, including the single-turn tool-use loop, mid-turn conflict handling, and toggling thinking between turns, are on [Thinking with tool use](build-with-claude-thinking.md#thinking-with-tool-use).
Manual mode adds one requirement: the final assistant turn of a thinking-enabled request must begin with a thinking block ([adaptive thinking](build-with-claude-thinking.md) drops that requirement). Changing the thinking configuration between turns also invalidates prompt caching; see the following section.
## Prompt caching in manual mode
Manual mode adds one rule on top of the mode-neutral caching behavior described in [thinking and prompt caching](build-with-claude-thinking.md#thinking-and-prompt-caching): changing `budget_tokens` between requests invalidates cache breakpoints, just as switching thinking modes does, because the budget value is rendered into the prompt. Message-level breakpoints always miss after a budget change; whether tool and system-prompt breakpoints miss too depends on where the model renders the configuration.
In practice, pick a budget and hold it stable for the life of a cached conversation. Running a multi-turn conversation with message-level caching on Claude Sonnet 4.6 and changing the budget on the third request from 4,000 to 8,000 tokens shows the invalidation directly:
Output
``` block
First request - establishing cache
First response usage: { cache_creation_input_tokens: 1370, cache_read_input_tokens: 0, input_tokens: 17, output_tokens: 700 }
Second request - same thinking parameters (cache hit expected)
Second response usage: { cache_creation_input_tokens: 0, cache_read_input_tokens: 1370, input_tokens: 303, output_tokens: 874 }
Third request - different thinking budget (cache miss expected)
Third response usage: { cache_creation_input_tokens: 1370, cache_read_input_tokens: 0, input_tokens: 747, output_tokens: 619 }
```
The third request re-creates the cache (`cache_creation_input_tokens=1370`, `cache_read_input_tokens=0`) because the budget changed between requests. For a runnable version of the same experiment in adaptive mode, where the effort level plays the cache role that `budget_tokens` plays here, see [Prompt caching](build-with-claude-thinking-steering-and-cost.md#prompt-caching) on the steering page.
## Shared mechanics
Most thinking behavior is mode neutral and documented once on the [Thinking](build-with-claude-thinking.md) page. Everything there applies in manual mode too:
- [Controlling thinking display](build-with-claude-thinking.md#controlling-thinking-display)
- [Streaming thinking](build-with-claude-thinking.md#streaming-thinking)
- [Thinking with tool use](build-with-claude-thinking.md#thinking-with-tool-use), including [preserving thinking blocks](build-with-claude-thinking.md#preserving-thinking-blocks)
- [Thinking and prompt caching](build-with-claude-thinking.md#thinking-and-prompt-caching)
- [Thinking and the context window](build-with-claude-thinking.md#thinking-and-the-context-window)
- [Thinking encryption](build-with-claude-thinking.md#thinking-encryption)
- [Pricing](build-with-claude-thinking-steering-and-cost.md#pricing) (on the [Steering thinking](build-with-claude-thinking-steering-and-cost.md) page)
## Migrating to adaptive thinking
If your model supports only extended thinking (Claude Sonnet 4.5, Claude Opus 4.5, Claude Haiku 4.5, and earlier Claude 4 models), no action is needed now: adaptive thinking is not available there, and `type: "adaptive"` [returns a 400 error](build-with-claude-thinking-troubleshooting.md#error-thinking-type-adaptive). Keep `budget_tokens` until you move to a model that supports adaptive thinking, then apply the mapping that follows.
You need to migrate off `type: "enabled"` if:
- You use Claude Opus 4.6 or Claude Sonnet 4.6, where `budget_tokens` is deprecated.
- You use Claude 4.7 or a later model, such as Claude Opus 5.5, Claude Sonnet 5, or Claude Fable 5.1, where `type: "enabled"` returns a 400 error.
The mapping is small: remove `budget_tokens`, set `thinking: {type: "adaptive"}`, and control reasoning depth with `output_config: {effort: ...}` instead of a token budget.
```python
{
"model": "claude-sonnet-4-6",
"max_tokens": 16000,
"thinking": {
"type": "enabled",
"budget_tokens": 10000
}
}
```
becomes:
```python
{
"model": "claude-sonnet-4-6",
"max_tokens": 16000,
"thinking": {
"type": "adaptive"
},
"output_config": {
"effort": "high"
}
}
```
`effort: "high"` matches the API default; it appears here only to show where the depth control now lives, and omitting it produces identical behavior.
Expect a behavioral difference, not just a syntax change. With a fixed budget, Claude thinks on every request. With adaptive thinking, Claude decides whether and how much to think on each request, and at lower [effort](build-with-claude-effort.md) settings it may skip thinking entirely on easy inputs. You can also remove the `interleaved-thinking-2025-05-14` beta header after migrating: adaptive thinking interleaves automatically, and the Claude API ignores the header on these models. Thinking block preservation changes too: Claude Opus 4.5 and models numbered 4.6 and higher keep prior turns' thinking blocks in context and bill them as input, where Claude Sonnet 4.5, Claude Haiku 4.5, and earlier models stripped them; see [thinking block preservation by model](build-with-claude-thinking.md#thinking-block-preservation-by-model).
Switching modes is a thinking-configuration change, so the first request after the switch invalidates cache breakpoints, as described in [Prompt caching in manual mode](#extended-thinking-with-prompt-caching).
For full guidance, see [adaptive thinking](build-with-claude-thinking.md), [effort](build-with-claude-effort.md), and the [model migration guide](../../20-Models/about-claude-models-migration-guide.md).
## Next steps
[Thinking](build-with-claude-thinking.md)
Learn how thinking works: blocks, display, streaming, and tool use.
[Steering thinking](build-with-claude-thinking-steering-and-cost.md)
Let Claude decide when and how much to think on each request.
[Thinking in tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md)
Preserve thinking blocks and manage thinking across tool calls and turns.
---
## Fallback credit - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/fallback-credit
Path: 04-API-Reference/Guides/build-with-claude-fallback-credit.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Ffallback-credit)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Building with Claude
# Fallback credit
Copy page
Avoid paying the prompt-cache cost twice when you retry a refused request on another model.
Copy page
Prompt caches are per-model. When a model declines a request and you retry on another model, the conversation prefix already cached for the first model must be written into the new model's cache from scratch. Cache writes cost more than cache reads. Fallback credit removes that extra cost. The refusal carries a credit token, you echo the token on the retry, and the retry is billed as though the conversation had been on the new model all along.
You need this page only when you build the retry yourself: over raw HTTP or with custom retry logic. [Server-side fallback](build-with-claude-refusals-and-fallback.md#server-side-fallback) and the [SDK middleware](build-with-claude-refusals-and-fallback.md#client-side-fallback) apply fallback credit automatically. If you use either, skip this page.
[Refusals and fallback](build-with-claude-refusals-and-fallback.md) covers detecting refusals and choosing a fallback approach. [Prompt caching](build-with-claude-prompt-caching.md) explains cache reads and cache writes if those terms are new.
## The basic flow
1. 1
### Opt in with the beta header
Send the request that may be refused with the `anthropic-beta: fallback-credit-2026-07-01` header. The `server-side-fallback-2026-07-01` header also grants the same fields, and the earlier `fallback-credit-2026-06-01` header remains accepted and grants the same fields.
2. 2
### Read two fields from the refusal
On a refusal, `stop_details` includes two fields:
- **`fallback_credit_token`:** an opaque string that represents the credit.
- **`fallback_has_prefill_claim`:** a Boolean that tells you which retry body shape to use.
Both are `null` when no credit is available for the refusal.
3. 3
### Build the retry
Start from the refused request body. Set `model` to the fallback model and add the token as the top-level `fallback_credit_token` parameter. Pick the body shape from the following table.
4. 4
### Send the retry with the same header
Send the retry with the same `fallback-credit-2026-07-01` beta header. The retry needs the header to redeem the token.
The `fallback_has_prefill_claim` field tells you whether the retry can continue the refused model's partial output instead of starting over:
| `fallback_has_prefill_claim` | Retry body |
|:-----------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `true` | The refused request body, unchanged, plus one appended assistant message whose `content` echoes the refused response's `content`. The retry model continues the response from where the refused model stopped, and completed server tool calls are not re-executed. |
| `false` | The refused request body, unchanged. |
## Example
The following example makes a request that may be refused and redeems the credit token on a retry against Claude Opus 4.8. When a retry attempt is rejected, the example degrades through the rejection ladder: the sequence of progressively simpler retry shapes covered in [When a retry is rejected](#when-a-retry-is-rejected).
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = Anthropic()
request = {
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello, Claude"}],
}
def send(model: str, body: dict[str, object]) -> BetaMessage:
return client.beta.messages.create(
model=model, betas=["fallback-credit-2026-07-01"], **body
)
response = send("claude-fable-5", request)
if (
response.stop_reason == "refusal"
and (details := response.stop_details)
and (token := details.fallback_credit_token)
):
exact_body = request | {"fallback_credit_token": token}
# Prefer the continuation shape unless the claim is False
if details.fallback_has_prefill_claim is not False:
echoed = [block.model_dump() for block in response.content]
match echoed:
case [*_, {"type": "text"} as final_block]:
final_block["text"] = final_block["text"].rstrip()
attempt = exact_body | {
"messages": [
*request["messages"],
{"role": "assistant", "content": echoed},
]
}
else:
attempt = exact_body
try:
response = send("claude-opus-4-8", attempt)
except BadRequestError as error:
if "redemption temporarily unavailable" in error.message:
raise # Transient: retry with the token within its five-minute window
try:
# Fall back to the unchanged body, still with the token
response = send("claude-opus-4-8", exact_body)
except BadRequestError as retry_error:
if "redemption temporarily unavailable" in retry_error.message:
raise # Transient: retry with the token within its five-minute window
# The token itself was rejected: forfeit it and retry without.
response = send("claude-opus-4-8", request)
print(json.dumps({"stop_reason": response.stop_reason, "model": response.model}))
```
## Where it works
Fallback credit is in beta on the Claude API, Amazon Bedrock, Claude Platform on AWS, Google Cloud, and Microsoft Foundry. Refusals in [Message Batches](build-with-claude-batch-processing.md) don't mint credit tokens, and redemption applies only to direct Messages API requests: a token passed on a batch request is accepted but ignored.
The retry model must be one of the refused model's permitted fallback targets. For Claude Fable 5.1 and Claude Fable 5, those are Claude Opus 4.8 (`claude-opus-4-8`) and Claude Opus 5 (`claude-opus-5`).
### Looking up permitted fallback targets programmatically
On the Claude API and Claude Platform on AWS, the target list is published as `allowed_fallback_models` on each model's entry in the [Models API](../Endpoints/models-list.md) when the `server-side-fallback-2026-07-01` beta header is set. The list is not yet visible under the `fallback-credit-*` header alone. It is not exposed on Amazon Bedrock, Google Cloud, or Microsoft Foundry.
## Checking that the credit applied
The refund is visible in the retry's `usage`. Compared with what the same request would report without the token, `cache_creation_input_tokens` is lower, and `cache_read_input_tokens` is higher by the same amount. A shift of zero means the token was honored but there was nothing to reprice, for example because the retry model's cache was already warm.
## When a retry is rejected
Most retries redeem on the first attempt. When one does not, the API returns a 400 error that tells you what to try next.
1. 1
### Continuation rejected: resend the unchanged body
If the retry that appends the assistant message is rejected with a 400 error, resend the refused request body unchanged, still with the token.
2. 2
### Token rejected: drop the token
If the unchanged body is also rejected with a 400 error whose message names `fallback_credit_token`, retry without the token. The credit is forfeited, but the retry itself goes through.
If the refused request executed server tools, a tokenless retry re-runs and re-bills those tools. In that case, surface the 400 error to your caller instead of falling through to a tokenless retry.
### If the error says 'redemption temporarily unavailable'
This rejection is transient, not a verdict on your retry shape. Retry the same request, with the same token, within the token's five-minute window. Do not move to the next step of the ladder.
## Reference
The following sections cover edge cases and the complete redemption rules. Most integrations do not need them.
### Fields that must match the refused request
Redemption compares the retry against the refused request. Every field that shapes the prompt must match exactly. Fields that do not shape the prompt may change on the retry.
| Rule | Fields |
|:------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Must match exactly | `system`, `messages`, `tools`, `tool_choice`, `thinking`, and `cache_control`, plus `output_config`, `mcp_servers`, `context_management`, and `container` when you use them |
| May change on the retry | `model`, `max_tokens`, `stop_sequences`, `temperature`, `top_p`, `top_k`, `stream`, `metadata`, and `service_tier` |
The continuation shape (`fallback_has_prefill_claim: true`) is the one exception to the `messages` match: it adds exactly one assistant message at the end of `messages`.
Do not strip `thinking` or `redacted_thinking` blocks from earlier turns on the retry, even though a plain retry without a token usually strips them. The body must match the refused request, and the server handles those blocks itself.
### Beta headers must match too
Send the same `anthropic-beta` headers on the retry as on the refused request. A beta header present on one of the two requests but not the other can fail the match even when the bodies are identical. The resulting 400 error carries the same `request body ... does not match` message as a body difference, so a header difference is easy to misread as a body problem. In particular, do not add or drop beta headers based on which model the request targets.
Two header families are exempt from the match, for the retry's sake:
- **`server-side-fallback-*`:** a retry must drop the `fallbacks` parameter, and dropping this header along with it does not cause a mismatch.
- **`fallback-credit-*`:** keep this header on both requests. The retry needs it to redeem the token.
On models that include the 1M token context window by default, such as Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, and Claude Opus 4.8, the `context-1m-2025-08-07` beta header has no effect. To keep the two requests identical, omit that header on both rather than sending it on one and not the other.
### When fallback_has_prefill_claim is absent
The field is `null` only when the token is also `null`, so a value you observe while holding a token is never `null`. It can still be absent (`None` in the typed SDKs) on Amazon Bedrock, Google Cloud, and Microsoft Foundry while their support for the field rolls out. In that case, treat the retry shape as unknown rather than as `false`. Try the appended-assistant-message shape first, and rely on the rejection handling in [When a retry is rejected](#when-a-retry-is-rejected), which falls back to the unchanged body.
### Echoing the refused response's content
When a refusal's token supports the continuation shape, the response `content` carries only the model's own output, and the refusal explanation is delivered in `stop_details.explanation`. You can therefore echo `content` into the appended assistant message as-is.
Two adjustments may still be needed before sending:
- If the final block you send is a `text` block, strip its trailing whitespace.
- Omit any client-side `tool_use` block that has no matching `tool_result`.
If the echoed content includes a `fallback` block from an earlier [server-side fallback](build-with-claude-refusals-and-fallback.md#server-side-fallback), keep the block exactly where it appeared. It is accepted on any request without a beta header. The API uses its position to validate the thinking blocks around it, so a request that echoes thinking blocks from both sides of that boundary is rejected if the block is omitted or moved.
### Token scope and lifetime
The token redeems only from the organization and workspace that received the refusal, including on Microsoft Foundry. On Amazon Bedrock and Google Cloud, which do not have workspaces, the token is bound to the platform's caller identity instead.
The token expires five minutes after the refusal. After that, send the retry without it. The token is also stateless: the server stores nothing about it, and there is no endpoint to inspect or revoke it.
### When a token cannot be redeemed by either shape
When the refusal arrived after server tools had already executed within the request, the token redeems only by continuing the partial response. That restriction is what prevents the completed tool calls from running, and billing, again.
One combination can therefore leave the token unredeemable by either shape, when both of the following are true:
- The request used `output_config.format` or a `tool_choice` that forces tool use. Either one rules out the appended-assistant-message shape.
- The refusal arrived after server tools had executed. That rules out the unchanged body.
If the unchanged-body retry is rejected with a 400 error saying the token must be redeemed by continuing the partial response, discard the token. A retry without it goes through, but it re-runs and re-bills the completed server tools. Surface the cost or the error to your caller rather than retrying silently.
## Next steps
[Refusals and fallback](build-with-claude-refusals-and-fallback.md)
Detect refusals and choose between server-side fallback, the SDK middleware, and a manual retry.
[Prompt caching](build-with-claude-prompt-caching.md)
How cache reads and cache writes are billed.
[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)
Every `stop_reason` value and how to handle it.
[SDK middleware](../Other/cli-sdks-libraries-middleware.md)
The SDK helper that applies fallback credit automatically.
---
## Fast mode (research preview) - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/fast-mode
Path: 04-API-Reference/Guides/build-with-claude-fast-mode.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Ffast-mode)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Model capabilities
# Fast mode (research preview)
Copy page
Get up to 2.5x higher output tokens per second from supported Claude Opus models.
Copy page
Fast mode delivers up to 2.5x higher output tokens per second from Claude Opus 5.5, Claude Opus 5, and Claude Opus 4.8 at premium pricing. Set `speed: "fast"` with the `fast-mode-2026-02-01` beta header on your request to opt in.
Fast mode is in research preview. Contact your account manager to request access. If you do not have an account manager, [join the waitlist](https://claude.com/fast-mode) for fast mode.
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
## Supported models
Fast mode is supported on the following models:
- Claude Opus 5.5 (
claude-opus-5-5
)
- Claude Opus 5 (
claude-opus-5
)
- Claude Opus 4.8 (
claude-opus-4-8
)
Fast mode for Claude Opus 5.5, Claude Opus 5, and Claude Opus 4.8 is available as a research preview on the Claude API, including [Claude Managed Agents](../Other/managed-agents-overview.md), only. It is not available on Amazon Bedrock, Claude Platform on AWS, Google Cloud, or Microsoft Foundry.
Fast mode is not available on Claude Opus 4.7. Requests to `claude-opus-4-7` with `speed: "fast"` return an error; unlike Claude Opus 4.6 (see the following note), requests do not fall back to standard speed. The model itself remains available at standard speed. To continue using fast mode, see [Migrating to Claude Opus 5.5 from Claude Opus 4.7](../../20-Models/models-opus-5-5-migration-guide.md#migrating-from-claude-opus-47).
Fast mode is not available on Claude Opus 4.6. Requests to `claude-opus-4-6` with `speed: "fast"` do not return an error: they run at standard speed and are billed at [standard rates](../../17-Billing-Plans/about-claude-pricing.md) rather than fast mode's premium rates, and the response reports [`usage.speed: "standard"`](#checking-which-speed-was-used). To continue using fast mode, see [Migrating to Claude Opus 5.5 from Claude Opus 4.6 and earlier Opus models](../../20-Models/models-opus-5-5-migration-guide.md#migrating-from-claude-opus-46).
## How fast mode works
Fast mode runs the same model with a faster inference configuration. There is no change to intelligence or capabilities.
- Up to 2.5x higher output tokens per second compared to standard speed
- Speed benefits are focused on output tokens per second (OTPS), not time to first token (TTFT)
- Same model weights and behavior (not a different model)
- Compatible with [streaming](build-with-claude-streaming.md), where the OTPS gain is most visible
## Basic usage
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
speed="fast",
betas=["fast-mode-2026-02-01"],
messages=[
{"role": "user", "content": "Refactor this module to use dependency injection"}
],
)
for block in response.content:
if block.type == "text":
print(block.text)
```
## Pricing
Fast mode is priced at a multiplier on standard rates across the full context window, including requests over 200k input tokens. The following table shows fast mode pricing for the supported models:
| Model | Input | Output |
|:--------------------------------|:----------------|:----------------|
| Claude Opus 5.5 | \$8 USD / MTok | \$40 USD / MTok |
| Claude Opus 5 / Claude Opus 4.8 | \$10 USD / MTok | \$50 USD / MTok |
Fast mode pricing stacks with other pricing modifiers:
- [Prompt caching multipliers](../../17-Billing-Plans/about-claude-pricing.md#prompt-caching) apply on top of fast mode pricing
- [Data residency](build-with-claude-data-residency.md) multipliers apply on top of fast mode pricing
For complete pricing details, see the [Pricing](../../17-Billing-Plans/about-claude-pricing.md#fast-mode-pricing) page.
## Rate limits
Fast mode has a dedicated rate limit that is separate from standard Opus rate limits. When your fast mode rate limit is exceeded, the API returns a `429` error with a `retry-after` header indicating when capacity will be available.
The response includes headers that indicate your fast mode rate limit status:
| Header | Description |
|:-----------------------------------------|:--------------------------------------------------|
| `anthropic-fast-input-tokens-limit` | Maximum fast mode input tokens per minute |
| `anthropic-fast-input-tokens-remaining` | Remaining fast mode input tokens |
| `anthropic-fast-input-tokens-reset` | Time when the fast mode input token limit resets |
| `anthropic-fast-output-tokens-limit` | Maximum fast mode output tokens per minute |
| `anthropic-fast-output-tokens-remaining` | Remaining fast mode output tokens |
| `anthropic-fast-output-tokens-reset` | Time when the fast mode output token limit resets |
For tier-specific rate limits, see the [Rate limits](../Endpoints/rate-limits.md) page.
## Checking which speed was used
The response `usage` object includes a `speed` field that indicates which speed was used, either `"fast"` or `"standard"`. Requesting `speed: "fast"` on a [model that doesn't support fast mode](#supported-models) returns an error, and so does exceeding fast mode's rate limits or capacity (a `429` or `529`). When a request with `speed: "fast"` succeeds, `usage.speed` is `"fast"`. If you are using Claude Opus 4.6 and request fast mode, its behavior is unique. Instead of returning an error like other models that don't support fast mode, it silently switches to standard speed. Though there is no error with Opus 4.6, the `speed` field accurately shows `"standard"`.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
speed="fast",
betas=["fast-mode-2026-02-01"],
messages=[{"role": "user", "content": "Hello"}],
)
print(response.usage.speed) # "fast" or "standard"
```
Output
```python
{
"id": "msg_01XFDUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
// ...
"usage": {
"input_tokens": 8,
"output_tokens": 12,
"speed": "fast"
}
}
```
To track fast mode usage and costs across your organization, see the [Usage and Cost API](../Other/manage-claude-usage-cost-api.md).
## Retries and fallback
### Automatic retries
When fast mode rate limits are exceeded, the API returns a `429` error with a `retry-after` header. The Anthropic SDKs automatically retry these requests up to 2 times by default (configurable with `max_retries`), waiting for the server-specified delay before each retry. Because fast mode uses continuous token replenishment, the `retry-after` delay is typically short and requests succeed once capacity is available.
### Falling back to standard speed
This section covers an opt-in client-side fallback when fast mode is rate limited. It is separate from the behavior on [Claude Opus 4.6](#supported-models), where fast mode is not available and requests run at standard speed automatically.
If you'd prefer to fall back to standard speed rather than wait for fast mode capacity, catch the rate limit error and retry without `speed: "fast"`. Set `max_retries` to `0` on the initial fast request to skip automatic retries and fail immediately on rate limit errors.
Falling back from fast to standard speed will result in a [prompt cache](build-with-claude-prompt-caching.md) miss. Requests at different speeds do not share cached prefixes.
Because setting `max_retries` to `0` also disables retries for other transient errors (overloaded, internal server errors), the following examples reissue the original request with default retries for those cases.
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
def create_message_with_fast_fallback(max_retries=0, max_attempts=3, **params):
try:
return client.with_options(max_retries=max_retries).beta.messages.create(
**params
)
except anthropic.RateLimitError:
if params.get("speed") == "fast":
del params["speed"]
return create_message_with_fast_fallback(max_retries=max_retries, **params)
raise
except (
anthropic.APIStatusError,
anthropic.APIConnectionError,
) as error:
if isinstance(error, anthropic.APIStatusError) and error.status_code < 500:
raise
if max_attempts > 1:
return create_message_with_fast_fallback(
max_retries=max_retries, max_attempts=max_attempts - 1, **params
)
raise
message = create_message_with_fast_fallback(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
betas=["fast-mode-2026-02-01"],
speed="fast",
max_retries=0,
)
```
## Considerations
- **Prompt caching:** Switching between fast and standard speed invalidates the prompt cache. Requests at different speeds do not share cached prefixes.
- **Supported models:** Fast mode is supported on Claude Opus 5.5, Claude Opus 5, and Claude Opus 4.8. See [Supported models](#supported-models).
- **TTFT:** Fast mode's benefits are focused on output tokens per second (OTPS), not time to first token (TTFT).
- **Batch API:** Fast mode is not available with the [Batch API](build-with-claude-batch-processing.md).
- **Priority Tier:** Fast mode is not available with a [Priority Tier](../Endpoints/service-tiers.md) commitment.
- **Claude Platform on AWS:** Fast mode is not currently available on [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md).
## Next steps
[Structured outputs](build-with-claude-structured-outputs.md)
Get validated JSON results from agent workflows.
[Pricing](../../17-Billing-Plans/about-claude-pricing.md#fast-mode-pricing)
Learn about Anthropic's pricing structure for models and features.
[Effort](build-with-claude-effort.md)
Control how many tokens Claude uses when responding with the effort parameter, trading off between response thoroughness and token efficiency.
[Streaming messages](build-with-claude-streaming.md)
Stream Messages API responses incrementally with server-sent events, including text, tool use, and extended thinking deltas.
---
## Files API - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/files
Path: 04-API-Reference/Guides/build-with-claude-files.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Ffiles)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Working with files
# Files API
Copy page
Upload files once, reference them by file_id in Messages requests, and download outputs created by skills or the code execution tool.
Copy page
Files API
[ZDR](../Other/manage-claude-api-and-data-retention.md)
Not eligible
The Files API lets you upload and manage files to use with the Claude API without re-uploading content with each request. This is particularly useful when using the [code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md) to provide inputs (for example, datasets and documents) and then download outputs (for example, charts). You can [explore the API reference directly](../Endpoints/files-upload.md), in addition to this guide.
## File type support
Referencing a `file_id` in a Messages request is supported on all models that support the given file type. [Images](build-with-claude-vision.md) are supported on all current Claude models. For [PDFs](build-with-claude-pdf-support.md) and [other file types with the code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md#compatibility), see the linked pages for model support.
## How the Files API works
The Files API provides a create-once, use-many-times approach for working with files:
- **Upload files** to Anthropic's secure storage and receive a unique `file_id`
- **Download files** that are created by skills or the code execution tool
- **Reference files** in [Messages](../Endpoints/messages-create.md) requests using the `file_id` instead of re-uploading content
- **Manage your files** with list, retrieve, and delete operations
**Uploaded files are accessible to your entire workspace, not scoped to an end user, conversation, or session.** Any API key with access to a workspace can access any files uploaded to that workspace. Every service account, and every user whose organization role allows API access, can use the Default Workspace in addition to any workspace you add them to, so keep files that must stay separate in their own [workspace](../Other/manage-claude-workspaces.md#api-keys-and-resource-scoping) and access them only with keys scoped to that workspace. Never accept `file_id` values from end users or other untrusted sources: a user-supplied file ID would let one user of your application read content that another user uploaded. Treat file IDs as server-side references, and keep the mapping between your users and their files in your application.
If you are building a multi-tenant application on the Files API, create a separate [workspace](../Other/manage-claude-workspaces.md) for each tenant. The workspace is the isolation boundary for files, so a workspace per tenant gives each tenant's data hard isolation from every other tenant. Each organization can have up to 100 workspaces; contact your account team if you need more.
## How to use the Files API
### Uploading a file
Upload a file to be referenced in future API calls:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
uploaded = client.files.upload(
file=("document.pdf", open("/path/to/document.pdf", "rb"), "application/pdf"),
)
file_id = uploaded.id
print(file_id)
```
The response from uploading a file includes:
Response
```python
{
"id": "file_011CNha8iCJcU1wXNR6q4V8w",
"type": "file",
"filename": "document.pdf",
"mime_type": "application/pdf",
"size_bytes": 1024000,
"created_at": "2025-01-01T00:00:00Z",
"downloadable": false,
"expires_at": null
}
```
`downloadable` is `false` for files you upload. Only files created by [skills](build-with-claude-skills-guide.md) or the [code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md) can be downloaded. See [Downloading a file](#downloading-a-file).
### Using a file in messages
Once uploaded, reference the file by passing the `id` from the upload response as `file_id`:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Please summarize this document for me."},
{
"type": "document",
"source": {
"type": "file",
"file_id": file_id,
},
},
],
}
],
)
print(response)
```
### File types and content blocks
The Files API supports different file types that correspond to different content block types:
| File type | MIME type | Content block type | Use case |
|:-------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------|:-------------------|:------------------------------------|
| PDF | `application/pdf` | `document` | Text analysis, document processing |
| Plain text | `text/plain` | `document` | Text analysis, processing |
| Images | `image/jpeg`, `image/png`, `image/gif`, `image/webp` | `image` | Image analysis, visual tasks |
| [Datasets, others](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md#upload-and-analyze-your-own-files) | Varies | `container_upload` | Analyze data, create visualizations |
#### Document blocks
For PDFs and text files, use the `document` content block:
```python
{
"type": "document",
"source": {
"type": "file",
"file_id": "file_011CNha8iCJcU1wXNR6q4V8w"
},
"title": "Document Title", // Optional
"context": "Context about the document", // Optional
"citations": { "enabled": true } // Optional, enables citations
}
```
#### Image blocks
For images, use the `image` content block:
```python
{
"type": "image",
"source": {
"type": "file",
"file_id": "file_011CPMxVD3fHLUhvTqtsQA5w"
}
}
```
#### Container upload blocks
To send a file to the [code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md#upload-and-analyze-your-own-files), use the `container_upload` content block:
```python
{
"type": "container_upload",
"file_id": "file_011CNha8iCJcU1wXNR6q4V8w"
}
```
### Working with other file formats
For file types that the `document` block doesn't support (for example, .docx and .xlsx), convert the files to plain text and include the content directly in your message. Files that are already plain text, such as .csv and .md files, can either be read in this way or uploaded through the Files API with an explicit `text/plain` content type. To analyze datasets instead of reading them as text, upload them for the [code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md#upload-and-analyze-your-own-files) using a `container_upload` block.
The following examples read a text file and send its contents as plain text:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Read the text file
with open("document.txt") as f:
text_content = f.read()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": f"Here's the document content:\n\n{text_content}\n\nPlease summarize this document.",
}
],
}
],
)
for block in response.content:
if block.type == "text":
print(block.text)
```
For .docx files containing images, convert them to PDF format first, then use [PDF support](build-with-claude-pdf-support.md) to take advantage of the built-in image parsing. This allows using citations from the PDF document.
### Managing files
#### List files
Retrieve a list of your uploaded files. The endpoint is paginated: each request returns up to `limit` files (20 by default, and at most 1,000), and the response's `next_page` cursor fetches the next page when passed back as the `page` parameter. Files are ordered newest first. See the [List Files API reference](../Endpoints/files-list.md). The SDKs return the first page and provide auto-pagination helpers. The CLI example bounds the total with `--max-items`:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
files = client.files.list()
print(files)
```
To check a known set of files in one request instead of paging, pass up to 100 file IDs as `ids[]` query parameters. An `ids[]` request always returns a single page (`next_page` is `null`), and any ID that does not resolve to a file in your workspace is silently omitted from `data`; compare the returned IDs against the requested IDs to detect misses. `ids[]` cannot be combined with `page` or `limit`.
#### Get file metadata
Retrieve information about a specific file:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
file = client.files.retrieve_metadata(file_id)
print(file)
```
#### Delete a file
Remove a file from your workspace:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client.files.delete(file_id)
```
### Downloading a file
Download files that were created by [skills](build-with-claude-skills-guide.md) or the [code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md). Files you upload cannot be downloaded. The `file_id` of a generated file appears in the [`bash_code_execution_tool_result` content block](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md#retrieve-generated-files) of the Messages response that created it:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
file_content = client.files.download(file_id)
file_content.write_to_file("downloaded_file.txt")
```
A file is downloadable only when its metadata shows `"downloadable": true`, which is the case for files created by skills or the code execution tool. Downloading a file you uploaded returns a 400 error.
On the Claude API, supported image, video, and audio files that Claude produces with the code execution tool, including files created by skills, carry signed C2PA Content Credentials when you download them. See [Content Credentials on generated files](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md#content-credentials-on-generated-files) for what the credential contains and how to verify it.
## File storage and limits
### Storage limits
- **Maximum file size:** 500 MB per file
- **Total storage:** 1 TB per organization
### File lifecycle
- Files are scoped to the workspace they were uploaded in. Any request in the same workspace can reference them; never accept file IDs from untrusted sources (see the [workspace access warning](#workspace-scoped-access))
- Files cannot be modified or renamed after upload. To change a file's content, upload a new file and delete the old one
- Files persist until you delete them with the `DELETE /v1/files/{file_id}` endpoint or they reach their `expires_at`
- Deleted files cannot be recovered
- Files are inaccessible through the API shortly after deletion, but they may persist in active Messages API calls and associated tool uses
- Files that users delete will be deleted in accordance with Anthropic's [data retention policy](https://privacy.claude.com/en/articles/7996866-how-long-do-you-store-my-organization-s-data). For ZDR eligibility across all features, see [API and data retention](../Other/manage-claude-api-and-data-retention.md)
### File expiration
To have a file expire automatically, include an `expires_in_seconds` form field when you upload it. The value is an integer number of seconds between 3,600 (1 hour) and 7,776,000 (90 days). The resulting `expires_at` timestamp (RFC 3339) appears on every file response and is `null` for files uploaded without an expiration. Expiration is set once at upload and cannot be changed.
When a file reaches its `expires_at`:
- Downloading its content (`GET /v1/files/{file_id}/content`) returns a 404 error
- A Messages request that references the file fails before inference
- Its metadata (`GET /v1/files/{file_id}`) remains readable for up to 30 days, with `expires_at` in the past
- It continues to appear in list responses during that window; compare `expires_at` to the current time to filter expired files
Deleting an expired file with `DELETE /v1/files/{file_id}` removes its metadata immediately instead of waiting for the 30-day window to elapse.
Expiration is a lifecycle feature, not a guaranteed-deletion control. After `expires_at`, file content is no longer retrievable through the API and is released from your storage quota; the underlying content may be retained for a limited period thereafter for safety review before permanent deletion, and file metadata remains visible for up to 30 days after expiration. To remove a file before its scheduled expiration, use `DELETE /v1/files/{file_id}`.
### Audit logging
If your organization has the [Compliance API](../Other/manage-claude-compliance-api.md) enabled, its [Activity Feed](../Other/manage-claude-compliance-activity-feed.md) records Files API operations made with a Claude API key or from the Claude Console: each upload (`POST /v1/files`), content download (`GET /v1/files/{file_id}/content`), and deletion (`DELETE /v1/files/{file_id}`) appears as a `platform_file_uploaded`, `platform_file_content_downloaded`, or `platform_file_deleted` activity. Listing files and retrieving file metadata are not recorded. Operations that occur while the Compliance API is off are not recorded and cannot be recovered later, so [set up the Compliance API](../Other/manage-claude-compliance-api-access.md) before you rely on this audit trail. On [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md#monitoring-and-logging), audit file operations with AWS CloudTrail data events instead.
## Migrate from `files-api-2025-04-14`
The Files API is out of beta and needs no beta header. Migrating off `files-api-2025-04-14` is optional: requests that still send it keep working and keep returning the beta response shapes, so an existing integration keeps working until you change it. Removing the header switches those requests to the shapes documented on this page:
| | With `files-api-2025-04-14` | Without the header |
|------------------------------------------|-----------------------------------------|------------------------------------------------------------------------------|
| List response | `{ data, has_more, first_id, last_id }` | `{ data, next_page }`; pass `next_page` back as the `page` query parameter |
| List cursors | `before_id`, `after_id` | `page`, or up to 100 `ids[]` (`before_id` and `after_id` return a 400 error) |
| `expires_at` on file objects | Not returned | Always present; `null` when the file has no expiration |
| `Content-Type` on the uploaded file part | Required | Optional; the type is detected when omitted |
To migrate:
1. **Remove the beta header.** Drop `anthropic-beta: files-api-2025-04-14` from your requests. In the SDKs, call `client.files` instead of `client.beta.files`; keeping `client.beta.files` works only on the [SDK releases that no longer send the header](#sdk-beta-namespace). Earlier releases send it from `client.beta.files` even with no `betas` argument.
2. **Update pagination.** Replace `after_id`/`before_id` loops with the `page`/`next_page` cursor, or use the SDK auto-pagination helpers shown in [Managing files](#managing-files).
3. **Read `expires_at`.** The field appears only without the header; `null` means the file has no expiration (see [File expiration](#file-expiration)).
### SDK beta namespace
Starting with Python SDK 1.2.0, TypeScript SDK 0.122.0, Go SDK 1.68.0, Java SDK 2.59.0, Ruby SDK 1.67.0, and C# SDK 12.44.0, `client.beta.files` no longer sends `files-api-2025-04-14` and returns the same shapes as `client.files`, with `Beta`-prefixed type names. It accepts a `betas` argument for Files features that are still in beta, such as `scope_id` filtering under a [Managed Agents](../Other/managed-agents-files.md) beta header. Earlier SDK releases are typed to the beta shapes; if you depend on those types, stay on an earlier release until you migrate.
Requests that carry `anthropic-beta: managed-agents-2026-04-01` without `files-api-2025-04-14` receive the shapes on this page with one compatibility affordance on `GET /v1/files`: `before_id` and `after_id` are still accepted (not combinable with `page` or `ids[]`), and the list response includes `has_more`, `first_id`, and `last_id` alongside `next_page`. Later Managed Agents beta versions receive the plain shape.
## Error handling
Common errors when using the Files API include:
- **File not found (404):** The specified `file_id` doesn't exist or you don't have access to it
- **Invalid file type (400):** The file type doesn't match the content block type (for example, using an image file in a document block)
- **Not downloadable (400):** Files you upload have `"downloadable": false` and cannot be downloaded. Only files created by skills or the code execution tool can be downloaded
- **Exceeds context window size (400):** The file is larger than the context window size (for example, using a 500 MB plain text file in a `/v1/messages` request)
- **Invalid filename (400):** The file name doesn't meet the length requirements (1-255 characters) or contains forbidden characters (`<`, `>`, `:`, `"`, `|`, `?`, `*`, `\`, `/`, or Unicode characters 0-31)
- **File too large (413):** File exceeds the 500 MB limit
- **Storage limit exceeded (400):** Your organization has reached the 1 TB storage limit
Output
```python
{
"type": "error",
"error": {
"type": "not_found_error",
"message": "File `file_011CNha8iCJcU1wXNR6q4V8w` not found."
},
"request_id": "req_011CQFYcrRp7mCHLDsAYT8Qt"
}
```
## Usage and billing
Files API operations are free:
- Uploading files
- Downloading files
- Listing files
- Getting file metadata
- Deleting files
File content used in Messages requests is priced as input tokens.
### Rate limits
File-related API calls are limited to approximately 500 requests per minute. To request a higher limit, [contact sales](mailto:sales@anthropic.com).
## Next steps
[PDF support](build-with-claude-pdf-support.md)
Process PDFs with Claude. Extract text, analyze charts, and understand visual content from your documents.
[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)
Run Python and bash code in a sandboxed container to analyze data, generate files, and iterate on solutions.
[Vision](build-with-claude-vision.md)
Process and analyze visual input and generate text and code from images.
## Compatibility
Supported platforms
- Claude API
- Claude Platform on AWS
- Microsoft Foundry^([1](#compat-fn-1))
1. On [Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md), the Files API requires a [Hosted on Anthropic deployment](build-with-claude-claude-in-microsoft-foundry.md#additional-features-not-supported-when-hosted-on-azure). [↩](#compat-fnref-1)
---
## Stop reasons and fallback - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons
Path: 04-API-Reference/Guides/build-with-claude-handling-stop-reasons.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fhandling-stop-reasons)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Building with Claude
# Stop reasons and fallback
Copy page
Learn what each stop_reason value means and how to handle truncation, tool use, paused turns, and refusals in your application.
Copy page
Every Messages API response includes a `stop_reason` field that tells you why Claude stopped generating. Check this field to decide whether to use the response as-is, continue the conversation, retry, or fall back to another model.
For the full response schema, see the [Messages API reference](../Endpoints/messages-create.md).
## Quick reference
| Value | When it occurs | What to do |
|-------------------------------------------------------------------|-------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|
| [`end_turn`](#end-turn) | Claude finished its response naturally. | Use the response. |
| [`max_tokens`](#max-tokens) | The response reached your `max_tokens` limit. | Raise `max_tokens` or [continue the response](#ensuring-complete-responses). |
| [`stop_sequence`](#stop-sequence) | Claude emitted one of your `stop_sequences`. | Read `stop_sequence` to see which one fired. |
| [`tool_use`](#tool-use) | Claude is calling a tool. | Run the tool and return the result. A server tool call still missing its result block completes in a later response. |
| [`pause_turn`](#pause-turn) | A server-tool loop reached its iteration limit. | Send the assistant content back to continue. |
| [`refusal`](#refusal) | Claude declined to respond. | Read `stop_details` and [retry on a fallback model](build-with-claude-refusals-and-fallback.md). |
| [`model_context_window_exceeded`](#model-context-window-exceeded) | The response filled the model's context window. | Treat the response as truncated. |
## The stop_reason field
The `stop_reason` field is part of every successful Messages API response. Unlike errors, which indicate failures in processing your request, `stop_reason` tells you why Claude completed its response generation.
Example response
```python
{
"id": "msg_01234",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Here's the answer to your question..."
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"stop_details": null,
"usage": {
"input_tokens": 100,
"output_tokens": 50
}
}
```
## Stop reason values
### end_turn
The most common stop reason. Indicates Claude finished its response naturally.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
if response.stop_reason == "end_turn":
# Process the complete response
for block in response.content:
if block.type == "text":
print(block.text)
```
### Empty responses with end_turn
Sometimes Claude returns an empty response (exactly 2–3 tokens with no content) with `stop_reason: "end_turn"`. This typically occurs when Claude interprets that the assistant turn is complete, particularly after tool results.
**Common causes:**
- Adding text blocks immediately after tool results (Claude learns to expect the user to always insert text after tool results, so it ends its turn to follow the pattern)
- Sending Claude's completed response back without adding anything (Claude already determined it's done, so it will remain done)
**How to prevent empty responses:**
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
# INCORRECT: Adding text immediately after tool_result
messages = [
{"role": "user", "content": "Calculate the sum of 1234 and 5678"},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_123",
"name": "calculator",
"input": {"operation": "add", "a": 1234, "b": 5678},
}
],
},
{
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"},
{
"type": "text",
"text": "Here's the result", # Don't add text after tool_result
},
],
},
]
# CORRECT: Send tool results directly without additional text
messages = [
{"role": "user", "content": "Calculate the sum of 1234 and 5678"},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_123",
"name": "calculator",
"input": {"operation": "add", "a": 1234, "b": 5678},
}
],
},
{
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"}
],
}, # Just the tool_result, no additional text
]
```
If you still get empty responses after fixing the message structure, add a continuation prompt in a new user message rather than retrying with the empty response:
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
def handle_empty_response(client, messages):
response = client.messages.create(
model="claude-opus-5-5", max_tokens=1024, messages=messages
)
# Check if response is empty
if response.stop_reason == "end_turn" and not response.content:
# INCORRECT: Don't just retry with the empty response
# This won't work because Claude already decided it's done
# CORRECT: Add a continuation prompt in a NEW user message
messages.append({"role": "user", "content": "Please continue"})
response = client.messages.create(
model="claude-opus-5-5", max_tokens=1024, messages=messages
)
return response
```
**Best practices:**
1. **Never add text blocks immediately after tool results:** This teaches Claude to expect user input after every tool use.
2. **Don't retry empty responses without modification:** Sending the empty response back won't help.
3. **Use continuation prompts as a last resort:** Only if these fixes don't resolve the issue.
### max_tokens
Claude stopped because it reached the `max_tokens` limit specified in your request.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Request with limited tokens
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=10,
messages=[{"role": "user", "content": "Explain quantum physics"}],
)
if response.stop_reason == "max_tokens":
# Response was truncated
print("Response was cut off at token limit")
# Consider making another request to continue
```
### Incomplete tool use blocks
If Claude's response is cut off because it hit the `max_tokens` limit, and the truncated response contains an incomplete tool use block, you'll need to retry the request with a higher `max_tokens` value to get the full tool use.
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
# Check if response was truncated during tool use
if response.stop_reason == "max_tokens":
# Check if the last content block is an incomplete tool_use
last_block = response.content[-1]
if last_block.type == "tool_use":
# Send the request with higher max_tokens
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096, # Increased limit
messages=messages,
tools=tools,
)
```
### stop_sequence
Claude encountered one of your custom stop sequences.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
stop_sequences=["END", "STOP"],
messages=[{"role": "user", "content": "Generate text until you say END"}],
)
if response.stop_reason == "stop_sequence":
print(f"Stopped at sequence: {response.stop_sequence}")
```
### tool_use
Claude is calling a tool and expects you to run it.
For most tool use implementations, use the [tool runner](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md), which automatically handles tool execution, result formatting, and conversation management.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
weather_tool = {
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City and state"},
},
"required": ["location"],
},
}
def execute_tool(name, tool_input):
"""Execute a tool and return the result."""
return f"Weather in {tool_input.get('location', 'unknown')}: 72°F"
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
tools=[weather_tool],
messages=[{"role": "user", "content": "What is the weather in San Francisco?"}],
)
if response.stop_reason == "tool_use":
# Extract and execute the tool
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
# Return result to Claude for final response
```
A `tool_use` response can also contain a `server_tool_use` block whose `id` has no matching result block. That server tool call is not finished, and this response does not carry its result. In the common case, Claude calls a [server tool](../Agents-Tools/agents-and-tools-tool-use-server-tools.md) and one of your client tools in the same group of parallel tool calls: the API returns without running the server tool so that you can run the client tools first. There is no other marker for the state; detect it by checking each `server_tool_use` or `mcp_tool_use` block's `id` for a matching result block.
With [programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md), the same response shape means something different. The client `tool_use` block comes from code that is running in the `code_execution` tool rather than from Claude directly, and its `caller` field names the `code_execution` block that called it. That code has already started: it is paused waiting for your `tool_result` blocks, and sending them resumes the execution instead of starting a deferred tool. The `code_execution` block's own result block arrives once the code finishes, which can take more than one round of tool results. The follow-up user message itself is the same in both cases; with programmatic tool calling, also pass back the `id` from the response's `container` field, as that page shows.
A mixed tool_use response
```python
{
"stop_reason": "tool_use",
"content": [
{
"type": "server_tool_use",
"id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
"name": "web_search",
"input": { "query": "example article" }
},
{
"type": "tool_use",
"id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
"name": "run_command",
"input": { "command": "uname -a" }
}
]
}
```
The continuation is a user message of `tool_result` blocks, one for every `tool_use` block in the response (see [Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)), with two extra rules: that message must contain nothing except the `tool_result` blocks, and the request must keep the same `tools` array. A resume request that no longer defines the waiting server tool fails with a 400 whose message ends `` but no `web_search` tool was provided ``. The API attaches your results to the still-open assistant turn, runs the deferred server tool (for paused code execution, resumes it), and continues the turn. For a server tool Claude called directly, the next response's `content` starts with the result block that answers the previous response's `server_tool_use` `id`.
The follow-up user message
```python
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
"content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
}
]
}
```
Adding anything after the `tool_result` blocks in that user message, such as text, ends the assistant turn; for a server tool Claude called directly, the request then fails with a 400 `invalid_request_error` that names the unresolved server tool:
``` block
`web_search` tool use with id `srvtoolu_01HxbWnMRmbWyMfUtJKC45rA` was found without a corresponding `web_search_tool_result` block
```
Leaving out a `tool_result`, or putting one after other content, fails earlier with the standard `tool_use ids were found without tool_result blocks immediately after` error instead. To give Claude more input, send it as a separate user message after the turn completes.
### pause_turn
Returned when the server-side sampling loop reaches its iteration limit while executing [server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md) such as web search. The default limit is 10 iterations per request.
When this happens, the response may contain a `server_tool_use` block without a corresponding result block. To let Claude finish processing, continue the conversation by sending the response back as-is. A response that leaves a client `tool_use` block waiting on you never has a `stop_reason` of `pause_turn`: when Claude stops to call your tools, `stop_reason` is [`tool_use`](#tool-use), and you continue it by sending the client `tool_result` blocks instead of the response itself.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
tools=[{"type": "web_search_20250305", "name": "web_search"}],
messages=[{"role": "user", "content": "Search for latest AI news"}],
)
if response.stop_reason == "pause_turn":
# Continue the conversation by sending the response back
messages = [
{"role": "user", "content": "Search for latest AI news"},
{"role": "assistant", "content": response.content},
]
continuation = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
tools=[{"type": "web_search_20250305", "name": "web_search"}],
)
```
Your application should handle `pause_turn` in any agent loop that uses server tools. Add the assistant's response to your messages array and make another API request to let Claude continue.
### refusal
Claude declined to generate a response. Safety classifiers return this stop reason as a normal HTTP 200 response, not an error.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "[Unsafe request]"}],
)
if response.stop_reason == "refusal":
# Claude declined to respond
print("Claude was unable to process this request")
# Consider rephrasing or modifying the request
```
If you encounter `refusal` stop reasons frequently while using Claude Sonnet 4.5 or Claude Opus 4.1 (the latter [retired, except on Bedrock and Google Cloud](../../20-Models/about-claude-model-deprecations.md)), you can try updating your API calls to use Haiku 4.5 (`claude-haiku-4-5-20251001`), which has different usage restrictions. Learn more about [understanding Sonnet 4.5's API safety filters](https://support.claude.com/en/articles/12449294-understanding-sonnet-4-5-s-api-safety-filters).
On a refusal, the `stop_details` object identifies the policy category that triggered it. The categories and the full refusal response shape are covered on [Refusals and fallback](build-with-claude-refusals-and-fallback.md#refusal-response). `stop_details` is `null` for all stop reasons other than `refusal`.
A refused request on Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, or Claude Opus 5 can usually be served by retrying on another Claude model. [Refusals and fallback](build-with-claude-refusals-and-fallback.md) shows how to set up that retry, server-side or in your client. If you build the retry yourself from Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, or Claude Opus 5, [fallback credit](build-with-claude-fallback-credit.md) covers how to avoid paying the prompt-cache cost twice.
### model_context_window_exceeded
Claude stopped because it reached the model's context window limit. This lets you request the maximum possible tokens without knowing the exact input size.
This stop reason is currently typed only in the SDKs' `beta` namespace, so the following examples call `client.beta.messages` and use the `Beta`-prefixed types. On Sonnet 4.5 and newer models the API returns this value without a beta header. For earlier models, add the `model-context-window-exceeded-2025-08-26` beta header to enable it.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
# Request with maximum tokens to get as much as possible
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=20000, # Python SDK requires streaming for max_tokens above ~21k
messages=[
{"role": "user", "content": "Large input that uses most of context window..."}
],
)
if response.stop_reason == "model_context_window_exceeded":
# Response hit context window limit before max_tokens
print("Response reached model's context window limit")
# The response is still valid but was limited by context window
```
## Best practices for handling stop reasons
### Always check stop_reason
Make it a habit to check the `stop_reason` in your response handling logic:
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
def handle_response(response):
match response.stop_reason:
case "tool_use":
return handle_tool_use(response)
case "max_tokens":
return handle_truncation(response)
case "model_context_window_exceeded":
return handle_context_limit(response)
case "pause_turn":
return handle_pause(response)
case "refusal":
return handle_refusal(response)
case _:
# Handle end_turn and other cases
return next(
(block.text for block in response.content if block.type == "text"),
"",
)
```
### Handle truncated responses gracefully
When a response is truncated because of token limits or the context window, append a notice so the reader knows the output is incomplete. To continue generating from where the response left off instead, see [Ensuring complete responses](#ensuring-complete-responses).
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
def handle_truncated_response(response):
text = next((block.text for block in response.content if block.type == "text"), "")
if response.stop_reason in ["max_tokens", "model_context_window_exceeded"]:
if response.stop_reason == "max_tokens":
note = "[Response truncated due to max_tokens limit]"
else:
note = "[Response truncated due to context window limit]"
return f"{text}\n\n{note}"
return text
```
### Implement retry logic for pause_turn
When using [server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md), the API may return `pause_turn` if the server-side sampling loop reaches its iteration limit (default 10). Handle this by continuing the conversation:
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
def handle_server_tool_conversation(client, user_query, tools, max_continuations=5):
"""
Handle server tool conversations that may require multiple continuations.
The server runs a sampling loop when executing server tools. If the loop
reaches its iteration limit, the API returns pause_turn. Continue the
conversation by sending the response back to let Claude finish.
"""
messages = [{"role": "user", "content": user_query}]
for _ in range(max_continuations):
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
messages=messages,
tools=tools,
)
if response.stop_reason != "pause_turn":
# Claude finished processing - return the final response
return response
# pause_turn: replace the full message list to maintain alternating roles
messages = [
{"role": "user", "content": user_query},
{"role": "assistant", "content": response.content},
]
# Reached max continuations - return the last response
return response
```
## Stop reasons vs. errors
It's important to distinguish between `stop_reason` values and actual errors:
### Stop reasons (successful responses)
- Part of the response body
- Indicate why generation stopped normally
- Response contains valid content
### Errors (failed requests)
- HTTP status codes 4xx or 5xx
- Indicate request processing failures
- Response contains error details
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
try:
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
# Handle successful response with stop_reason
if response.stop_reason == "max_tokens":
print("Response was truncated")
except anthropic.APIStatusError as e:
# Handle actual errors
match e.status_code:
case 429:
print("Rate limit exceeded")
case 500:
print("Server error")
```
## Streaming considerations
When using streaming, `stop_reason` is:
- `null` in the initial `message_start` event
- Provided in the `message_delta` event
- Not provided in any other events
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
) as stream:
for event in stream:
if event.type == "message_delta":
stop_reason = event.delta.stop_reason
if stop_reason:
print(f"Stream ended with: {stop_reason}")
```
## Common patterns
### Handling tool use workflows
**Simpler with tool runner:** The following example shows manual tool handling. For most use cases, the [tool runner](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md) automatically handles tool execution with much less code.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
def complete_tool_workflow(client, user_query, tools):
messages = [{"role": "user", "content": user_query}]
while True:
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=messages,
tools=tools,
)
if response.stop_reason == "tool_use":
# Execute tools and continue
tool_results = execute_tools(response.content)
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
else:
# Final response
return response
```
### Ensuring complete responses
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
def get_complete_response(client, prompt, max_attempts=3):
messages = [{"role": "user", "content": prompt}]
full_response = ""
for _ in range(max_attempts):
response = client.messages.create(
model="claude-opus-5-5", messages=messages, max_tokens=4096
)
full_response += next(
(block.text for block in response.content if block.type == "text"), ""
)
if response.stop_reason != "max_tokens":
break
# Continue from where it left off
messages = [
{"role": "user", "content": prompt},
{"role": "assistant", "content": full_response},
{"role": "user", "content": "Please continue from where you left off."},
]
return full_response
```
### Getting maximum tokens without knowing input size
With the `model_context_window_exceeded` stop reason, you can request the maximum possible tokens without calculating input size:
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
def get_max_possible_tokens(client, prompt):
"""
Get as many tokens as possible within the model's context window
without needing to calculate input token count
"""
response = client.beta.messages.create(
model="claude-opus-5-5",
messages=[{"role": "user", "content": prompt}],
max_tokens=20000, # Python SDK requires streaming for max_tokens above ~21k
)
match response.stop_reason:
case "model_context_window_exceeded":
# Got the maximum possible tokens given input size
print(
f"Generated {response.usage.output_tokens} tokens (context limit reached)"
)
case "max_tokens":
# Got exactly the requested tokens
print(
f"Generated {response.usage.output_tokens} tokens (max_tokens reached)"
)
case _:
# Natural completion
print(
f"Generated {response.usage.output_tokens} tokens (natural completion)"
)
return next((block.text for block in response.content if block.type == "text"), "")
```
## Next steps
[Refusals and fallback](build-with-claude-refusals-and-fallback.md)
Retry refused requests on a fallback model, server-side or in your client.
[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)
Let the SDK manage the `tool_use` loop, result formatting, and retries for you.
[Streaming messages](build-with-claude-streaming.md)
Read `stop_reason` from the `message_delta` event when streaming.
[Errors](../Endpoints/errors.md)
Handle 4xx and 5xx HTTP errors, which are distinct from stop reasons.
---
## Build an orchestration mode - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/mid-conversation-effort-example
Path: 04-API-Reference/Guides/build-with-claude-mid-conversation-effort-example.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fmid-conversation-effort-example)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Context management
# Build an orchestration mode
Copy page
Build a session-level mode that grants standing consent for multiagent fan-out, switched on and off with mid-conversation system messages.
Copy page
An orchestration mode is a session-level switch: when it is on, the model puts maximum thoroughness behind every substantive request, scouting the task itself and then fanning work out to parallel subagents by default. When it is off, the same orchestration tool goes back to per-request opt-in.
The mode is not an API parameter. It is built entirely from documented pieces:
1. **An effort level:** requests run at a documented [Effort](build-with-claude-effort.md) value such as `xhigh`. There is no hidden level above the ones on that page. This example sets effort at the top level of each request, which needs no beta header.
2. **A mode reminder:** a [mid-conversation system message](build-with-claude-mid-conversation-system-messages.md) tells the model the mode is active, with a one-line refresher every several turns and an exit notice when the mode is turned off. The top-level `system` field never changes, so the cached prefix stays intact.
3. **Standing consent in the tool description:** the orchestration tool's description states that while the mode is on, the model should author and run a workflow for every substantive task without asking first.
This example uses mid-conversation system messages; for the models and platforms that support them, see [Mid-conversation system messages](build-with-claude-mid-conversation-system-messages.md). The fan-out itself multiplies token usage: a single request can spawn many subagent conversations, so reserve the mode for work that justifies the cost.
## Set up the loop
The example is a single file. The constants control the effort level, the fan-out shape, and how often the mode refresher is re-sent. `MAX_CONCURRENT` caps how many subagents run at the same time (the PHP port is sequential and ignores it); `MAX_TOTAL_SUBTASKS` caps how many the model may queue in a single Workflow call. Splitting the two lets the model plan a large backlog without launching it all at once. The `DOC_TEST_MODE` check caps the loops to a single turn when that environment variable is set, so the automated docs harness can validate that the file compiles and finishes quickly without running the full orchestration; leave it unset when running the example yourself.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import atexit
import concurrent.futures
import hashlib
import json
import os
import shutil
import subprocess
import sys
import tempfile
import threading
import anthropic
client = anthropic.Anthropic()
MODEL = "claude-opus-5-5"
EFFORT = "xhigh"
SYSTEM_PROMPT = "You are a helpful general-purpose agent. Answer the user's request directly."
REQUEST_TIMEOUT_SECONDS = 600
BASH_TIMEOUT_SECONDS = 60
TOOL_RESULT_MAX_CHARS = 8000
MAX_CONCURRENT = 10
DOC_TEST_MODE = bool(os.environ.get("DOC_TEST_MODE"))
MAX_TOTAL_SUBTASKS = 2 if DOC_TEST_MODE else 200
MAX_SUBAGENT_TURNS = 1 if DOC_TEST_MODE else 15
MAX_MAIN_TURNS = 1 if DOC_TEST_MODE else 30
TURNS_BETWEEN_REFRESHERS = 10
JOURNAL_PATH = os.environ.get("ORCH_JOURNAL") or "orchestration_journal.json"
```
## Define the mode reminders
The reminders are short on purpose. They flip the mode and point at the tool description, where the heavyweight instructions live. The full text is sent once when the mode turns on, the refresher is re-sent only after several user turns, and the exit notice is sent once when the mode turns off.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
MODE_ENTER = (
"Orchestration mode is on: optimize for the most exhaustive, correct answer rather than "
"the fastest one. Use the Workflow tool on every substantive task, sized to the problem's "
"natural decomposition rather than the maximum the tool allows. See the Workflow tool's "
"description for standing consent, granularity guidance, and quality patterns. Work solo "
"only on conversational or trivial turns."
)
MODE_REFRESH = (
"Orchestration mode is still on. Use the Workflow tool; see its standing consent section."
)
MODE_EXIT = (
"Orchestration mode is off. The Workflow tool's standard opt-in rule applies again."
)
```
## Grant standing consent in the tool description
The Workflow tool carries the real behavioral contract: the opt-in rule, the standing consent that applies while the mode is on, granularity guidance for sizing the fan-out, and the quality patterns the model can reach for (a verification wave, a completeness critic, multiphase sequencing). Subagents also get a `report_findings` tool so their results come back as structured JSON instead of prose, and the bash tool is the Anthropic-defined `bash_20250124` tool run locally.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
WORKFLOW_TOOL = {
"name": "Workflow",
"description": (
"Orchestrate a multiagent workflow: split a large task into independent subtasks "
"and run them as parallel agents, then collect their results.\n\n"
"Opt-in: only use this tool when the user explicitly asks for a workflow, or when a "
"system message confirms that orchestration mode is on.\n\n"
"Quality patterns: adversarial verification (a second wave of agents checks the first "
"wave's findings against the source), a completeness critic (one agent hunts for what "
"the others missed), and multiphase sequencing (understand, design, implement, and "
"review as separate workflow calls, reading results between phases). A useful default "
"is hybrid: scout inline first to discover the work-list, then fan out over it.\n\n"
"Granularity: scope each subtask to a distinct concern, component, or question rather "
"than per line or per file section. Scale the count to what the user asked for: a "
"focused review of a module of a few hundred lines rarely needs more than about ten "
"subtasks; a broad audit of a large codebase can justify more.\n\n"
"Standing consent: while a system message confirms orchestration mode is on, that "
"opt-in is standing. Author and run a workflow for every substantive task by default, "
"and lean toward verifying findings adversarially. Work solo only on conversational "
"turns or trivial mechanical edits. When a system message says the mode is off, "
"revert to the opt-in rule above."
),
"input_schema": {
"type": "object",
"properties": {
"subtasks": {
"type": "array",
"items": {"type": "string"},
"description": "Independent subtask prompts to run as parallel agents",
}
},
"required": ["subtasks"],
},
}
BASH_TOOL = {"type": "bash_20250124", "name": "bash"}
REPORT_TOOL = {
"name": "report_findings",
"description": (
"Report the final findings for your subtask. Call this exactly once, when you are "
"done investigating; it ends your task."
),
"input_schema": {
"type": "object",
"properties": {
"summary": {"type": "string", "description": "Two or three sentences of synthesis"},
"findings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"claim": {"type": "string", "description": "The finding, one sentence"},
"evidence": {
"type": "string",
"description": "How it was verified (file, line, or command output)",
},
"severity": {"type": "string", "enum": ["high", "medium", "low", "info"]},
},
"required": ["claim", "evidence", "severity"],
},
},
},
"required": ["summary", "findings"],
},
}
```
## Run the bash tool locally
The bash handler runs the requested command with a timeout, captures combined stdout and stderr, and truncates the result so a runaway command can't flood the context window. Commands run in the directory you launch the example from, so pointing it at a project means starting it there; when `DOC_TEST_MODE` is set, the harness instead gives bash a small throwaway fixture directory that is removed on exit. There is no sandbox here: the command runs with the permissions of the process that launched the example. For clarity this example runs each call in a fresh subshell rather than maintaining the persistent session the `bash_20250124` contract describes; a production agent should back the tool with a long-lived shell so that working directory, environment, and the `restart` action behave as documented.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
# Run bash where the example was launched. In DOC_TEST_MODE the docs harness
# points it at a throwaway fixture directory instead, removed on exit.
if DOC_TEST_MODE:
WORK_DIR = tempfile.mkdtemp(prefix="orchestration-")
atexit.register(shutil.rmtree, WORK_DIR, ignore_errors=True)
with open(os.path.join(WORK_DIR, "sample.py"), "w") as fixture:
fixture.write(
"def fib(n):\n"
" return n if n < 2 else fib(n - 1) + fib(n - 2)\n\n"
"print(fib(10))\n"
)
else:
WORK_DIR = os.getcwd()
def run_bash(command: str) -> tuple[str, bool]:
"""Run a shell command and return (output, is_error). No sandbox: example code only."""
print(f"[bash] {command}", file=sys.stderr)
try:
proc = subprocess.run(
["bash", "-c", command],
cwd=WORK_DIR,
capture_output=True,
text=True,
errors="replace",
timeout=BASH_TIMEOUT_SECONDS,
)
except subprocess.TimeoutExpired:
return f"command timed out after {BASH_TIMEOUT_SECONDS}s", True
output = (proc.stdout + proc.stderr).strip() or "(no output)"
if len(output) > TOOL_RESULT_MAX_CHARS:
output = output[:TOOL_RESULT_MAX_CHARS] + f"\n(truncated at {TOOL_RESULT_MAX_CHARS} chars)"
if proc.returncode != 0:
output = f"(exit code {proc.returncode})\n{output}"
return output, proc.returncode != 0
def handle_bash_block(block) -> tuple[str, bool]:
if block.input.get("restart") is True:
return "Shell restarted.", False
command = block.input.get("command")
if not isinstance(command, str) or not command:
return "bash error: no command was provided.", True
return run_bash(command)
```
## Run one subagent
Each workflow subtask becomes its own small agent loop with the bash tool, running at the same effort as the main loop. A per-request timeout bounds each API call so a dropped connection degrades one subagent instead of stalling the whole run.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
def run_subagent(model: str, prompt: str) -> str:
"""One subagent: a small nested agent loop with the bash tool plus report_findings.
Subagents inherit the main loop's effort level."""
subagent_system = (
"You are one agent in a larger parallel fan-out, assigned a single subtask. "
"Investigate it directly, using bash to check facts rather than guessing, and finish "
"by calling report_findings exactly once. Return findings, not narration."
)
messages = [{"role": "user", "content": prompt}]
for _ in range(MAX_SUBAGENT_TURNS):
with client.messages.stream(
model=model,
max_tokens=64000,
system=subagent_system,
output_config={"effort": EFFORT},
tools=[BASH_TOOL, REPORT_TOOL],
messages=messages,
timeout=REQUEST_TIMEOUT_SECONDS,
) as stream:
response = stream.get_final_message()
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason == "pause_turn":
continue
if response.stop_reason != "tool_use":
text = "".join(block.text for block in response.content if block.type == "text")
if response.stop_reason == "max_tokens":
text += "\n\n(warning: subagent response was truncated at max_tokens)"
return text
tool_results = []
report = None
for block in response.content:
if block.type != "tool_use":
continue
match block.name:
case "report_findings":
report = json.dumps(block.input, indent=2)
output, is_error = "Findings recorded.", False
case "bash":
output, is_error = handle_bash_block(block)
case _:
output, is_error = f"unknown tool: {block.name}", True
tool_results.append(
{
"type": "tool_result",
"tool_use_id": block.id,
"content": output,
"is_error": is_error,
}
)
if report is not None:
return report
messages.append({"role": "user", "content": tool_results})
return "(subagent hit the turn limit before finishing)"
```
## Journal results so reruns resume
A fan-out that spawns dozens of subagents is expensive to restart from scratch. A small content-addressed journal makes it idempotent: before dispatching a subagent, look up the SHA-256 of its prompt in a local JSON file, and return the recorded result if one exists. Interrupt the run, rerun it, and only the subtasks that never finished are recomputed. The journal deduplicates across runs, not within a single fan-out wave; delete the journal file to start fresh.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
_journal_lock = threading.Lock()
def _load_journal() -> dict:
try:
with open(JOURNAL_PATH) as file:
return json.load(file) or {}
except (OSError, json.JSONDecodeError):
return {}
def journaled(prompt: str, compute) -> str:
"""Return a cached result for this exact prompt, or compute and persist it. This
makes the fan-out resumable: interrupt the run, rerun it, and only the subtasks
that never finished are recomputed. Delete the journal file to start fresh."""
key = hashlib.sha256(prompt.encode()).hexdigest()
cached = _load_journal().get(key)
if cached is not None:
print(f"[journal] cache hit for {key[:12]}", file=sys.stderr)
return cached
result = compute()
try:
with _journal_lock: # fan-out writes from many threads
journal = _load_journal()
journal[key] = result
temp = f"{JOURNAL_PATH}.tmp"
with open(temp, "w") as file:
json.dump(journal, file)
os.replace(temp, JOURNAL_PATH) # atomic on POSIX and Windows
except OSError as error: # the journal is best-effort; never discard a computed result
print(f"[journal] write failed: {error}", file=sys.stderr)
return result
```
## Fan out, then verify
The fan-out accepts up to `MAX_TOTAL_SUBTASKS` prompts, runs them through the journal with at most `MAX_CONCURRENT` in flight (sequential in the PHP port), and isolates failures so one broken subagent degrades to an error string instead of ending the run. Once the first wave finishes, a second wave reuses the same subagent path to try to refute each result: every verifier re-derives the claims from the source, defaulting to refuted when uncertain. Both the original result and its verdict are returned to the orchestrator so it can weigh them together.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
def normalize_subtasks(raw) -> list[str]:
"""Accept the subtasks input in whatever shape the model emits: an array, the array
JSON-encoded as a single string, or a newline-separated list."""
if isinstance(raw, str):
try:
raw = json.loads(raw)
except json.JSONDecodeError:
raw = raw.splitlines() if "\n" in raw else [raw]
if not isinstance(raw, list):
return []
return [task.strip() for task in raw if isinstance(task, str) and task.strip()]
def verify_prompt_for(subtask: str, result: str) -> str:
return (
"Adversarially verify the subagent result below: try to REFUTE it. Re-derive the "
"claims yourself with bash rather than trusting the result, and look for evidence "
"that contradicts them. Default to refuted if uncertain. Call report_findings with "
"summary 'refuted: <why>' or 'confirmed: <why>', citing the file:line or command "
"output that decided it.\n\n"
f"Subtask: {subtask}\n\nResult to verify:\n{result}"
)
def run_workflow(model: str, raw_subtasks) -> tuple[str, bool]:
"""Run subtasks as parallel subagents, then run a second verification wave over
the results, and return both. MAX_TOTAL_SUBTASKS bounds how many the model can
queue; MAX_CONCURRENT bounds how many run at once."""
all_subtasks = normalize_subtasks(raw_subtasks)
subtasks = all_subtasks[:MAX_TOTAL_SUBTASKS]
dropped = len(all_subtasks) - len(subtasks)
if not subtasks:
return "Workflow error: no usable subtasks were provided.", True
print(f"[workflow] fanning out {len(subtasks)} agents", file=sys.stderr)
def run_one(prompt: str) -> str:
try:
return journaled(prompt, lambda: run_subagent(model, prompt))
except Exception as error: # isolation boundary: one bad subagent should not end the run
return f"(subagent failed: {type(error).__name__}: {error})"
with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_CONCURRENT) as pool:
results = list(pool.map(run_one, subtasks))
print(f"[workflow] verifying {len(results)} results", file=sys.stderr)
verify_prompts = [verify_prompt_for(task, result) for task, result in zip(subtasks, results)]
verdicts = list(pool.map(run_one, verify_prompts))
joined = "\n\n".join(
f"[agent {index + 1}: {task}]\n{result}\n\n[verify {index + 1}]\n{verdict}"
for index, (task, result, verdict) in enumerate(zip(subtasks, results, verdicts))
)
if dropped > 0:
joined = (
f"(note: {dropped} subtasks beyond MAX_TOTAL_SUBTASKS={MAX_TOTAL_SUBTASKS} were not "
"run; rerun them in a follow-up Workflow call)\n\n" + joined
)
return joined, False
```
## Toggle the mode with mid-conversation system messages
The agent appends the user's message first, then any system messages that are due: the exit notice, the full mode text on entry, or the periodic refresher. Placing the system message after the user turn keeps every cached byte ahead of it untouched, and satisfies the placement rule that a system message follows a user turn.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
class ModeAgent:
"""An agent loop whose orchestration mode is toggled with mid-conversation system messages."""
def __init__(self, model: str, mode_on: bool = True):
self.model = model
self.mode_on = mode_on
self.messages: list[dict] = []
self._mode_announced = False
self._exit_pending = False
self._turns_since_reminder = 0
def set_mode(self, mode_on: bool) -> None:
"""Turn the mode on or off. The notice is delivered with the next user turn."""
if mode_on == self.mode_on:
return
if not mode_on:
if self._mode_announced:
self._exit_pending = True
else:
self._exit_pending = False
self.mode_on = mode_on
def _due_system_messages(self) -> list[dict]:
"""System messages owed on this turn: an exit notice, the full mode text on entry,
or a one-line refresher every TURNS_BETWEEN_REFRESHERS user turns."""
due = []
if self._exit_pending:
self._exit_pending = False
self._mode_announced = False
due.append({"role": "system", "content": MODE_EXIT})
if self.mode_on:
if not self._mode_announced:
self._mode_announced = True
self._turns_since_reminder = 0
due.append({"role": "system", "content": MODE_ENTER})
elif self._turns_since_reminder >= TURNS_BETWEEN_REFRESHERS:
self._turns_since_reminder = 0
due.append({"role": "system", "content": MODE_REFRESH})
return due
def turn(self, user_input: str) -> str:
# Mid-conversation system messages follow the user turn they apply to, which keeps
# the cached prefix ahead of them untouched.
self.messages.append({"role": "user", "content": user_input})
self.messages.extend(self._due_system_messages())
self._turns_since_reminder += 1
for _ in range(MAX_MAIN_TURNS):
with client.messages.stream(
model=self.model,
max_tokens=64000,
system=SYSTEM_PROMPT, # static for the whole session
output_config={"effort": EFFORT},
tools=[WORKFLOW_TOOL, BASH_TOOL],
messages=self.messages,
timeout=REQUEST_TIMEOUT_SECONDS,
) as stream:
response = stream.get_final_message()
self.messages.append({"role": "assistant", "content": response.content})
if response.stop_reason == "pause_turn":
continue
if response.stop_reason != "tool_use":
text = "".join(block.text for block in response.content if block.type == "text")
if response.stop_reason == "max_tokens":
# Drop the truncated assistant message so later turns don't build on it.
self.messages.pop()
text += "\n\n(warning: response was truncated at max_tokens)"
return text
tool_results = []
for block in response.content:
if block.type != "tool_use":
continue
match block.name:
case "Workflow":
output, is_error = run_workflow(self.model, block.input.get("subtasks", []))
case "bash":
output, is_error = handle_bash_block(block)
case _:
output, is_error = f"unknown tool: {block.name}", True
tool_results.append(
{
"type": "tool_result",
"tool_use_id": block.id,
"content": output,
"is_error": is_error,
}
)
self.messages.append({"role": "user", "content": tool_results})
return "(hit the main loop turn limit before finishing)"
```
## Run it
The bash tool in this example runs model-written commands directly on your machine with no sandbox, and the fan-out runs several of those agents in parallel. Run it in a directory and environment you are comfortable exposing, and add sandboxing before adapting it for anything beyond local experimentation.
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
if __name__ == "__main__":
task = (
sys.argv[1]
if len(sys.argv) > 1
else "Explore the current directory, then give a thorough review: what it does, "
"code-quality issues, and concrete improvements."
)
agent = ModeAgent(MODEL)
print(agent.turn(task))
agent.set_mode(False)
print(agent.turn("Briefly summarize what you found above, no fan-out needed."))
```
Start the example from the directory you want the agents to work in, for example the root of a repository to review:
```python
python orchestration_mode.py "Review this repository for flaky tests and propose fixes."
```
With the mode on, expect the model to scout with a few bash commands, dispatch the Workflow tool unprompted, and synthesize the subagent reports into a final answer. Trivial or conversational requests stay solo, as the reminder instructs.
## Toward a production harness
This example is deliberately small. A harness meant for real workloads would typically add:
- **Sandboxed orchestration scripts:** let the model emit a short orchestration program (branching, loops, and reduce steps) and run it inside an isolated interpreter, rather than accepting only a flat list of subtask strings.
- **Durable journaling:** replace the local JSON file with a store that survives process restarts and is safe under concurrent writers across machines.
- **Budget enforcement:** track total subagents launched across the whole session, not just per Workflow call, and refuse to exceed a hard cap so a runaway plan cannot exhaust your quota.
The patterns in this example (the mode reminders, standing consent in the tool description, journaling, and a verification wave) carry over unchanged; only the execution substrate around them gets more robust.
## Related
[Mid-conversation system messages](build-with-claude-mid-conversation-system-messages.md)
The mechanism the mode reminders use, and how it interacts with prompt caching.
[Effort](build-with-claude-effort.md)
The effort levels the API accepts and how to choose one.
[Tool use with Claude](../Agents-Tools/agents-and-tools-tool-use-overview.md)
Defining tools, handling tool calls, and tool results.
[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)
The Anthropic-defined bash tool this example executes locally.
---
## Mid-conversation system messages and tool changes - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages
Path: 04-API-Reference/Guides/build-with-claude-mid-conversation-system-messages.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fmid-conversation-system-messages)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Context management
# Mid-conversation system messages and tool changes
Copy page
Change system instructions or tool availability partway through a conversation without invalidating the cached prefix that came before them.
Copy page
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
System instructions normally live in the top-level `system` field, ahead of every message in the conversation. That position is great for [prompt caching](build-with-claude-prompt-caching.md): the system prompt is part of the stable prefix, so subsequent turns hit the cache. It is a poor position for instructions you only discover you need partway through a session, because editing the top-level `system` field changes the very beginning of the prompt and invalidates the cache for everything that follows.
Mid-conversation system messages close that gap. You append a `{"role": "system"}` message at the point in the conversation where the new instruction becomes relevant, instead of editing the top-level `system` field. The cached prefix stays the same, so the next request still reads it from cache, and the new instruction is still applied as a system instruction rather than as ordinary user text.
Mid-conversation system messages are available on the Claude API, [Claude in Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md), and [Google Cloud](build-with-claude-claude-on-vertex-ai.md).
This feature is available on Claude Fable 5.1, [Claude Mythos 5.1](../../22-Safety-Policy/glasswing.md), Claude Fable 5, [Claude Mythos 5](../../22-Safety-Policy/glasswing.md), Claude Opus 5.5, Claude Opus 4.8, and Claude Opus 5. No beta header is required for mid-conversation system messages. This feature is not available on Claude Sonnet 5. Use the top-level `system` field there instead.
[Mid-conversation tool changes](#mid-conversation-tool-changes) are in beta on the same models. On the Claude API, send the `inline-tools-2026-09-15` beta header, which also covers [defining a tool inside a `tool_addition` block](#define-tools-in-a-message-beta). [Adding an MCP server that way](#add-an-mcp-server-mid-conversation-beta) needs a second beta header, `mcp-client-2026-09-15`, which is available on the Claude API. The `mid-conversation-tool-changes-2026-07-01` header works for changes that name a tool by reference, on the Claude API, Amazon Bedrock, and Google Cloud.
[Turn-scoped system messages](#turn-scoped-system-messages) (`clear_at`) are in beta and require the `mid-conversation-system-clear-at-2026-08-21` beta header, on the same models and platforms as mid-conversation system messages.
## Mid-conversation tool changes
The `tools` array sits even earlier in the hashed request prefix than the top-level `system` field, so editing it invalidates the [prompt cache](build-with-claude-prompt-caching.md) for the entire conversation. Mid-conversation tool changes are the tools counterpart to mid-conversation system messages. Instead of fixing the tool list for the lifetime of the conversation, you change which tools are offered to the model between turns: declare the full tool set in `tools` up front, then use `tool_addition` and `tool_removal` blocks to offer a tool to the model, or withdraw it, from a specific point in the conversation onward. The `tools` array itself never changes, so the cached prefix stays intact. Mid-conversation tool changes are in beta and use the `inline-tools-2026-09-15` beta header on the Claude API.
`tool_addition` and `tool_removal` are content blocks in the `content` array of a `role: "system"` message, and they can be mixed with `text` blocks in the same message. The message follows the placement rules for any mid-conversation system message, with one extra restriction after a paused turn (see [Limitations](#limitations)), and the change applies from that point in the conversation onward. Each block's `tool` field references a tool rather than defining one: `{"type": "tool_reference", "name": "..."}` names a tool declared in the request's `tools` array, and [MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md) tools can be referenced individually with `mcp_tool_reference` (`server_name` and `name`) or as a whole toolset with `mcp_toolset_reference` (`server_name`). Referencing a name that is not declared in `tools` returns a 400 error (on the Claude API, with `error.details.error_code` set to `tool_reference_unresolved`). A `tool_addition` block can instead [carry the tool's full definition](#define-tools-in-a-message-beta), which the `mid-conversation-tool-changes-2026-07-01` header doesn't support.
Every tool declared in `tools` is offered to the model from the start of the conversation unless it is declared with `defer_loading: true`, which keeps it withheld until a `tool_addition` block surfaces it. `tool_addition` also re-offers a tool that an earlier `tool_removal` withdrew.
The following request declares `get_weather` in `tools`, then withdraws it after the first user turn with a `tool_removal` block. The request sends the `inline-tools-2026-09-15` beta header.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
betas=["inline-tools-2026-09-15"],
# The full tool set is declared up front and never changes, so the
# cached prefix stays intact.
tools=[
{
"name": "get_weather",
"description": "Get the current weather for a location.",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"},
},
"required": ["location"],
},
},
],
messages=[
{
"role": "user",
"content": "Say OK.",
},
# Withdraw get_weather from this point onward. The block references
# the tool by name instead of editing `tools`, so earlier turns stay
# byte-identical and the cache still hits.
{
"role": "system",
"content": [
{
"type": "tool_removal",
"tool": {"type": "tool_reference", "name": "get_weather"},
},
],
},
],
)
for block in response.content:
if block.type == "text":
print(block.text)
```
### Define tools in a message (beta)
With the `inline-tools-2026-09-15` beta header, a `tool_addition` block can define a tool by value, carrying its full definition, instead of naming it by reference. This lets you introduce a tool that is unknown at the start of the conversation, or whose schema changes later, by appending a `role: "system"` message. The `tools` array and every earlier message stay exactly as sent, so the prompt cache still hits and only the appended message is processed as new input. The one exception, a `tools` array with no non-deferred tool, is covered in the rules below. The header also covers adding and removing tools by reference, so you don't need to send `mid-conversation-tool-changes-2026-07-01` as well.
Wrap the definition in a `tool` object of type `tool_definition`. The `definition` is a `tools` entry, such as a custom tool or an Anthropic-defined client or server tool, with its usual configuration, including `cache_control` and `defer_loading`. During the beta, some tool types (the computer use tool among them) can't be defined in a message yet and return a 400 error that says so; declare those in `tools` and add them by reference. For example, to define a custom tool mid-conversation:
```python
{
"role": "system",
"content": [
{
"type": "tool_addition",
"tool": {
"type": "tool_definition",
"definition": {
"name": "db_query",
"description": "Run a read-only SQL query against the analytics database.",
"input_schema": {
"type": "object",
"properties": { "sql": { "type": "string" } },
"required": ["sql"]
}
}
}
}
]
}
```
From that position onward, the model can call the tool the same way it calls a tool declared in `tools`. Sending an identical definition again changes nothing, so a client can safely resend it, for example on a retry.
The following request keeps `get_weather` in `tools` and defines `db_query` after the first user turn:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
betas=["inline-tools-2026-09-15"],
# Keep at least one non-deferred tool in `tools`, so a tool defined
# later doesn't change the start of the rendered prompt.
tools=[
{
"name": "get_weather",
"description": "Get the current weather for a location.",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"},
},
"required": ["location"],
},
},
],
messages=[
{"role": "user", "content": "How many orders shipped yesterday?"},
# Define db_query by value from this point onward. `tools` and the
# earlier messages stay exactly as sent, so the cache still hits.
{
"role": "system",
"content": [
{
"type": "tool_addition",
"tool": {
"type": "tool_definition",
"definition": {
"name": "db_query",
"description": "Run a read-only SQL query against the analytics database.",
"input_schema": {
"type": "object",
"properties": {"sql": {"type": "string"}},
"required": ["sql"],
},
},
},
},
],
},
],
)
for block in response.content:
if block.type == "tool_use":
print(block.name, block.input)
```
The response's `content` includes a `tool_use` block for the new tool, for example:
```python
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "db_query",
"input": {
"sql": "SELECT COUNT(*) FROM orders WHERE shipped_at::date = CURRENT_DATE - 1"
}
}
```
To change a tool's schema, or to move a server tool to a newer version, send a different definition under the same name. The new definition replaces the earlier one from that position onward. A definition that reuses the name of a different type of tool returns a 400 error with `error.details.error_code` set to `tool_name_conflict`. A newer version of the same tool doesn't count as a different type. `tool_removal` still takes a reference, and a removed tool can be defined or re-offered again later.
A few rules follow from where the definition renders:
- **Declare what you know up front.** A tool you know about at the first request belongs in `tools`, with `defer_loading: true` and a later `tool_addition` reference if the model shouldn't see it yet. Define by value only what is unknown at the first request or changes later.
- **Keep at least one non-deferred tool in `tools`.** A conversation whose `tools` array has no non-deferred tool is accepted, but the first tool it defines by value changes the start of the rendered prompt, which costs one full cache miss on that request. A [tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md) counts as non-deferred.
- **Dated tool types keep their own beta headers.** If a server tool you define by value requires its own beta header, send that header on every later request in the conversation.
- **`cache_control` goes on the block or in the definition, not both,** and counts toward the request's breakpoint limit. A deferred definition can't carry `cache_control`.
A request returns a 400 error with `error.details.error_code` set to `available_tools_limit_exceeded` when any of these limits is exceeded:
- More than 10,000 deferred tools are available after any message.
- More than 10,000 tools defined after the first user message are available after any message.
- The tool definitions sent after the first user message that are still available after any message total more than 4 MB (4,194,304 bytes).
- The rendered tool text is larger than 4 MB (4,194,304 bytes).
### Add an MCP server mid-conversation (beta)
To add an [MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md) server partway through a conversation, send the `mcp-client-2026-09-15` beta header along with `inline-tools-2026-09-15`. The `definition` in a `tool_addition` block can then be an `mcp_toolset`, so the server's tools become available without editing `tools`. List the server's connection details in `mcp_servers` as usual, then append the toolset where the server became available:
```python
{
"role": "system",
"content": [
{
"type": "tool_addition",
"tool": {
"type": "tool_definition",
"definition": { "type": "mcp_toolset", "mcp_server_name": "calendar" }
}
}
]
}
```
The `mcp_toolset` object is the same one you would put in `tools`, including `default_config` and `configs`. A `tool_addition` block never holds a server URL or token. Those stay in `mcp_servers`.
The following request keeps `get_weather` in `tools`, lists the calendar server in `mcp_servers`, and adds the server's toolset after the first user turn:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
betas=["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
mcp_servers=[
{
"type": "url",
"url": "https://mcp.example.com/calendar",
"name": "calendar",
"authorization_token": "YOUR_TOKEN",
},
],
tools=[
{
"name": "get_weather",
"description": "Get the current weather for a location.",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"},
},
"required": ["location"],
},
},
],
messages=[
{"role": "user", "content": "What's on my calendar tomorrow?"},
# Make the calendar server's tools available from this point onward.
# The block names the server; it never holds a URL or token.
{
"role": "system",
"content": [
{
"type": "tool_addition",
"tool": {
"type": "tool_definition",
"definition": {
"type": "mcp_toolset",
"mcp_server_name": "calendar",
},
},
},
],
},
],
)
# The response starts with an mcp_tool_listing block for the calendar server,
# so check each block's type instead of reading content[0].
for block in response.content:
match block.type:
case "mcp_tool_listing":
print(block.mcp_server_name, [tool.name for tool in block.tools])
case "text":
print(block.text)
```
With `mcp-client-2026-09-15`, a response for which the API fetched a server's tool list starts with an `mcp_tool_listing` block, one for each server it fetched. If your code reads `content[0]`, skip these blocks. Send the assistant message back unchanged, this block included, and keep sending `mcp-client-2026-09-15` on every request that carries it. Later requests then use the recorded list instead of asking the server again. To pin a toolset yourself, copy that list into the `mcp_toolset`'s `tools` field, as described in [Pin an MCP server's tool list](../Agents-Tools/agents-and-tools-mcp-connector.md#pin-mcp-tool-list).
`mcp-client-2026-09-15` includes everything `mcp-client-2025-11-20` does, so you don't need to send both. These features are available on the Claude API. Requests that use the MCP connector keep its [data retention](../Agents-Tools/agents-and-tools-mcp-connector.md#data-retention) terms.
## When to use a mid-conversation system message
[Prompt caching](build-with-claude-prompt-caching.md) hashes the request prefix in order: `tools`, then `system`, then `messages`. A cache hit requires the prefix to match a recent request exactly, byte for byte, up to the cache breakpoint.
That ordering means the top-level `system` field sits near the very start of the hashed prefix. Any change to it, even appending a sentence, produces a different hash, and the request misses the cache for the system prompt and every cached message after it.
Mid-conversation system messages let you add the instruction at the **end** of the message history instead. Everything before the new instruction is unchanged, so the existing cache entry still matches, and only the new message is processed as fresh input.
A few situations where this matters:
- **Mid-session policy or persona changes.** A long agentic session needs a new constraint ("from now on, write all SQL as parameterized queries") after dozens of cached turns. Adding it to the top-level `system` field would re-process the entire history.
- **Per-turn context that must be authoritative.** You want to inject a freshness note, a session deadline, or a tool-availability change with system-level weight, and it changes too often to live in the cached prefix.
- **Per-turn reminders that shouldn't pile up.** A harness nudges the model after each batch of tool results ("request independent reads together", "the user hasn't heard from you in a while") and wants the model to see only the newest copy. A [turn-scoped system message](#turn-scoped-system-messages) renders for one turn and then costs nothing, without deleting anything from the history.
- **State changes your application observes.** Your application notices something Claude should treat as an operator-level fact: files changed on disk, the user toggled an auto-approve setting, available tools changed, or the remaining token budget dropped below a threshold.
- **User input that should not interrupt an agentic loop.** A user types a follow-up while Claude is still executing tools for the previous request. Relaying it as a system message after the next tool result lets Claude fold the new input into the work it is already doing, instead of treating it as a fresh request to switch to. See [Placement after tool results](#placement-after-tool-results).
- **Mode switches that grant standing permissions.** A session-level mode can use a mid-conversation system message to grant standing consent to an expensive capability, such as automatically launching multiagent workflows, with a short refresher every several turns and an exit notice when the mode is turned off. For a worked example, see [Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md).
In all of these cases you could put the instruction in a regular `user` message, and Claude does follow instructions that arrive in user turns. The difference is priority: a `user` message is treated as coming from the end user, while a `system` message is treated as coming from you, the application operator. When the two conflict, system instructions take precedence, so use the `system` role for operator-level facts and constraints that should hold even if the end user asks for something different. A mid-conversation system message keeps that operator-level priority without paying the cache-miss cost of editing the top-level `system` field.
## How it works
Add a message with `"role": "system"` to the `messages` array. Use a plain string or content blocks for `content`, the same as a `user` or `assistant` turn. The instruction applies from that point in the conversation onward. When instructions conflict, later system messages take precedence over earlier ones, and mid-conversation system messages take precedence over the top-level `system` field for the turns that follow them.
You can still set the top-level `system` field for instructions that should apply to the entire conversation. Reserve mid-conversation system messages for instructions that only become relevant later, or that you want to add without invalidating the cached prefix.
A `role: "system"` message can also carry `output_config.effort` to change the [effort](build-with-claude-effort.md) level from the next `user` turn on. This is in beta on Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, and Claude Opus 5 on the Claude API and Google Cloud, and requires the `mid-conversation-output-config-2026-07-01` beta header. See [Per-message effort](build-with-claude-effort.md#change-effort-mid-conversation-beta).
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
# Automatic prompt caching: each request caches the conversation so far,
# and the next request reads the unchanged prefix from cache.
cache_control={"type": "ephemeral"},
system="You are a code review assistant. Be concise.",
messages=[
{
"role": "user",
"content": "Review process() in utils.py for performance issues.",
},
{
"role": "assistant",
"content": "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.",
},
{
"role": "user",
"content": "Now review the calling code that invokes process().",
},
# The reviewer realizes mid-session that all suggestions must
# also pass the team's strict typing policy. Appending the
# instruction here keeps earlier turns byte-identical, so the
# prefix cached by the previous request is still read from cache.
{
"role": "system",
"content": "From now on, every suggestion must include explicit type annotations.",
},
],
)
for block in response.content:
if block.type == "text":
print(block.text)
```
This example enables [automatic caching](build-with-claude-prompt-caching.md#automatic-caching) with the top-level `cache_control` field. Prompt caching is opt-in: if a request has no `cache_control` field (automatic or an [explicit breakpoint](build-with-claude-prompt-caching.md#explicit-cache-breakpoints)), nothing is cached and every request pays the regular input token price for the full conversation. With caching enabled, appending the system message leaves the already-cached turns unchanged, so the request that carries the new instruction still reads them from cache instead of processing them again. Caching also requires the conversation to meet the [minimum cacheable prompt length](build-with-claude-prompt-caching.md#cache-limitations); an example as short as this one falls below it, so `cache_creation_input_tokens` and `cache_read_input_tokens` stay at 0 until the conversation grows.
A mid-conversation system message must immediately follow a `user` turn (or an `assistant` turn ending in a server tool result), and must either be the last entry in `messages` or be immediately followed by an `assistant` turn. A `user` message that carries `tool_result` blocks counts: in an agentic loop you can place the system message right after the tool results, before Claude's next turn. Any other position, including between an `assistant` `tool_use` block and the `tool_result` that answers it, returns a 400 error.
### Placement after tool results
In an [agentic loop](../Agents-Tools/agents-and-tools-tool-use-overview.md), the system message goes after the `user` message that delivers the tool results. This is also where your application can relay input that the user typed while Claude was working, so the new context is absorbed without restarting the turn:
```python
[
{ "role": "user", "content": "Run the test suite and fix any failures." },
{
"role": "assistant",
"content": [{ "type": "tool_use", "id": "toolu_01", "name": "run_tests", "input": {} }]
},
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 passed, 0 failed" }
]
},
{
"role": "system",
"content": "The user sent the following message while you were working: also update the changelog before you finish."
}
]
```
Phrase the system content as context rather than as a command that overrides the user. State the fact ("new input arrived from the user: X", "the remaining token budget is now Y") and let Claude act on it. Claude is trained to resist instructions that appear to work against the user, and that protection still applies to the system role, so language such as "ignore what the user said" is less effective than stating what changed.
This pattern is for relaying input from the conversation's own end user. Do not use it to pass tool output, retrieved documents, or other third-party content; keep that content in `tool_result` blocks (see [Limitations](#limitations)).
### Turn-scoped system messages
To scope a `role: "system"` message to the current turn, set its `clear_at` field. It takes one of two values:
- `"never"` (the default): the message renders at its position on every request that includes it. Omitting the field is identical.
- `"next_user_message"`: the message is **turn-scoped**. Its text renders only while no `role: "user"` message comes after it in `messages`. A user message that carries only `tool_result` blocks counts as a user message here. Once a later user message exists, the message is **cleared**: it stays in the array but renders nothing and costs no input tokens, on that request and every later one.
Turn-scoped system messages are in beta. Include the [beta header](../Endpoints/beta-headers.md) `mid-conversation-system-clear-at-2026-08-21`. Without it, `clear_at` is rejected as an unknown field.
```python
{
"role": "system",
"clear_at": "next_user_message",
"content": "First privately list what you need next; then request every item that doesn't depend on another's result in this one response."
}
```
The main use is a per-turn reminder in a tool loop. Append the reminder after the `tool_result` message each time you want the model to see it, and leave every earlier copy where it is. The model sees only the copies that come after the last user message, so the reminder never piles up. Nothing earlier in `messages` changes, so the [prompt cache](build-with-claude-prompt-caching.md) keeps matching. On Claude Fable 5.1 and Claude Opus 5.5 this also keeps later [thinking blocks valid](build-with-claude-thinking.md#preserved-in-conversation): deleting an earlier reminder would change the conversation before those blocks and fail the conversation check, while a cleared message stays in the array and leaves that conversation unchanged.
The following request is a later step of an agent loop. `messages[3]` rendered on the earlier request, when it was the last message in the array. Once `messages[5]` (a later user message) exists, `messages[3]` is cleared: the cleared message stays in the array, so the conversation before the thinking block in `messages[4]` is unchanged, but the model no longer sees its text. `messages[6]` and `messages[7]` both render, in order.
```python
{
"model": "claude-fable-5-1",
"max_tokens": 16000,
"messages": [
{ "role": "user", "content": "Fix the failing test." },
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "", "signature": "..." },
{
"type": "tool_use",
"id": "toolu_01",
"name": "read_file",
"input": { "path": "test_auth.py" }
}
]
},
{
"role": "user",
"content": [{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "..." }]
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "Request independent reads in one turn."
},
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "", "signature": "..." },
{
"type": "tool_use",
"id": "toolu_02",
"name": "read_file",
"input": { "path": "auth.py" }
},
{
"type": "tool_use",
"id": "toolu_03",
"name": "read_file",
"input": { "path": "tokens.py" }
}
]
},
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_02", "content": "..." },
{
"type": "tool_result",
"tool_use_id": "toolu_03",
"content": "...",
"cache_control": { "type": "ephemeral" }
}
]
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "Request independent reads in one turn."
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "The shell exited with status 137."
}
]
}
```
Rules for turn-scoped messages:
- **Re-send cleared messages verbatim.** A cleared message is still part of the conversation history. Rebuilding it from current state (a fresh token count, a timestamp), dropping it as redundant, or changing its `clear_at` value is an edit to an earlier message. The prompt cache misses from that point, and on Claude Fable 5.1 and Claude Opus 5.5 every thinking block produced after it fails the [conversation check](build-with-claude-thinking.md#preserved-in-conversation).
- **Text only.** `content` is one or more `text` blocks (or a string). `tool_addition` and `tool_removal` blocks return a 400 error on a turn-scoped message, and so does `output_config`. Use a separate `role: "system"` message without `clear_at` for those.
- **No `cache_control` on its blocks.** A cleared message is never part of a cache key, so a breakpoint on it could never match. Put the breakpoint on the last block of the preceding user turn instead, as the example does. The top-level [automatic caching](build-with-claude-prompt-caching.md#automatic-caching) field skips turn-scoped messages when it picks a breakpoint. On the request that clears a message, the reusable cached prefix ends at the user turn before it, so only the one assistant turn between that message and the new user message is reprocessed.
- **Placement rules still apply**, cleared or not. A turn-scoped message must follow a `user` turn (or an `assistant` turn ending in a server tool result) and precede an `assistant` turn or end the array, like any mid-conversation system message. One that ends the array always renders. One followed directly by another `user` message is a 400 error, not a cleared message: put all of a tool round's results in one user message and the reminders after it.
- **Assistant turns don't clear it.** A prefilled or [paused](build-with-claude-handling-stop-reasons.md#pause-turn) assistant turn after the message, or a server-side tool loop, adds no user message, so the message still renders on that continuation. To keep a reminder in view through a client-side tool loop, append it again after each `tool_result` message.
- **Token counting follows what renders.** A cleared message adds nothing to `usage.input_tokens` or to a [token count](build-with-claude-token-counting.md).
- **Imported history.** In a transcript you construct in one step (few-shot examples, a migrated conversation), a turn-scoped message that already has an assistant turn and a user message after it is cleared from the first request and never renders. That is the right state for a per-turn reminder you are carrying over. Leave `clear_at` unset only on a message the model should see on every request.
The validation errors are:
```python
messages.3.clear_at: Extra inputs are not permitted
messages.3.clear_at: clear_at is only permitted on role 'system' messages
messages.3.clear_at: Input should be 'next_user_message' or 'never'
messages.3: a turn-scoped system message supports text blocks only (clear_at: 'next_user_message')
messages.3: output_config is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
messages.3.content.0: cache_control is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
```
The first is the error returned without the beta header. On Amazon Bedrock and Google Cloud, pass the beta value as described in [Beta headers](../Endpoints/beta-headers.md).
Through the SDKs, set `clear_at` on the `role: "system"` entry in `messages` and send the beta header. The following example appends a turn-scoped reminder after the user turn; on the next request, once a later user message exists, the reminder stays in the array but no longer renders:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=4096,
messages=[
{
"role": "user",
"content": "Draft a short status update on the database migration for the team channel.",
},
# Turn-scoped reminder: renders for this turn, then clears once a later user message exists.
{
"role": "system",
"clear_at": "next_user_message",
"content": "The reader is on call: keep this reply under 50 words.",
},
],
betas=["mid-conversation-system-clear-at-2026-08-21"],
)
for block in response.content:
if block.type == "text":
print(block.text)
```
## Combining with prompt caching
Mid-conversation system messages and [prompt caching](build-with-claude-prompt-caching.md) are designed to be used together:
- **Enable caching explicitly.** Caching only happens when the request includes `cache_control`, either the top-level [automatic caching](build-with-claude-prompt-caching.md#automatic-caching) field or an [explicit breakpoint](build-with-claude-prompt-caching.md#explicit-cache-breakpoints) on a content block. A mid-conversation system message does not create a cache entry on its own, and without caching enabled there are no savings to preserve.
- **Cache the stable prefix as usual.** Place `cache_control` on the last block that stays the same across requests, whether that is the end of the top-level `system` field, the end of your tool definitions, or a stable point in the message history.
- **Append the system message after the breakpoint.** Because it comes after the cached prefix, it does not change the prefix hash and the cache still hits.
- **A mid-conversation system message is itself cacheable.** Once it is in the conversation, it becomes part of the stable history. On the next turn you can move your cache breakpoint past it (or rely on [automatic caching](build-with-claude-prompt-caching.md#automatic-caching) to do so) and the system message is read from cache like any other turn.
Avoid editing or removing a mid-conversation system message that has already been sent. Like any other change to earlier messages, that invalidates the cache from that point forward. On Claude Fable 5.1 and Claude Opus 5.5 it also invalidates the [thinking blocks](build-with-claude-thinking.md#preserved-in-conversation) in every later assistant turn. For guidance that should apply to one turn only, use a [turn-scoped system message](#turn-scoped-system-messages) and leave it in place. If the instruction needs to evolve, append a new system message rather than rewriting the old one. Consecutive system messages are accepted and treated as a single system section, which follows the same placement rule as a whole.
## Limitations
- **Not for the first message.** A `system` message that carries content cannot be the first entry in `messages`. Use the top-level `system` field for instructions that apply from the very start.
- **Placement is constrained.** A `system` message that carries content (`text`, `tool_addition`, or `tool_removal` blocks) must immediately follow a `user` turn (including a `user` turn that carries `tool_result` blocks) or an `assistant` turn ending in a server tool result, and must precede an `assistant` turn or end the array. It cannot sit between a `tool_use` block and its `tool_result`. Placing it elsewhere returns a 400 error. One exception: `tool_addition` and `tool_removal` blocks are not accepted immediately after a [paused](build-with-claude-handling-stop-reasons.md#pause-turn) `assistant` turn (one ending in a server tool result), though `text` blocks are; resume the paused turn first, then send the tool change in the next `system` message. A message with empty `content` that only sets [`output_config.effort`](build-with-claude-effort.md#change-effort-mid-conversation-beta) renders nothing at its position and is accepted anywhere in `messages`, including first or between an `assistant` turn and a `user` turn. Consecutive `system` messages are judged together, so adding a text-carrying message next to an effort-only one makes the whole group follow the content rule.
- **Turn-scoped messages are text-only and re-sent verbatim.** A `clear_at: "next_user_message"` message carries no `tool_addition`, `tool_removal`, `output_config`, or `cache_control`, and once cleared it must stay in `messages` byte-for-byte on later requests. See [Turn-scoped system messages](#turn-scoped-system-messages).
- **Not a place for untrusted content.** Claude treats system content as operator instructions and follows it. Do not place text from outside the conversation, such as raw tool output, retrieved documents, or web content, directly in a system message; doing so gives that text operator-level authority. Keep that data in `tool_result` blocks and continue to follow [Mitigate jailbreaks and prompt injections](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-mitigate-jailbreaks.md).
## Related
[Prompt caching](build-with-claude-prompt-caching.md)
How caching works, where to place breakpoints, and how to read cache usage fields.
[Cache diagnostics](build-with-claude-cache-diagnostics.md)
Find out exactly where two requests diverged when a cache hit you expected does not happen.
[Using the Messages API](build-with-claude-working-with-messages.md)
Message structure, multi-turn conversations, and the `system` field.
[Prompting best practices](../../10-Prompting-Guides/build-with-claude-prompt-engineering-claude-prompting-best-practices.md)
Writing effective prompts and system instructions.
[Tool use with Claude](../Agents-Tools/agents-and-tools-tool-use-overview.md)
How `tool_use` and `tool_result` blocks are structured in the `messages` array.
---
## Multilingual support - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/multilingual-support
Path: 04-API-Reference/Guides/build-with-claude-multilingual-support.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fmultilingual-support)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Model capabilities
# Multilingual support
Copy page
Claude excels at tasks across multiple languages, maintaining strong cross-lingual performance relative to English.
Copy page
## Overview
Claude demonstrates robust multilingual capabilities, with particularly strong performance in zero-shot tasks across languages. The model maintains consistent relative performance across both widely spoken and lower-resource languages, making it a reliable choice for multilingual applications.
Claude is capable in many languages beyond those benchmarked in the following table. Test with any languages relevant to your specific use cases.
## Performance data
The following table shows zero-shot chain-of-thought evaluation scores for Claude models across languages, expressed as a percentage relative to English performance (100%):
| Language | Claude Sonnet 4.5¹ | Claude Haiku 4.5¹ |
|-----------------------------------|--------------------|-------------------|
| English (baseline, fixed to 100%) | 100% | 100% |
| Spanish | 98.2% | 96.4% |
| Portuguese (Brazil) | 97.8% | 96.1% |
| Italian | 97.9% | 96.0% |
| French | 97.5% | 95.7% |
| Indonesian | 97.3% | 94.2% |
| German | 97.0% | 94.3% |
| Arabic | 97.2% | 92.5% |
| Chinese (Simplified) | 96.9% | 94.2% |
| Korean | 96.7% | 93.3% |
| Japanese | 96.8% | 93.5% |
| Hindi | 96.7% | 92.4% |
| Bengali | 95.4% | 90.4% |
| Swahili | 91.1% | 78.3% |
| Yoruba | 79.7% | 52.7% |
¹ With [extended thinking](build-with-claude-extended-thinking.md).
These metrics are based on [MMLU (Massive Multitask Language Understanding)](https://en.wikipedia.org/wiki/MMLU) English test sets that were translated into 14 additional languages by professional human translators, as documented in [OpenAI's simple-evals repository](https://github.com/openai/simple-evals/blob/main/multilingual_mmlu_benchmark_results.md). The use of human translators for this evaluation ensures high-quality translations, particularly important for languages with fewer digital resources.
------------------------------------------------------------------------
## Set the response language
Claude infers the response language from the conversation, but for production applications you should state the target language explicitly. The most reliable place to do this is the system prompt, which keeps the instruction stable across every turn of a conversation.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
system="Always respond in French, regardless of the language the user writes in.",
messages=[{"role": "user", "content": "How do I reset my password?"}],
)
print(message.content)
```
If your application lets users pick a language at runtime, interpolate that choice into the system prompt rather than relying on Claude to infer it from the user's message. To translate between two specific languages, name both: `Translate the user's message from German to Korean. Respond with only the translation.`
------------------------------------------------------------------------
## Best practices
When working with multilingual content:
1. **Provide clear language context:** Although Claude can detect the target language automatically, explicitly stating the desired input and output languages improves reliability. For enhanced fluency, you can prompt Claude to use "idiomatic speech as if it were a native speaker."
2. **Use native scripts:** Submit text in its native script rather than transliteration for optimal results.
3. **Consider cultural context:** Effective communication often requires cultural and regional awareness beyond pure translation.
Also follow the general guidance in [Prompt engineering overview](../../10-Prompting-Guides/build-with-claude-prompt-engineering-overview.md) to further improve output quality.
------------------------------------------------------------------------
## Language support considerations
- Claude processes input and generates output in most world languages that use standard Unicode characters.
- Performance varies by language, with particularly strong capabilities in widely spoken languages.
- Even in languages with fewer digital resources, Claude maintains meaningful capabilities.
## Next steps
[Prompt engineering overview](../../10-Prompting-Guides/build-with-claude-prompt-engineering-overview.md)
Apply general prompting techniques to improve multilingual output quality.
[Customer support agent](../About/about-claude-use-case-guides-customer-support-chat.md)
Build a localized support chatbot using a language-constrained system prompt.
[Models overview](../../20-Models/about-claude-models-overview.md)
Compare model tiers to balance multilingual quality against cost and latency.
[Define success criteria and build evaluations](../Test-Evaluate/test-and-evaluate-develop-tests.md)
Evaluate translation and localization quality before you ship.
---
## Features overview - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/overview
Path: 04-API-Reference/Guides/build-with-claude-overview.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Foverview)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Building with Claude
# Features overview
Copy page
Explore Claude's advanced features and capabilities.
Copy page
Claude's API surface is organized into five areas:
- **Model capabilities:** Control how Claude reasons and formats responses.
- **Tools:** Let Claude take actions on the web or in your environment.
- **Tool infrastructure:** Handles discovery and orchestration at scale.
- **Context management:** Keeps long-running sessions efficient.
- **Files and assets:** Manage the documents and data you provide to Claude.
If you're new, start with [model capabilities](#model-capabilities) and [tools](#tools). Return to the other sections when you're ready to optimize cost, latency, or scale.
For administration and governance, see the [Admin API](../Other/manage-claude-admin-api.md), the [Usage and Cost API](../Other/manage-claude-usage-cost-api.md), and the [Compliance API](../Other/manage-claude-compliance-api.md).
## Feature availability
The Availability column in each of the following tables lists the platforms that offer a feature. A platform listed without a label offers the feature as stable, fully supported, and recommended for production use, with no beta header and with standard API [versioning](../Endpoints/versioning.md) guarantees. A label after a platform name marks one of the following classifications on that platform. Not all features pass through every stage, and a feature may enter at any stage or skip stages.
[TABLE]
**Platform labels:** Claude API (Anthropic first-party) · [Bedrock](build-with-claude-claude-in-amazon-bedrock.md) (AWS-operated) · [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md) (Anthropic-operated on AWS) · [Google Cloud](build-with-claude-claude-on-vertex-ai.md) (Google-operated) · [Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md) (Anthropic-operated on Azure)
## Model capabilities
Ways to steer Claude and Claude's direct outputs, including response format, reasoning depth, and input modalities.
You can discover which capabilities a model supports programmatically. The [Models API](../Endpoints/models-list.md) returns `max_input_tokens`, `max_tokens`, and a `capabilities` object for every available model.
The ZDR column indicates whether a feature is available under a Zero Data Retention arrangement. For most features this depends only on what the feature mechanism retains; for features tied to specific models, model-level ZDR availability also applies. See [Model-specific data retention requirements](../Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements).
[TABLE]
## Tools
Built-in tools that Claude invokes through `tool_use`. Server-side tools are run by the platform; client-side tools are implemented and executed by you.
### Server-side tools
[TABLE]
### Client-side tools
[TABLE]
## Tool infrastructure
Infrastructure that supports discovering, orchestrating, and scaling tool use.
[TABLE]
## Context management
Infrastructure for controlling and optimizing Claude's context window.
[TABLE]
## Files and assets
Manage files and assets for use with Claude.
[TABLE]
\* **Structured outputs:** Your prompts and Claude's outputs are not stored. Only JSON schemas are cached, for up to 24 hours since last use. **Web search and web fetch:** ZDR-eligible except when [dynamic filtering](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md#dynamic-filtering) is enabled. **Fallback credit and server-side fallback:** The features retain no message content, but they handle refusals from the Claude Fable models, which [are not available under ZDR](../Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements). See [ZDR details](../Other/manage-claude-api-and-data-retention.md#feature-eligibility).
† On Microsoft Foundry, feature availability differs by [hosting option](build-with-claude-claude-in-microsoft-foundry.md#hosting-options). These features are available on Hosted on Anthropic deployments, and not on Hosted on Azure deployments.
‡ On Microsoft Foundry, the [Skill version download endpoint](../Endpoints/beta-skills-versions-download.md) (`GET /v1/skills/{skill_id}/versions/{version}/content`) is not supported.
---
## PDF support - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/pdf-support
Path: 04-API-Reference/Guides/build-with-claude-pdf-support.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fpdf-support)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Working with files
# PDF support
Copy page
Process PDFs with Claude: extract text, analyze charts, and understand visual content from your documents.
Copy page
PDF support
[ZDR](../Other/manage-claude-api-and-data-retention.md)
Eligible
excludes [Covered Models](../Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements)
You can ask Claude about any text, pictures, charts, and tables in PDFs you provide. Some sample use cases:
- Analyzing financial reports and understanding charts/tables
- Extracting key information from legal documents
- Assisting with document translation
- Converting document information into structured formats
## Before you begin
### Check PDF requirements
Claude works with any standard PDF. Ensure your request size meets these requirements:
| Requirement | Limit |
|---------------------------|-------------------------------------------------------------------------|
| Maximum request size | 32 MB ([varies by platform](../Endpoints/overview.md#request-size-limits)) |
| Maximum pages per request | 600 (100 when the request's context window is under 1M tokens) |
| Format | Standard PDF (no passwords/encryption) |
Both limits are on the entire request payload, including any other content sent alongside PDFs. For large PDFs, consider uploading with the [Files API](build-with-claude-files.md) and referencing by `file_id` to keep request payloads small.
Dense PDFs (many small-font pages, complex tables, or heavy graphics) can fill the context window before reaching the page limit. Requests with large PDFs can also fail before reaching the page limit, even when using the Files API. Try splitting the document into sections; for large files, because each page is processed as an image, downsampling embedded images can also help.
Because PDF support relies on Claude's vision capabilities, it is subject to the same [limitations and considerations](build-with-claude-vision.md#limitations) as other vision tasks.
### Supported platforms and models
All [active models](../../20-Models/about-claude-models-overview.md) support PDF processing. For PDF support through Amazon Bedrock's Converse API, see [Amazon Bedrock PDF support](#amazon-bedrock-pdf-support).
### Amazon Bedrock PDF support
When using PDF support through the Converse API, part of [Claude on Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md), there are two distinct document processing modes:
**Important:** To access Claude's full visual PDF understanding capabilities in the Converse API, you must enable citations. Without citations enabled, the API falls back to basic text extraction only. Learn more about [working with citations](build-with-claude-citations.md).
#### Document processing modes
1. **Converse Document Chat** (Original mode - Text extraction only)
- Provides basic text extraction from PDFs
- Cannot analyze images, charts, or visual layouts within PDFs
- Uses approximately 1,000 tokens for a 3-page PDF
- Automatically used when citations are not enabled
2. **Claude PDF Chat** (New mode - Full visual understanding)
- Provides complete visual analysis of PDFs
- Can understand and analyze charts, graphs, images, and visual layouts
- Processes each page as both text and image for comprehensive understanding
- Uses approximately 7,000 tokens for a 3-page PDF
- **Requires citations to be enabled** in the Converse API
#### Key limitations
- **Converse API:** Visual PDF analysis requires citations to be enabled. There is currently no option to use visual analysis without citations (unlike the InvokeModel API).
- **InvokeModel API:** Provides full control over PDF processing without forced citations.
#### Common issues
If Claude isn't seeing images or charts in your PDFs when using the Converse API, you likely need to enable the citations flag. Without it, Converse falls back to basic text extraction only.
This is a known constraint with the Converse API. For applications that require visual PDF analysis without citations, consider using the InvokeModel API instead.
Plain text files such as .txt, .csv, or .md can be used directly in document blocks: upload them to the Files API with MIME type `text/plain` and reference them by `file_id`. Binary formats such as .xlsx or .docx are not supported in document blocks and must be converted to text or PDF first. See [Working with other file formats](build-with-claude-files.md#working-with-other-file-formats).
## Process PDFs with Claude
### Send your first PDF request
Start with a simple example using the Messages API. You can provide PDFs to Claude in three ways:
1. As a URL reference to a PDF hosted online
2. As a base64-encoded PDF in `document` content blocks
3. By a `file_id` from the [Files API](build-with-claude-files.md)
On Amazon Bedrock and Google Cloud, only base64-encoded sources are currently available. On Microsoft Foundry, the Files API is not supported for deployments hosted on Azure.
#### Option 1: URL-based PDF document
The simplest approach is to reference a PDF directly from a URL:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "url",
"url": "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf",
},
},
{"type": "text", "text": "What are the key findings in this document?"},
],
}
],
)
print(message.content)
```
The response returns Claude's analysis as text blocks in `content`, with token consumption in `usage`:
Output
```python
{
"id": "msg_01Hfp8YuFjQ55VgWbpdHDehB",
"type": "message",
"role": "assistant",
"model": "claude-opus-5-5",
"content": [
{
"type": "text",
"text": "This document is an addendum to the Claude 3 model card, reporting updated evaluation results. The key findings include..."
}
],
"stop_reason": "end_turn",
"usage": {
"input_tokens": 45000,
"output_tokens": 300
}
}
```
#### Option 2: Base64-encoded PDF document
If you need to send PDFs from your local system or when a URL isn't available:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import base64
import httpx2
# First, load and encode the PDF
pdf_url = "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
pdf_data = base64.standard_b64encode(
httpx2.get(pdf_url, follow_redirects=True).content
).decode("utf-8")
# Alternative: Load from a local file
# with open("document.pdf", "rb") as f:
# pdf_data = base64.standard_b64encode(f.read()).decode("utf-8")
# Send to Claude using base64 encoding
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": pdf_data,
},
},
{"type": "text", "text": "What are the key findings in this document?"},
],
}
],
)
print(message.content)
```
#### Option 3: Files API
For PDFs you'll use repeatedly, or when you want to avoid encoding overhead, use the [Files API](build-with-claude-files.md):
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Upload the PDF file
with open("/path/to/document.pdf", "rb") as f:
file_upload = client.files.upload(file=("document.pdf", f, "application/pdf"))
# Use the uploaded file in a message
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {"type": "file", "file_id": file_upload.id},
},
{"type": "text", "text": "What are the key findings in this document?"},
],
}
],
)
print(message.content)
```
### How PDF support works
When you send a PDF to Claude, the following steps occur:
1. 1
### The system extracts the contents of the document.
- The system converts each page of the document into an image.
- The text from each page is extracted and provided alongside each page's image.
2. 2
### Claude analyzes both the text and images to better understand the document.
- Documents are provided as a combination of text and images for analysis.
- This allows users to ask for insights on visual elements of a PDF, such as charts, diagrams, and other non-textual content.
3. 3
### Claude responds, referencing the PDF's contents if relevant.
Claude can reference both textual and visual content when it responds. You can further improve performance by integrating PDF support with:
- [Use prompt caching](#use-prompt-caching): To improve performance for repeated analysis.
- [Process document batches](#process-document-batches): For high-volume document processing.
- [Tool use](../Agents-Tools/agents-and-tools-tool-use-overview.md): To extract specific information from documents for use as tool inputs.
### Estimate your costs
The token count of a PDF file depends on the total text extracted from the document and the number of pages:
- Text token costs: Each page typically uses 1,500–3,000 tokens per page depending on content density. Standard API pricing applies with no additional PDF fees.
- Image token costs: Because each page is converted into an image, the same [image-based cost calculations](build-with-claude-vision.md#evaluate-image-size) are applied.
You can use [token counting](build-with-claude-token-counting.md) to estimate costs for your specific PDFs.
## Optimize PDF processing
### Improve performance
Follow these best practices for optimal results:
- Place PDFs before text in your requests
- Use standard fonts
- Ensure text is clear and legible
- Rotate pages to proper upright orientation
- Use logical page numbers (from PDF viewer) in prompts
- Split large PDFs into chunks when needed
- Enable prompt caching for repeated analysis
### Scale your implementation
For high-volume processing, consider these approaches:
#### Use prompt caching
Cache PDFs with [prompt caching](build-with-claude-prompt-caching.md) to improve performance on repeated queries:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import base64
import httpx2
# First, load and encode the PDF
pdf_url = "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
pdf_data = base64.standard_b64encode(
httpx2.get(pdf_url, follow_redirects=True).content
).decode("utf-8")
# Create a message with the cached document
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": pdf_data,
},
"cache_control": {"type": "ephemeral"},
},
{
"type": "text",
"text": "Which model has the highest human preference win rates across each use-case?",
},
],
}
],
)
print(message.content)
```
#### Process document batches
Use the [Message Batches API](build-with-claude-batch-processing.md) to process many PDFs in one request:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import base64
import httpx2
# First, load and encode the PDF
pdf_url = "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
pdf_data = base64.standard_b64encode(
httpx2.get(pdf_url, follow_redirects=True).content
).decode("utf-8")
# Create a batch of requests that use the document
client = anthropic.Anthropic()
message_batch = client.messages.batches.create(
requests=[
{
"custom_id": "my-first-request",
"params": {
"model": "claude-opus-5-5",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": pdf_data,
},
},
{
"type": "text",
"text": "Which model has the highest human preference win rates across each use-case?",
},
],
}
],
},
},
{
"custom_id": "my-second-request",
"params": {
"model": "claude-opus-5-5",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": pdf_data,
},
},
{
"type": "text",
"text": "Extract 5 key insights from this document.",
},
],
}
],
},
},
]
)
print(message_batch)
```
Batches process asynchronously. To check progress and retrieve results once processing ends, see [Batch processing](build-with-claude-batch-processing.md).
## Next steps
[Vision](build-with-claude-vision.md)
Claude's vision capabilities allow it to understand and analyze images, opening up exciting possibilities for multimodal interaction.
[Try PDF examples](https://platform.claude.com/cookbook/multimodal-getting-started-with-vision)
Explore practical examples of PDF processing in the Claude Cookbook recipe.
[View API reference](../Endpoints/messages-create.md)
See complete API documentation for PDF support.
## Compatibility
Supported platforms
- Claude API
- Claude Platform on AWS
- Amazon Bedrock
- Google Cloud
- Microsoft Foundry
---
## Preserved thinking - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/preserved-thinking
Path: 04-API-Reference/Guides/build-with-claude-preserved-thinking.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fpreserved-thinking)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
[Overview](build-with-claude-thinking.md)[Steering and cost control](build-with-claude-thinking-steering-and-cost.md)[Tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md)[Preserved thinking](build-with-claude-preserved-thinking.md)[Troubleshooting](build-with-claude-thinking-troubleshooting.md)[Extended thinking (legacy)](build-with-claude-extended-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Thinking
# Preserved thinking
Copy page
Preserved thinking lets a model use a thinking block from an earlier turn only if that model or an earlier one produced it and nothing before the block has changed.
Copy page
Preserved thinking is a property of newer Claude models that guards against distillation. It decides whether the model can use a thinking block that you send back from an earlier turn. Starting with Claude Fable 5.1, when a `thinking` or `redacted_thinking` block comes back in a request, the API checks the block's `signature` for two things:
- **The model can read the block.** Each model reads its own thinking blocks and those of a fixed set of other models. Claude Fable 5.1 reads blocks from Claude Opus 5 and, on the Claude API, from Claude Opus 5.5; neither Claude Opus 5 nor Claude Opus 5.5 reads blocks from Claude Fable 5.1. If the current model can't read a block, the API drops it from that request without an error. See [Switching models mid-conversation](#switching-models).
- **Nothing before the thinking block has changed.** The top-level `system` prompt, `tools`, and `messages` before the block are its prefix. If the prefix differs from what you sent when the block was produced, that block and every later thinking block are invalid, and the API rejects the request with a 400 error or drops the invalid blocks, whichever you choose. See [Keeping the prefix unchanged](#prefix-check).
The model check applies to every account. The API enforces the prefix check by default for accounts created on or after August 31, 2026, 00:00 UTC. On older accounts, it enforces the prefix check only on requests that set `thinking.block_binding.prefix_mismatch_behavior`. **Make your integration append-only regardless of your account's age**, so the same code works on every account, including newer accounts enforced by default.
## Who needs to change anything
Nothing changes for you if Claude Code, claude.ai, Claude Managed Agents, or the Claude Agent SDK builds your requests, or if your code keeps `system` and `tools` fixed for a session and only ever appends to `messages`. Claude Mythos 5.1 and models before Claude Fable 5.1 don't run the prefix check. If you never send thinking blocks back, the prefix check has nothing to reject, and the model gets none of its earlier reasoning.
Check your integration if, between two requests in one conversation, it does any of the following. Each item links to what to do instead:
- [Rebuilds the `system` prompt](#new-instructions): the date, a mode flag, re-read project instructions, or a plugin or MCP server that connects after the first turn
- [Re-renders the context in the first user message](#changing-context)
- [Clears or shortens old tool results, or re-encodes old images](#server-side-trimming)
- [Summarizes or drops old turns on the client](#custom-compaction-on-the-client) and keeps recent turns with their thinking
- [Adds, removes, or edits entries in `tools`](#tool-changes)
- [Adds a reminder to a user turn](#per-turn-reminders) and removes or rewrites it later
- [Drops some `thinking` blocks and keeps later ones](#append-assistant-turns-exactly-as-returned), or removes them and [later puts them back](#prefix-check)
- [Rebuilds a saved session from templates](#faq) instead of replaying what it sent
On an older account, none of these produces an error unless the request sets `prefix_mismatch_behavior`, so a run with no errors on your own key doesn't show whether your code is affected. If people run your tool with their own API keys, those on newer accounts get the 400 error before you do. To see what they see without changing how your requests behave, send the `thinking-binding-controls-2026-08-01` beta header. On an older account, each response then flags blocks that fail the check, and the model still reads them (see [Set the mismatch behavior and read `input_transformations`](#preserved-thinking-controls)).
## Switching models mid-conversation
Claude Fable 5.1 and Claude Mythos 5.1 read thinking blocks produced by each other and by earlier Claude models. No earlier model reads thinking blocks from Claude Fable 5.1 or Claude Mythos 5.1.
Claude Opus 5.5 reads thinking blocks from Claude Opus 5 and earlier Opus, Sonnet, and Haiku models, but not from Claude Fable or Claude Mythos models. On the Claude API, Claude Fable 5.1 and Claude Mythos 5.1 read thinking blocks from Claude Opus 5.5; no other model does. So a conversation that moves from Claude Opus 5 onto Claude Opus 5.5 keeps its reasoning, and so does one that moves from Claude Opus 5.5 up to Claude Fable 5.1 or Claude Mythos 5.1 on the Claude API. One that moves from Claude Fable 5.1 or Claude Mythos 5.1 to Claude Opus 5.5, or from Claude Opus 5.5 to any model other than those two, runs the turns after the switch without the previous model's reasoning. The blocks are dropped, not rejected, as described below.
- **A conversation that moves to Claude Fable 5.1 from an earlier model, or from Claude Opus 5.5 on the Claude API, keeps its reasoning.** The earlier model's thinking blocks stay readable, so the model thinks as usual from the first turn after the switch.
- **A conversation that moves down to an earlier model loses Claude Fable 5.1's reasoning for that request.** This happens when a router sends a turn to a cheaper model, after a [classifier refusal fallback](build-with-claude-refusals-and-fallback.md), or during a [server-side fallback](build-with-claude-refusals-and-fallback.md#server-side-fallback). The API removes the unreadable blocks before the prompt reaches the model. They aren't billed and don't count toward `input_tokens`.
Keep sending the full history on every request, thinking blocks included, and let the API drop what the current model can't read. The API never edits your `messages` array, so the dropped blocks stay in your history. When the same history goes back to Claude Fable 5.1, its blocks are readable again, along with the earlier model's thinking. The reasoning is lost for good only if your client removes the blocks itself, for example a harness that strips thinking on a model switch or rebuilds the history from what each model used.
With the `thinking-binding-controls-2026-08-01` [beta header](../Endpoints/beta-headers.md), the response lists each dropped block in a top-level `input_transformations` array with `reason: "model_binding_mismatch"`:
```python
{
"input_transformations": [
{
"type": "thinking_dropped",
"path": "messages.3.content.0",
"reason": "model_binding_mismatch"
}
]
}
```
Without the header, the drop is silent. This entry isn't a bug in your integration, and `prefix_mismatch_behavior` has no effect on it: a block the current model can't read is always dropped.
## Keeping the prefix unchanged
On Claude Fable 5.1 and Claude Opus 5.5, a thinking block stays valid only while everything you sent before it is unchanged on later requests. The checked prefix has three parts:
- The top-level `system` prompt
- The set of `tools`
- Every `message` before the block
Note: With server-side [compaction](build-with-claude-compaction.md), the checked prefix starts at the most recent compaction block.
Request parameters outside those three fields, such as `effort`, `max_tokens`, `output_config`, `tool_choice`, and `metadata`, aren't part of the prefix check, and neither are `cache_control` markers. [What counts as an edit](#what-counts-as-an-edit) has the full list.
Earlier thinking blocks aren't in the prefix, but each thinking block records which thinking block came before it, across turns. You can remove thinking blocks from the start of the history (oldest first), from the end, or all of them. What fails is a gap: the thinking blocks you keep must be an unbroken run of the original sequence, so removing one from the middle invalidates the thinking blocks after it. Once you remove a block, leave it out. Putting it back invalidates the thinking blocks produced while it was gone.
Keep `system` and `tools` fixed for the session and treat `messages` as append-only. The same discipline keeps the prefix stable for [prompt caching](build-with-claude-prompt-caching.md): the edits that invalidate thinking are the edits that restart the cache.
### What the API does with an invalid block
You choose with `thinking.block_binding.prefix_mismatch_behavior`:
- **`"error"` (the default):** the API rejects the request with a 400 `invalid_request_error` that names the first failing block.
- **`"drop_block"`:** the API drops each failing block and every thinking block after it, and the request succeeds. Dropped blocks aren't billed. The model answers that turn without using reasoning from dropped blocks, and the prompt cache restarts at the edit. The response lists each dropped block in `input_transformations` (on the `message_start` event when streaming) with `reason: "prefix_binding_mismatch"`.
`"drop_block"` hides the error but doesn't fix the edit that caused it. Dropped blocks aren't billed, but a session's token usage might still increase because Claude can sometimes think more to re-create the dropped thinking. The increase tends to be larger when more thinking blocks are dropped, or when blocks are dropped on more turns of a long session.
Count the responses in each session whose `input_transformations` has a `prefix_binding_mismatch` entry, alert on them, and replace each edit with the matching pattern in [Make changes without editing the prefix](#replace-prefix-edits). In the Message Batches API, an item that leaves the field unset doesn't fail. Where the API enforces the check by default, it drops the failing blocks instead. Set `"error"` explicitly there if you want batch items to fail.
Both the field and the `input_transformations` array require the `thinking-binding-controls-2026-08-01` [beta header](../Endpoints/beta-headers.md). [Set the mismatch behavior and read `input_transformations`](#preserved-thinking-controls) shows the request in each SDK.
The 400 message begins:
``` block
messages.1.content.0: Invalid `signature` in `thinking` block. The block is bound to a different conversation. Remove the block, or set `thinking.block_binding.prefix_mismatch_behavior` to "drop_block".
```
If the request didn't send the beta header, the message continues:
```python
That setting requires the `thinking-binding-controls-2026-08-01` value in the `anthropic-beta` header.
```
It usually ends with a sentence naming what changed, for example that the `system` prompt or the `tools` list differs from when the block was created. [Troubleshooting thinking](build-with-claude-thinking-troubleshooting.md#error-thinking-block-signature) describes what that sentence can name.
A tampered or undecryptable signature is a different failure. It always returns a 400 (`` Invalid `signature` in `thinking` block `` with no sentence about the conversation), and `prefix_mismatch_behavior` doesn't apply to it.
#### Handle the error in code
This is the 400 `invalid_request_error` shown earlier in this section. Don't resend the same body: it fails the same way every time. Retry once with the beta header and `prefix_mismatch_behavior: "drop_block"`, and store that choice with the session so every later request sends it too, including after a restart. If you can't send the beta header, remove every `thinking` and `redacted_thinking` block from the history once, leave them out, and continue. Then fix the edit that caused the mismatch.
### Set the mismatch behavior and read `input_transformations`
The `thinking-binding-controls-2026-08-01` [beta header](../Endpoints/beta-headers.md) adds:
- A top-level `input_transformations` array on every response
- A `block_binding` object on the `thinking` configuration, whose one field is `prefix_mismatch_behavior`
`block_binding` is accepted alongside `thinking.type: "adaptive"` and `thinking.type: "enabled"`. Sending it without the beta header returns a 400 error whose message ends `block_binding: Extra inputs are not permitted`. Models that don't run the prefix check accept the object and report only model-check drops, so one request body works across models. The API reference calls the prefix check the conversation check.
The following request opts into dropping rather than rejecting. On a first turn there's nothing to replay, so `input_transformations` comes back empty:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=16000,
thinking={
"type": "adaptive",
"block_binding": {"prefix_mismatch_behavior": "drop_block"},
},
messages=[
{
"role": "user",
"content": "What is the greatest common divisor of 1071 and 462?",
}
],
betas=["thinking-binding-controls-2026-08-01"],
)
for block in response.content:
if block.type == "text":
print(block.text)
print(f"Input transformations: {len(response.input_transformations or [])}")
```
Output
``` block
The greatest common divisor of 1071 and 462 is 21.
Input transformations: 0
```
Under the beta header, every response from a thinking-capable model carries `input_transformations`. Each entry names one thinking block by its `path` (for example `messages.1.content.0`) and gives a `reason`. There are two entry types:
- **`thinking_dropped`:** the API drops the block before the model reads it, and the block isn't billed. The `reason` is `prefix_binding_mismatch` or `model_binding_mismatch` (see [Switching models mid-conversation](#switching-models)).
- **`thinking_mismatch_allowed`:** the block fails the prefix check, but the API doesn't enforce that check for this request, so the block reaches the model unchanged and is billed. The `reason` is always `prefix_binding_mismatch`. This entry appears only on requests where the API doesn't enforce the check by default, such as those from an older account (see [When the API enforces the check](#enforcement)). Setting `prefix_mismatch_behavior` to either value opts the request into enforcement, so a request that sets it never gets this entry.
The array is empty when no block was dropped and none failed the prefix check. Ignore entries whose `type` or `reason` you don't recognize, because later checks add values.
When [streaming](build-with-claude-streaming.md), the array arrives on the `message` object in the `message_start` event. After a mid-stream server-side fallback, the final `message_delta` event carries it again with the serving model's entries. In a [message batch](build-with-claude-batch-processing.md), an item whose block fails the prefix check under an explicit `"error"` resolves as `errored`. An item that leaves the field unset doesn't fail. Where the API enforces the check by default, it drops the failing blocks instead. The [token counting](build-with-claude-token-counting.md) endpoint runs the same prefix check and returns the same 400.
### When the API enforces the check
The API enforces the prefix check on Claude Fable 5.1 and Claude Opus 5.5 for new accounts.
- **Accounts created on or after August 31, 2026, 00:00 UTC:** the API checks Claude Fable 5.1 and Claude Opus 5.5 requests and applies `"error"` unless you set `"drop_block"`. The same definition of a new account applies to the Claude API and to cloud platforms.
- **Older accounts:** the API enforces the check only on requests that set `prefix_mismatch_behavior`. Setting the field opts a request in, so you can see what a new account sees without creating one. On requests that leave it unset, the API still runs the check but lets failing blocks through to the model. With the beta header, the response lists each one in `input_transformations` as `thinking_mismatch_allowed`, so you can find prefix edits without changing what the model receives.
To find out which group your account is in, take a Claude Fable 5.1 conversation that contains a thinking block, change something before that block, and send it to Claude Fable 5.1 without the beta header or the `block_binding` field. A 400 response that names the header means your account is enforced by default. A 200 response means it isn't. To confirm, send the same request again with the beta header, still without `block_binding`: the response lists every thinking block after your edit in `input_transformations` as `thinking_mismatch_allowed`.
### What counts as an edit
Each row compares two consecutive requests:
| Change between requests | Later thinking blocks |
|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Append messages at the end | Valid |
| Add a tool with `defer_loading: true` that nothing has referenced yet | Valid |
| Remove `thinking` blocks from the start of the history, from the end, or all of them | Valid (the model loses that reasoning) |
| Change any request parameter outside `system`, `tools`, and `messages` (`effort`, `max_tokens`, `output_config`, `tool_choice`, `metadata`, `thinking.display`, and so on) | Valid |
| Add, move, or remove `cache_control` markers | Valid |
| A rotating signed URL that returns the same bytes | Valid |
| Server-side compaction or context editing removes or replaces content | Valid (the check compares what you sent, not the server's edited copy) |
| A cleared [turn-scoped system message](#per-turn-reminders) left in place | Valid |
| Edit, reorder, or delete any earlier `user`, `assistant`, or `system` message | Invalid, except when the signed block from [on-demand compaction](build-with-claude-compaction-on-demand.md) replaces the messages it summarizes, under the [conditions for kept thinking](build-with-claude-compaction-thinking-blocks.md#conditions-for-kept-thinking-to-stay-valid) |
| Re-render the context you put in the first user message with a changed value | Invalid for every thinking block |
| Clear or shorten an earlier `tool_result`, re-encode an earlier image, or change an earlier `tool_use` input | Invalid for every later thinking block |
| Add a text block to an earlier user turn, or remove one you added last time | Invalid |
| Change the top-level `system` string or blocks | Invalid |
| Add, remove, rename, or edit a tool in `tools` | Invalid |
| Remove a `thinking` block from the middle of the history and keep later ones | Invalid for every later thinking block |
| Put back a `thinking` block you removed on an earlier request | Invalid for thinking blocks produced while it was gone |
| An image or document URL that returns different bytes on the next request | Invalid |
| The same turn-scoped message deleted or reworded on a later request | Invalid |
### Check whether your code edits the prefix
First, diff what you send. Capture the request bodies your integration sends over a few normal turns, including a compaction or a tool change. For each pair of consecutive requests, compare `system`, `tools`, and the `messages` they share. They should be identical up to the newly appended turns.
Then confirm against the API. Add the `thinking-binding-controls-2026-08-01` beta header, set `prefix_mismatch_behavior` to `"drop_block"`, and run a normal multi-turn session through your integration on claude-fable-5-1. The following example runs two turns the way your integration should: `messages` only grows, each assistant turn goes back exactly as the API returned it, `thinking` blocks included, and `block_binding` is set on every request. After each turn it prints the number of `thinking` blocks in the response and the number of dropped blocks:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
user_turns = [
"How many positive integers below 500 have exactly 6 positive divisors?",
"How many of those are odd?",
]
# messages grows across turns: each assistant turn goes back exactly as returned
messages = []
for user_turn in user_turns:
messages.append({"role": "user", "content": user_turn})
response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=16000,
thinking={
"type": "adaptive",
"block_binding": {"prefix_mismatch_behavior": "drop_block"},
},
messages=messages,
betas=["thinking-binding-controls-2026-08-01"],
)
messages.append({"role": "assistant", "content": response.content})
thinking_blocks = sum(block.type == "thinking" for block in response.content)
dropped = len(response.input_transformations or [])
print(f"thinking blocks: {thinking_blocks}, dropped: {dropped}")
```
Output
``` block
thinking blocks: 1, dropped: 0
thinking blocks: 1, dropped: 0
```
Neither turn drops a block because nothing earlier changed. Check that the first response contains a `thinking` block. With adaptive thinking, some responses have none. If no response in the session has one, there is nothing to check and the dropped count is 0 whatever you change, so run the example again.
Log `input_transformations` on every turn of your own integration. When the API drops a block, the entry looks like the following:
```python
{
"input_transformations": [
{
"type": "thinking_dropped",
"path": "messages.1.content.0",
"reason": "prefix_binding_mismatch"
}
]
}
```
- **Empty on every turn of a session that contains `thinking` blocks:** your integration keeps the prefix intact.
- **`reason: "prefix_binding_mismatch"`:** something before the block at `path` changed since the previous request. Diff `system`, `tools`, and `messages` up to that turn to find it, or resend the request with `"error"`: the 400 usually ends with a sentence naming what changed. Then find the matching replacement in [Make changes without editing the prefix](#replace-prefix-edits).
- **`reason: "model_binding_mismatch"`:** the conversation moved to a model that can't read the earlier model's blocks. This isn't a prefix edit. See [Switching models mid-conversation](#switching-models).
To see a failure on purpose, send a third turn from the earlier example and add a `system` prompt to that request only, so that it differs from the first two requests, which had none. With `"drop_block"`, the dropped count is no longer 0: the response has one entry for each thinking block in the history, each with `reason: "prefix_binding_mismatch"`. With `"error"`, the request returns the 400 described in [What the API does with an invalid block](#mismatch-behavior), and its last sentence names the `system` prompt. In the cURL and CLI tabs, remove the `jq` filter to see the error body. If the count is still 0, there was nothing to check: confirm that the model is claude-fable-5-1, that the request sets `block_binding`, that the history you sent contains `thinking` blocks, and that the first two requests had no `system` prompt.
Two plain turns rarely show the problem. Run a session through each of the following, with `"error"` set so that a regression fails your CI:
- The first client-side compaction or trim
- A tool, plugin, or MCP server that connects after the first turn
- A mode or instruction change
- A long tool loop, if you add reminders or shorten old tool results
- A switch to another model and back
- A save, a restart, and a resume on a later date
On an older account, you can also watch production traffic without opting into enforcement: send the beta header, leave `block_binding` out, and log `input_transformations`. Sending the header alone doesn't change what the model receives. Every thinking block that comes after the content you edited fails the check and gets its own `thinking_mismatch_allowed` entry, with the same `path` and `reason` fields as a `thinking_dropped` entry. Blocks before the edit still pass. An edit to `system` or `tools` comes before every block, so it fails every thinking block in the request. One entry looks like this:
```python
{
"input_transformations": [
{
"type": "thinking_mismatch_allowed",
"path": "messages.1.content.0",
"reason": "prefix_binding_mismatch"
}
]
}
```
Run the following example from an [older account](#enforcement), because a newer account rejects its third request with the 400. It sends the header without `block_binding` and extends the earlier session with a third request that adds a system prompt, which changes the prefix on purpose. After each turn it prints the number of `thinking` blocks and flagged blocks:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
user_turns = [
"How many positive integers below 500 have exactly 6 positive divisors?",
"How many of those are odd?",
"And how many of the odd ones are below 100?",
]
# messages grows across turns: each assistant turn goes back exactly as returned
messages = []
for turn, user_turn in enumerate(user_turns, start=1):
messages.append({"role": "user", "content": user_turn})
response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=16000,
thinking={"type": "adaptive"},
# Only the last request adds a system prompt, which changes the prefix on purpose
system="Answer briefly." if turn == len(user_turns) else anthropic.omit,
messages=messages,
betas=["thinking-binding-controls-2026-08-01"],
)
messages.append({"role": "assistant", "content": response.content})
thinking_blocks = sum(block.type == "thinking" for block in response.content)
flagged = sum(
transformation.type == "thinking_mismatch_allowed"
for transformation in response.input_transformations or []
)
print(f"thinking blocks: {thinking_blocks}, flagged: {flagged}")
```
Output
``` block
thinking blocks: 1, flagged: 0
thinking blocks: 1, flagged: 0
thinking blocks: 1, flagged: 2
```
The third response flags every thinking block from the earlier turns, one per turn in this run, because the new system prompt comes before all of them. The model still read them.
Handle these entries as you would `prefix_binding_mismatch` drops. The edit is before the first block listed: diff `system`, `tools`, and `messages` up to that block's `path` against the previous request to find it, then replace it with the matching pattern in [Make changes without editing the prefix](#replace-prefix-edits). On a new account, or on any request that sets `prefix_mismatch_behavior`, the API instead rejects the request or drops the failing blocks. The entries are a lower bound on what enforcement would remove: with `"drop_block"`, a failing block also takes the rest of that turn's thinking blocks with it, and removing one block can make the next one fail too. When the API only records the check, it judges each block on its own and lists a block only if that block fails.
## Make changes without editing the prefix
Each common prefix edit has a replacement that gives the model the same information and leaves earlier bytes unchanged, so later thinking stays valid. Find the edit your code makes today in the first column:
| Instead of | Use | Beta header |
|:----------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Rebuilding the top-level `system` prompt | A [mid-conversation system message](#new-instructions) | None |
| Re-rendering the context in your first user message (environment, date, memory, project instructions) on each request | Render it once and resend it unchanged. When something changes, [put the new version in the newest turn](#changing-context) | None |
| Clearing or shortening old `tool_result` content, or re-encoding old images, in place | Shorten a tool result or downscale an image before the first time you send it, not after. To clear old results later, [trim context on the server](#server-side-trimming) with `clear_tool_uses_20250919` | `context-management-2025-06-27` |
| Injecting a reminder and deleting it on the next request | A [turn-scoped system message](#per-turn-reminders) (`clear_at: "next_user_message"`) | `mid-conversation-system-clear-at-2026-08-21` |
| Adding or removing entries in `tools` | [`tool_addition` and `tool_removal` blocks](#tool-changes) | `inline-tools-2026-09-15` (add `mcp-client-2026-09-15` when the tool comes from an MCP server connected through the MCP connector), or the older `mid-conversation-tool-changes-2026-07-01`, which works on the Claude API, Amazon Bedrock, and Google Cloud |
| Changing top-level `output_config.effort` (restarts the cache, doesn't affect thinking) | A [per-message `output_config`](#effort-changes) | `mid-conversation-output-config-2026-07-01` |
| Dropping or summarizing old turns on the client | [On-demand compaction](build-with-claude-compaction-on-demand.md) to keep the recent turns with their thinking, other server-side [compaction or context editing](#server-side-trimming), or [client-side compaction](#custom-compaction-on-the-client) that keeps no stale thinking | `compact-2026-09-04` |
| An image or document URL whose bytes change between requests | A [`file_id` from the Files API](#files-by-id), or base64 | None |
All of these assume you [send assistant turns back exactly as returned](#append-assistant-turns-exactly-as-returned). Mid-conversation system messages, turn-scoped system messages, and tool changes aren't available on every model: [Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md) lists the models that accept them. If your code serves several models, keep editing the top-level `system` prompt for the models that don't accept them.
To use several betas in one request, combine the values in one `anthropic-beta` header. Beta names are the same on Amazon Bedrock and Google Cloud wherever the beta is available there (see [Beta headers](../Endpoints/beta-headers.md)):
``` block
anthropic-beta: thinking-binding-controls-2026-08-01,mid-conversation-system-clear-at-2026-08-21,inline-tools-2026-09-15
```
### Send assistant turns back exactly as returned
Store the `content` array from each response and send it back unchanged as the assistant turn: every block type, in the order received, including `thinking` blocks whose `thinking` field is empty. A serializer that drops unknown block types, drops empty fields, or reorders blocks edits the prefix for every later turn.
On Claude Fable 5.1, the `thinking` field is empty by default and the `signature` carries the reasoning, so a serializer that skips empty blocks removes thinking. If it removes all of them, nothing fails and the model loses its earlier reasoning on every turn. If you parse the stream yourself, keep the block even when no thinking text arrives: it opens, receives its `signature` in a `signature_delta` event, and closes. A block sent back with an empty `signature` fails.
### Add instructions with a mid-conversation system message
Some harnesses rebuild the top-level `system` prompt on each request to carry the current time, a token budget, a mode flag, or newly discovered project context. That invalidates every thinking block in the conversation. Instead, freeze `system` at session start. When something changes, append a [`role: "system"` message](build-with-claude-mid-conversation-system-messages.md) at the point in `messages` where the change becomes true:
```python
{
"role": "system",
"content": "The user switched the workspace to read-only mode. Do not write files until told otherwise."
}
```
The model treats this message with system-prompt authority, and everything before it stays unchanged. In a tool loop, place the message after the `tool_result` user message, never between an assistant `tool_use` and its `tool_result` (see [Limitations](build-with-claude-mid-conversation-system-messages.md#limitations)). Once sent, the message is part of the prefix for later thinking: leave it in place on later requests.
### Put changing context in the newest turn
Some harnesses put an environment block in the first user message (working directory, branch, date, memory, project instructions) and render it again on every request. When any value changes, `messages[0]` changes, and every thinking block in the conversation is invalid. Render that block once and resend it as it was. When a value changes, say so in the newest turn: add a text block to the user message you are about to send, or append a [mid-conversation system message](#new-instructions) if the change comes from you as the operator.
```python
{
"role": "user",
"content": [
{
"type": "text",
"text": "Environment update: the current branch is now release-2."
},
{ "type": "text", "text": "Run the tests again." }
]
}
```
Once sent, that text block is part of the prefix for later thinking: leave it in place on later requests.
### Send per-turn reminders as turn-scoped system messages
A common prefix edit is the per-turn nudge: a line such as "request independent reads together" or "you haven't updated the user in a while" that your code appends after each batch of tool results. To keep reminders from piling up, send each nudge as a [mid-conversation system message](build-with-claude-mid-conversation-system-messages.md) with `clear_at: "next_user_message"`, placed after the `tool_result` user message. `clear_at` requires the beta header `mid-conversation-system-clear-at-2026-08-21`. The following `messages` array is the request after two tool calls and their results. `messages[3]` is the previous request's nudge, left in place, and `messages[6]` is this request's copy:
```python
[
{ "role": "user", "content": "Fix the failing test." },
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "", "signature": "..." },
{
"type": "tool_use",
"id": "toolu_01",
"name": "read_file",
"input": { "path": "tests/test_auth.py" }
}
]
},
{
"role": "user",
"content": [{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "..." }]
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "Request every independent read in one turn."
},
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "", "signature": "..." },
{
"type": "tool_use",
"id": "toolu_02",
"name": "read_file",
"input": { "path": "src/auth.py" }
}
]
},
{
"role": "user",
"content": [{ "type": "tool_result", "tool_use_id": "toolu_02", "content": "..." }]
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "Request every independent read in one turn."
}
]
```
A user message that contains only `tool_result` blocks counts as the "next user message", so `messages[3]` is already cleared. It adds nothing to what the model sees and costs no input tokens, but because it's still in the array, the thinking in `messages[4]` stays valid. `messages[6]` is the copy the model sees this turn. On later requests, keep both where they are and append a fresh copy after the next `tool_result` message.
### Add or remove tools with `tool_addition` and `tool_removal`
Editing the `tools` array mid-session invalidates preserved thinking blocks. Leave the array as you first sent it, and change which tools the model can use by appending a `role: "system"` message that carries `tool_addition` or `tool_removal` blocks. These are [mid-conversation tool changes](build-with-claude-mid-conversation-system-messages.md#mid-conversation-tool-changes) and need the beta header `inline-tools-2026-09-15`, which is available on the Claude API. The older `mid-conversation-tool-changes-2026-07-01` header still works for changes that name a tool by reference, on the Claude API, Amazon Bedrock, and Google Cloud.
You have two ways to use these blocks:
- **Declare every tool up front.** Put every tool the session might need in `tools` on the first request, with `defer_loading: true` on any the model shouldn't see yet. Then turn tools on and off with `tool_addition` and `tool_removal` blocks that name them.
- **Start with a snapshot and add tools as you go.** Put the tools you know about in `tools` on the first request. When a new tool comes along, define it inside a `tool_addition` block instead of editing `tools`.
Either way, `tools` never changes, so earlier thinking stays valid and the prompt cache still hits, with the one exception noted below.
For example, to withdraw a dangerous tool after a mode switch:
```python
{
"role": "system",
"content": [
{ "type": "tool_removal", "tool": { "type": "tool_reference", "name": "delete_branch" } },
{ "type": "text", "text": "Branch deletion is disabled for the rest of this session." }
]
}
```
To turn on a tool you declared with `defer_loading: true`, append a `tool_addition` block that names it:
```python
{
"role": "system",
"content": [
{ "type": "tool_addition", "tool": { "type": "tool_reference", "name": "deploy" } },
{ "type": "text", "text": "Authentication succeeded. Deployment is now available." }
]
}
```
Sometimes you can't declare a tool up front because you don't know its schema yet: a tool your application discovers at runtime, or an MCP server that connects after the first turn. Define it inside the `tool_addition` block instead of touching `tools`. With `inline-tools-2026-09-15`, the block's `tool` can be `{"type": "tool_definition", "definition": {...}}`, carrying the same entry you would have put in `tools`:
```python
{
"role": "system",
"content": [
{
"type": "tool_addition",
"tool": {
"type": "tool_definition",
"definition": {
"name": "db_query",
"description": "Run a read-only SQL query against the analytics database.",
"input_schema": {
"type": "object",
"properties": { "sql": { "type": "string" } },
"required": ["sql"]
}
}
}
}
]
}
```
The new tool arrives in `messages`, `tools` never changes, and earlier thinking stays valid. Keep at least one tool without `defer_loading: true` in `tools`: if every tool there is deferred, the first tool you define this way costs one full prompt cache miss.
If the API connects to the MCP server for you through the [MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md), also send `mcp-client-2026-09-15`. It covers everything `mcp-client-2025-11-20` does, so send it instead of that one. The block's `definition` can then be an `mcp_toolset` for a server listed in `mcp_servers`. When the API has to fetch a server's tool list, the response starts with an `mcp_tool_listing` block for that server. Send it back unchanged with the rest of the assistant turn, and keep sending `mcp-client-2026-09-15` on every later request that carries it. The block pins the toolset to that list, so the API doesn't contact the server again for it. These MCP connector features are available on the Claude API.
With only the older header, you can still append a tool you learn about mid-session to `tools` with `defer_loading: true`, then offer it with a `tool_addition` block. That's safe because the prefix check ignores a deferred tool until a `tool_addition` block references it. Adding a tool without `defer_loading: true` changes the prefix and invalidates earlier thinking.
The `role: "system"` messages that carry these blocks join the prefix for later thinking. Leave them in place on later requests.
### Change effort with a per-message `output_config`
Changing top-level `output_config.effort` between requests doesn't invalidate thinking, because effort isn't part of the prefix. Changing top-level effort does restart the prompt cache. On Claude Fable 5.1, use [per-message effort](build-with-claude-effort.md#change-effort-mid-conversation-beta) instead: append a `role: "system"` message with empty `content` and the new level. It needs the beta header `mid-conversation-output-config-2026-07-01`.
```python
{ "role": "system", "content": [], "output_config": { "effort": "low" } }
```
The new level takes effect from the next `user` turn. Once sent, the message is part of `messages` and therefore part of the prefix for later thinking: leave it in place on later requests, and append another one to change effort again.
### Trim context on the server
Another common prefix edit is client-side trimming: dropping or summarizing the oldest turns and keeping the recent ones verbatim. The kept turns' thinking blocks were produced while the removed history was still in place, so they fail the check. The server-side equivalents don't count as edits, because the check compares the conversation as you sent it:
- [On-demand compaction](build-with-claude-compaction-on-demand.md) (beta) returns the summary from a separate request, which can [run in the background](build-with-claude-compaction-background.md), and you send the returned block in place of the messages it summarizes. The check accepts that swap, so the turns you keep can stay valid with their thinking, under the [conditions for kept thinking](build-with-claude-compaction-thinking-blocks.md#conditions-for-kept-thinking-to-stay-valid). [Request a summary](build-with-claude-compaction-on-demand.md#request-a-summary) shows the request and names the beta header it needs.
- [Compaction at a token threshold](build-with-claude-compaction-threshold.md) summarizes older turns into a compaction block when the context approaches a threshold you set, and the checked prefix restarts from that block. Its [`instructions` parameter](build-with-claude-compaction-threshold.md#custom-summarization-instructions) takes your own summarization prompt, such as "preserve every ticker, position size, and stated assumption".
- [Context editing](build-with-claude-context-editing.md) clears old tool results or old thinking blocks by rule, oldest first. The strategies are `clear_tool_uses_20250919` and `clear_thinking_20251015`.
### Compact on the client
You can still compact on the client. If you write the summary yourself, don't send back a thinking block that was produced before the rewrite. If the API writes it with on-demand compaction, [Conditions for kept thinking to stay valid](build-with-claude-compaction-thinking-blocks.md#conditions-for-kept-thinking-to-stay-valid) lists when kept thinking stays valid.
#### Simple compaction (recommended)
When the conversation grows too long, summarize the whole session into one user message and send only that message plus the next instruction. Nothing earlier is replayed, so there's no thinking left to fail the check, and the model reasons afresh from the summary.
```python
[
{
"role": "user",
"content": "<summary of the session so far>\n\n<the next instruction>"
}
]
```
Claude models are trained on long-horizon tasks with this scheme and for most workloads it performs well.
#### Keep-tail compaction
Keep-tail compaction summarizes the older turns and keeps the most recent turns verbatim, so the model still sees the last few exchanges word for word. If you write the summary yourself, it breaks the rule: the kept assistant turns still carry thinking blocks that were produced when the original turns, not the summary, came before them. Those blocks fail.
To keep that thinking, have the API write the summary with on-demand compaction. [Compaction that keeps recent turns](build-with-claude-compaction-keep-recent-turns.md) shows how, and [Conditions for kept thinking to stay valid](build-with-claude-compaction-thinking-blocks.md#conditions-for-kept-thinking-to-stay-valid) lists when the kept thinking stays valid.
The rest of this section covers a summary you write yourself.
Fix: keep the turns exactly as they are and send `prefix_mismatch_behavior: "drop_block"`. The API drops the stale thinking blocks, the model reads the kept turns' `text` and `tool_use` blocks, and the request succeeds.
Pass the compacted history as `messages` and set `block_binding` on the `thinking` configuration. In the following example, `compacted_messages` is the array your compaction step produced: the summary message followed by the kept turns exactly as the API returned them, `thinking` blocks included:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# compacted_messages: the summary message, then the kept turns as returned
response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=16000,
thinking={
"type": "adaptive",
"block_binding": {"prefix_mismatch_behavior": "drop_block"},
},
messages=compacted_messages,
betas=["thinking-binding-controls-2026-08-01"],
)
print(response.input_transformations)
```
The response carries the new assistant turn as usual, plus one `input_transformations` entry per dropped block. For the history in the diagram, that's the thinking on assistant turns 3 and 4:
```python
{
"input_transformations": [
{
"type": "thinking_dropped",
"path": "messages.2.content.0",
"reason": "prefix_binding_mismatch"
},
{
"type": "thinking_dropped",
"path": "messages.4.content.0",
"reason": "prefix_binding_mismatch"
}
]
}
```
Keep sending `"drop_block"` on later requests for as long as those two turns stay in the history. Thinking the model produces from this request onward follows the summary and stays valid. If you'd rather not depend on the beta header, the alternative is to strip the `thinking` and `redacted_thinking` blocks from the kept assistant turns yourself when you build the compacted history.
#### Background (async) compaction
Background compaction builds the summary off the critical path while the conversation continues, then swaps it in a few requests later. To keep the thinking produced in the meantime, have the API write the summary with on-demand compaction: [Compaction in the background](build-with-claude-compaction-background.md) has the steps, and that thinking stays valid under the same [conditions for kept thinking](build-with-claude-compaction-thinking-blocks.md#conditions-for-kept-thinking-to-stay-valid) as kept recent turns.
A summary you build yourself breaks the rule the same way keep-tail does, with a delay: every assistant turn produced while the summary was being built carries thinking that predates the swap, and it all fails the moment the summary lands. If you use one, treat the swap like keep-tail and send `"drop_block"` from the swap onward, or compact synchronously.
#### Patterns that don't work with preserved thinking
- **Cutting turns out of the middle.** Removing individual turns invalidates every thinking block after them, and no compaction scheme avoids that. If you were cutting a turn to change an instruction, append a [mid-conversation system message](#new-instructions) instead. To remove old tool results or old thinking selectively, use server-side [context editing](build-with-claude-context-editing.md).
- **Compacting in the middle of a tool round.** Don't compact between an assistant turn's `tool_use` and the `tool_result` that answers it. Send that assistant turn back with its thinking intact so the model finishes the round with its reasoning. See [Preserving thinking blocks](build-with-claude-thinking.md#preserving-thinking-blocks).
### Reference files by ID, not by a URL whose content changes
For an `image` or `document` block with a `url` source, the check covers the fetched bytes, not the URL string. A URL whose content changes invalidates later thinking: a "latest screenshot" endpoint, or a document someone edits between turns. A rotating signed URL for the same file doesn't. For content you reference across turns, upload it once with the [Files API](build-with-claude-files.md) and use the `file_id`, or send base64.
### Libraries, proxies, and gateways
A library, proxy, or gateway sits between someone else's history and the API, so its own rewrites count as edits, and its users can't see or fix them.
- **Pass through what you don't recognize.** Forward the caller's `anthropic-beta` values and `thinking.block_binding` unchanged, and return `input_transformations` to them. An options schema that rejects unknown keys stops your users from choosing `"drop_block"`.
- **Leave a `role: "system"` message where the caller put it.** Moving it into the top-level `system` field changes `system` on that request and invalidates every thinking block in the conversation.
- **To turn tool use off for a request, send `tool_choice: {"type": "none"}`.** Don't remove `tools`.
- **Don't hide the 400.** If your code catches it, strips thinking, and retries on the caller's behalf, log that it did: their history is still edited, and the model loses its earlier reasoning on every later request.
## FAQ
### Do I need a new account to test preserved thinking?
No. Send the `thinking-binding-controls-2026-08-01` beta header and set `thinking.block_binding.prefix_mismatch_behavior`. Setting the field opts that request into enforcement regardless of account age. `"error"` rejects an edited history with the same 400 a new account gets, and `"drop_block"` lets the request through and lists what was dropped in `input_transformations`. To find prefix edits from an older account without enforcing the check, send the header and leave the field unset: failing blocks still reach the model, and `input_transformations` lists them as `thinking_mismatch_allowed`. See [Check whether your code edits the prefix](#how-to-tell-whether-your-integration-is-impacted).
### If anything before a thinking block changes, even one tool description, is the conversation unusable?
No. What fails is the thinking already in the history after the point you changed, and you choose what happens to it. With `prefix_mismatch_behavior: "drop_block"`, the API drops those blocks and the request succeeds: the model answers that turn without that reasoning, and the prompt cache restarts at the edit. With the default `"error"`, the API rejects the request with a 400 until you undo the edit or resend with `"drop_block"`. See [What the API does with an invalid block](#mismatch-behavior). [What counts as an edit](#what-counts-as-an-edit) lists which changes matter.
### Does changing effort or other thinking settings between requests invalidate earlier thinking?
No. `output_config.effort`, `max_tokens`, and the `thinking` configuration aren't part of the checked prefix, which covers only `system`, `tools`, and `messages`. A top-level effort change invalidates most of the prompt cache. On Claude Fable 5.1, a [per-message effort](#effort-changes) change keeps the prompt cache and is used as the new effort level until changed again.
### My tool list changes mid-session. How do I avoid invalidating the conversation?
Don't edit `tools`. Declare the full set at session start, mark tools that aren't available yet with `defer_loading: true`, and offer or withdraw them with `tool_addition` and `tool_removal` blocks. If you learn a tool's schema only mid-session, define it inside the `tool_addition` block (`inline-tools-2026-09-15`, plus `mcp-client-2026-09-15` for a server the API's MCP connector reaches) and leave `tools` unchanged. The `role: "system"` messages that carry these blocks join the prefix for later thinking, so don't move, reword, or delete them afterward. See [Add or remove tools with `tool_addition` and `tool_removal`](#tool-changes).
### I compact by summarizing older turns and keeping recent turns verbatim. Does that still work?
Yes, if the API writes the summary. [On-demand compaction](build-with-claude-compaction-on-demand.md) (beta header `compact-2026-09-04`) summarizes the older turns into a signed block that you send in place of them. The recent turns keep their thinking under the [conditions for kept thinking](build-with-claude-compaction-thinking-blocks.md#conditions-for-kept-thinking-to-stay-valid).
If you write the summary yourself, the kept turns' thinking fails the check, because those blocks were produced against the history you replaced. Strip `thinking` and `redacted_thinking` blocks from the turns you carry across and keep their `text` and `tool_use` blocks, or send `prefix_mismatch_behavior: "drop_block"` and let the API drop them. Simple compaction leaves no thinking behind to fail and is the recommended approach: one summary message plus the next user turn, with no earlier turns replayed. Server-side [compaction](build-with-claude-compaction.md) and [context editing](build-with-claude-context-editing.md) don't count as edits. See [Compact on the client](#custom-compaction-on-the-client).
### How do I handle instruction files such as AGENTS.md or CLAUDE.md that change mid-session?
Load them once at session start and keep the top-level `system` prompt and `tools` fixed. When a file changes, append the new version at that point in `messages` instead of editing the original. Use a [mid-conversation system message](build-with-claude-mid-conversation-system-messages.md) for instructions that come from you as the operator. For file text you treat as untrusted, which shouldn't carry system-prompt authority, put the content in the next `user` turn instead. See [Add instructions with a mid-conversation system message](#new-instructions) and [Limitations](build-with-claude-mid-conversation-system-messages.md#limitations).
### Can I resume a saved session later, after a restart or the next day?
Yes. A resumed session is an ordinary follow-up request: `system`, `tools`, and the earlier `messages` must have the same content as what you last sent. JSON formatting and key order don't matter; the values do. Persist exactly what you sent and received, and replay that: the rendered system prompt, the tool definitions, and each assistant turn as returned. Don't re-render from inputs that might have changed since, such as the date, an updated instruction file, or a new tool version. Anything new goes in an appended message. See [Send assistant turns back exactly as returned](#append-assistant-turns-exactly-as-returned).
### A saved session now fails on every request. How do I get it working again?
The stored history has an edit in it, so replaying it can't succeed. Send that session with `prefix_mismatch_behavior: "drop_block"` from now on, or remove its `thinking` and `redacted_thinking` blocks once and continue. Thinking the model produces from that point on stays valid as long as nothing before it changes again. Then find the edit so that new sessions don't hit it. See [Handle the error in code](#handle-the-error-in-code).
### My harness can route a turn to a non-Claude model. Do those turns invalidate Claude's earlier thinking?
No, provided they're appended after the existing history and nothing earlier changes: an assistant message without thinking blocks is an appended message like any other. Send the other model's output as `text` and `tool_use` content.
### Can I carry a conversation's reasoning into a new conversation?
Not into a different conversation. A thinking block is usable only when it follows the exact `system`, `tools`, and `messages` it was produced from. A branch that replays that history unchanged up to the fork point keeps its thinking. A conversation that starts from anything else can't use it, so start that conversation from a summary of the task state, as in [simple compaction](#custom-compaction-on-the-client): the goal, decisions made, files and results so far, and the next step.
## Next steps
[Troubleshooting thinking](build-with-claude-thinking-troubleshooting.md)
Diagnose and fix the most common thinking failures: configuration 400 errors, empty or missing thinking blocks, max_tokens stops, and cache misses.
[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)
Change system instructions or tool availability partway through a conversation without invalidating the cached prefix that came before them.
[Compaction](build-with-claude-compaction.md)
Server-side context compaction for managing long conversations that approach context window limits.
[Prompt caching](build-with-claude-prompt-caching.md)
Cache prompt prefixes with `cache_control` to cut costs and latency, using automatic caching or explicit breakpoints with 5-minute or 1-hour TTLs.
---
## Prompt caching - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/prompt-caching
Path: 04-API-Reference/Guides/build-with-claude-prompt-caching.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fprompt-caching)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Context management
# Prompt caching
Copy page
Cache prompt prefixes with `cache_control` to cut costs and latency, using automatic caching or explicit breakpoints with 5-minute or 1-hour TTLs.
Copy page
Prompt caching optimizes your API usage by allowing resuming from specific prefixes in your prompts. This significantly reduces processing time and costs for repetitive tasks or prompts with consistent elements.
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
There are two ways to enable prompt caching:
- **[Automatic caching](#automatic-caching)**: Add a single `cache_control` field at the top level of your request. The system automatically applies the cache breakpoint to the last cacheable block and moves it forward as conversations grow. Best for multi-turn conversations where the growing message history should be cached automatically.
- **[Explicit cache breakpoints](#explicit-cache-breakpoints)**: Place `cache_control` directly on individual content blocks for fine-grained control over exactly what gets cached.
The simplest way to start is with automatic caching:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system="You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.",
messages=[
{
"role": "user",
"content": "Analyze the major themes in 'Pride and Prejudice'.",
}
],
)
print(response.usage.model_dump_json())
```
With automatic caching, the system caches all content up to and including the last cacheable block. On subsequent requests with the same prefix, cached content is reused automatically.
------------------------------------------------------------------------
## How prompt caching works
When you send a request with prompt caching enabled:
1. The system checks if a prompt prefix, up to a specified cache breakpoint, is already cached from a recent query.
2. If found, it uses the cached version, reducing processing time and costs.
3. Otherwise, it processes the full prompt and caches the prefix once the response begins.
This is especially useful for:
- Prompts with many examples
- Large amounts of context or background information
- Repetitive tasks with consistent instructions
- Long multi-turn conversations
By default, the cache has a 5-minute lifetime. The cache is refreshed for no additional cost each time the cached content is used.
The lifetime is measured from the start of the request that writes or reads the cache entry, not from the end of its response. Time spent generating a response counts against the lifetime: if a response takes 4 minutes to stream, a follow-up request that reuses the same cached prefix must start within about 1 minute of that response completing.
If you find that 5 minutes is too short, Anthropic also offers a 1-hour cache duration [at additional cost](#pricing).
For more information, see [1-hour cache duration](#1-hour-cache-duration).
**Prompt caching caches the full prefix**
Prompt caching references the entire prompt: `tools`, `system`, and `messages` (in that order), up to and including the block designated with `cache_control`.
------------------------------------------------------------------------
## Pricing
Prompt caching introduces a new pricing structure. The following table shows the price per million tokens for each supported model:
[TABLE]
*^(1 Cache hits and refreshes on Claude Fable 5.1 and Claude Mythos 5.1 are priced at 0.025x the base input price.)*
*^(2 Cache hits and refreshes on Claude Opus 5.5 are priced at 0.05x the base input price.)*
*^(All other models use the standard 0.1x multiplier.)*
The previous table reflects the following pricing multipliers for prompt caching:
- 5-minute cache write tokens are 1.25 times the base input tokens price
- 1-hour cache write tokens are 2 times the base input tokens price
- Cache read tokens are 0.1 times the base input tokens price (see the table footnote for per-model exceptions)
These multipliers stack with other pricing modifiers such as the Batch API discount and data residency. See [pricing](../../17-Billing-Plans/about-claude-pricing.md) for full details.
------------------------------------------------------------------------
## Supported models
Prompt caching (both automatic and explicit) is supported on all [active Claude models](../../20-Models/about-claude-models-overview.md).
------------------------------------------------------------------------
## Automatic caching
Automatic caching is the simplest way to enable prompt caching. Instead of placing `cache_control` on individual content blocks, add a single `cache_control` field at the top level of your request body. The system automatically applies the cache breakpoint to the last cacheable block.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system="You are a helpful assistant that remembers our conversation.",
messages=[
{"role": "user", "content": "My name is Alex. I work on machine learning."},
{
"role": "assistant",
"content": "Nice to meet you, Alex! How can I help with your ML work today?",
},
{"role": "user", "content": "What did I say I work on?"},
],
)
print(response.usage.model_dump_json())
```
### How automatic caching works in multi-turn conversations
With automatic caching, the cache point moves forward automatically as conversations grow. Each new request caches everything up to the last cacheable block, and previous content is read from cache.
[TABLE]
The cache breakpoint automatically moves to the last cacheable block in each request, so you don't need to update any `cache_control` markers as the conversation grows.
### TTL support
By default, automatic caching uses a 5-minute TTL. You can specify a 1-hour TTL at 2x the base input token price:
```python
{ "cache_control": { "type": "ephemeral", "ttl": "1h" } }
```
### Combining with block-level caching
Automatic caching is compatible with [explicit cache breakpoints](#explicit-cache-breakpoints). When used together, the automatic cache breakpoint uses one of the 4 available breakpoint slots.
This lets you combine both approaches. For example, use an explicit breakpoint to cache your system prompt, while automatic caching handles the conversation:
```python
{
"model": "claude-opus-5-5",
"max_tokens": 1024,
"cache_control": { "type": "ephemeral" },
"system": [
{
"type": "text",
"text": "You are a helpful assistant.",
"cache_control": { "type": "ephemeral" }
}
],
"messages": [{ "role": "user", "content": "What are the key terms?" }]
}
```
### What stays the same
Automatic caching uses the same underlying caching infrastructure. Pricing, minimum token thresholds, context ordering requirements, and the 20-block lookback window all apply the same as with explicit breakpoints.
### Edge cases
- If the last block already has an explicit `cache_control` with the same TTL, automatic caching is a no-op.
- If the last block has an explicit `cache_control` with a different TTL, the API returns a 400 error.
- If 4 explicit block-level breakpoints already exist, the API returns a 400 error (no slots left for automatic caching).
- If the last block is not eligible as an automatic cache breakpoint target, the system silently walks backward to find the nearest eligible block. If none is found, caching is skipped.
Automatic caching is available on every platform except the legacy [Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md) integration. On that integration, the API returns a 400 error for a top-level `cache_control` field, so use [explicit cache breakpoints](#explicit-cache-breakpoints) instead.
------------------------------------------------------------------------
## Explicit cache breakpoints
For more control over caching, you can place `cache_control` directly on individual content blocks. This is useful when you need to cache different sections that change at different frequencies, or need fine-grained control over exactly what gets cached.
### Structuring your prompt
Place static content (tool definitions, system instructions, context, examples) at the beginning of your prompt. Mark the end of the reusable content for caching using the `cache_control` parameter.
Cache prefixes are created in the following order: `tools`, `system`, then `messages`. This order forms a hierarchy where each level builds upon the previous ones.
#### How automatic prefix checking works
You can use just one cache breakpoint at the end of your static content, and the system will automatically find the longest prefix that a prior request already wrote to the cache. Understanding how this works helps you optimize your caching strategy.
**Three core principles:**
1. **Cache writes happen only at your breakpoint.** Marking a block with `cache_control` writes exactly one cache entry: a hash of the prefix ending at that block. The system does not write entries for any earlier position. Because the hash is cumulative, covering everything up to and including the breakpoint, changing any block at or before the breakpoint produces a different hash on the next request.
2. **Cache reads look backward for entries that prior requests wrote.** On each request the system computes the prefix hash at your breakpoint and checks for a matching cache entry. If none exists, it walks backward one block at a time, checking whether the prefix hash at each earlier position matches something already in the cache. It is looking for prior writes, not for stable content.
3. **The lookback window is 20 blocks.** The system checks at most 20 positions per breakpoint, counting the breakpoint itself as the first. If the system finds no matching entry in that window, checking stops (or resumes from the next explicit breakpoint, if any). On the Claude API, a run of consecutive `tool_use` blocks counts as one position, and so does a run of consecutive `tool_result` blocks, so a turn with many parallel tool calls doesn't push the previous request's entry out of the window on its own.
**Example: Lookback in a growing conversation**
You append new blocks each turn and set `cache_control` on the final block of each request:
- **Turn 1:** 10 blocks, breakpoint on block 10. No prior cache entries exist. The system writes an entry at block 10.
- **Turn 2:** 15 blocks, breakpoint on block 15. Block 15 has no entry, so the system walks back to block 10 and finds the turn-1 entry. Cache hit at block 10; the system processes only blocks 11 through 15 fresh and writes a new entry at block 15.
- **Turn 3:** 35 blocks, breakpoint on block 35. The system checks 20 positions (blocks 35 through 16) and finds nothing. The turn-2 entry at block 15 is one position outside the window, so there is no cache hit. Adding a second breakpoint at block 15 starts a second lookback window there, which finds the turn-2 entry.
**Common mistake: Breakpoint on content that changes every request**
Your prompt has a large static system context (blocks 1 through 5) followed by a per-request block containing a timestamp and the user message (block 6). You set `cache_control` on block 6:
- **Request 1:** Cache write at block 6. The hash includes the timestamp.
- **Request 2:** The timestamp differs, so the prefix hash at block 6 differs. The lookback walks through blocks 5, 4, 3, 2, and 1, but the system never wrote an entry at any of those positions. No cache hit. You pay for a fresh cache write on every request and never get a read.
The lookback does not find stable content behind your breakpoint and cache it. It finds entries that prior requests already wrote, and writes happen only at breakpoints. Move `cache_control` to block 5, the last block that stays the same across requests, and every subsequent request reads the cached prefix. [Automatic caching](#automatic-caching) hits the same trap: it places the breakpoint on the last cacheable block, which in this structure is the one that changes every request, so use an explicit breakpoint on block 5 instead.
**Key takeaway:** Place `cache_control` on the last block whose prefix is identical across the requests you want to share a cache. In a growing conversation the final block works as long as each turn adds fewer than 20 blocks: earlier content never changes, so the next request's lookback finds the prior write. For a prompt with a varying suffix (timestamps, per-request context, the incoming message), place the breakpoint at the end of the static prefix, not on the varying block.
#### When to use multiple breakpoints
You can define up to 4 cache breakpoints if you want to:
- Cache different sections that change at different frequencies (for example, tools rarely change, but context updates daily)
- Have more control over exactly what gets cached
- Ensure a cache hit when a growing conversation pushes your breakpoint 20 or more blocks past the last cache write
**Important limitation:** The lookback can only find entries that earlier requests already wrote. If a growing conversation pushes your breakpoint 20 or more blocks past the last write, the lookback window misses it. Add a second breakpoint closer to that position from the start so a write accumulates there before you need it.
### Understanding cache breakpoint costs
**Cache breakpoints themselves don't add any cost.** You are only charged for:
- **Cache writes:** When new content is written to the cache (25% more than base input tokens for 5-minute TTL)
- **Cache reads:** When cached content is used (10% of base input token price, or 2.5% on Claude Fable 5.1 and Claude Mythos 5.1, and 5% on Claude Opus 5.5)
- **Regular input tokens:** For any uncached content
Adding more `cache_control` breakpoints doesn't increase your costs; you still pay the same amount based on what content is actually cached and read. The breakpoints give you control over what sections can be cached independently.
------------------------------------------------------------------------
## Caching strategies and considerations
### Cache limitations
On the Claude API, [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md), [Google Cloud](build-with-claude-claude-on-vertex-ai.md), and [Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md), the minimum cacheable prompt length is:
- 512 tokens for Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Opus 5, Claude Fable 5, and [Claude Mythos 5](../../22-Safety-Policy/glasswing.md)
- 2,048 tokens for [Claude Mythos Preview](../../22-Safety-Policy/glasswing.md) and Claude Opus 4.7
- 4,096 tokens for Claude Opus 4.6 and Claude Opus 4.5
- 1,024 tokens for Claude Opus 4.8, Claude Sonnet 5, Claude Sonnet 4.6, Claude Sonnet 4.5, Claude Opus 4.1 ([retired, except on Bedrock and Google Cloud](../../20-Models/about-claude-model-deprecations.md)), Claude Opus 4 ([retired, except on Google Cloud](../../20-Models/about-claude-model-deprecations.md)), and Claude Sonnet 4 ([retired, except on Bedrock and Google Cloud](../../20-Models/about-claude-model-deprecations.md))
- 4,096 tokens for Claude Haiku 4.5
- 2,048 tokens for Claude Haiku 3.5 ([retired, except on Bedrock and Google Cloud](../../20-Models/about-claude-model-deprecations.md))
These minimums apply on every platform where each model is available.
Shorter prompts cannot be cached, even if marked with `cache_control`. Any requests to cache fewer than this number of tokens will be processed without caching, and no error is returned. To verify whether a prompt was cached, check the [response usage fields](#tracking-cache-performance): if both `cache_creation_input_tokens` and `cache_read_input_tokens` are 0, the prompt was not cached (likely because it did not meet the minimum length requirement).
If your prompt falls just short of the minimum for your model and platform, expanding the cached content to reach the threshold is often worthwhile. Cache reads cost significantly less than uncached input tokens, so reaching the minimum can reduce costs for frequently reused prompts.
[Bedrock](build-with-claude-claude-in-amazon-bedrock.md) is an AWS-operated platform. On Bedrock, see the [Bedrock prompt caching documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html) for the per-model minimums, failure behavior, and usage-field names that apply.
For concurrent requests, note that a cache entry only becomes available after the first response begins. If you need cache hits for parallel requests, wait for the first response before sending subsequent requests.
Currently, "ephemeral" is the only supported cache type, which by default has a 5-minute lifetime.
### What can be cached
Most blocks in the request can be cached. This includes:
- Tools: Tool definitions in the `tools` array
- System messages: Content blocks in the `system` array
- Text messages: Content blocks in the `messages.content` array, for both user and assistant turns
- Images & Documents: Content blocks in the `messages.content` array, in user turns
- Tool use and tool results: Content blocks in the `messages.content` array, in both user and assistant turns
Each of these elements can be cached, either automatically or by marking them with `cache_control`.
### What cannot be cached
While most request blocks can be cached, there are some exceptions:
- Thinking blocks cannot be cached directly with `cache_control`. However, thinking blocks CAN be cached alongside other content when they appear in previous assistant turns. When cached this way, they DO count as input tokens when read from cache.
- Sub-content blocks (like [citations](build-with-claude-citations.md)) themselves cannot be cached directly. Instead, cache the top-level block.
In the case of citations, the top-level document content blocks that serve as the source material for citations can be cached. This allows you to use prompt caching with citations effectively by caching the documents that citations will reference.
- Empty text blocks cannot be cached.
### What invalidates the cache
Modifications to cached content can invalidate some or all of the cache.
As described in [Structuring your prompt](#structuring-your-prompt), the cache follows the hierarchy: `tools` → `system` → `messages`. Changes at each level invalidate that level and all subsequent levels.
The following table shows which parts of the cache are invalidated by different types of changes. ✘ indicates that the cache is invalidated, while ✓ indicates that the cache remains valid.
| What changes | Tools cache | System cache | Messages cache | Impact |
|-----------------------------------------------------------|----------------|----------------|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Tool definitions** | ✘ | ✘ | ✘ | Modifying tool definitions (names, descriptions, parameters) invalidates the entire cache |
| **Web search toggle** | ✓ | ✘ | ✘ | Enabling/disabling web search modifies the system prompt |
| **Citations toggle** | ✓ | ✘ | ✘ | Enabling/disabling citations modifies the system prompt |
| **Speed setting** | ✓ | ✘ | ✘ | Switching between [`speed: "fast"` and standard speed](build-with-claude-fast-mode.md) invalidates system and message caches |
| **Tool choice** | ✓ | ✓ | ✘ | Changes to `tool_choice` parameter only affect message blocks |
| **Images** | ✓ | ✓ | ✘ | Adding/removing images anywhere in the prompt affects message blocks |
| **Thinking parameters** | Model-specific | Model-specific | ✘ | The thinking configuration (mode, and `budget_tokens` in extended mode) is rendered into the prompt, so changing it always invalidates message blocks; tool and system caches are also invalidated on models that render the configuration ahead of them. See [Thinking and prompt caching](build-with-claude-thinking.md#thinking-and-prompt-caching). |
| **Effort setting** | Model-specific | Model-specific | ✘ | Changing the [`output_config.effort`](build-with-claude-effort.md) value always invalidates message blocks, with the same model-specific effect on tool and system caches as thinking parameters. Setting effort explicitly to the model's default is equivalent to omitting it and does not invalidate. On models that support [per-message effort](build-with-claude-effort.md#change-effort-mid-conversation-beta), an effort change carried in a `role: "system"` message inside `messages` leaves the cached prefix intact. |
| **Non-tool results passed to extended thinking requests** | ✓ | ✓ | Model-specific | On Opus 4.5+ and Sonnet 4.6+, thinking blocks are preserved by default, so the cache remains valid (✓). On earlier Opus/Sonnet models and all Haiku models, all previously-cached thinking blocks are stripped from context, and any messages that follow those thinking blocks are removed from the cache (✘). For more details, see [Caching with thinking blocks](#caching-with-thinking-blocks). |
| **Dropped thinking blocks** | ✓ | ✓ | ✘ | When the API drops a Claude Fable 5.1, Claude Mythos 5.1, or Claude Opus 5.5 thinking block that isn't [preserved](build-with-claude-thinking.md#preserved-thinking) on that request (for example, one you replay to a model that can't read it), the cached prefix changes from that block's position onward on that request. Blocks the receiving model can read, passed back unchanged, keep the cache intact. |
On models that support [mid-conversation tool changes](build-with-claude-mid-conversation-system-messages.md#mid-conversation-tool-changes), the `inline-tools-2026-09-15` beta header lets you add a tool, or change a tool's definition, partway through a conversation without editing `tools`. Send the definition in a `tool_addition` block in a mid-conversation system message and leave `tools` exactly as you first sent it. The cached prefix still matches, so only the appended message is processed as new input. The one exception is a `tools` array with no non-deferred tool, where the first tool defined this way costs one full cache miss on that request. See [Define tools in a message](build-with-claude-mid-conversation-system-messages.md#define-tools-in-a-message-beta).
On Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, [Claude Mythos 5](../../22-Safety-Policy/glasswing.md), Claude Opus 5.5, Claude Opus 4.8, and Claude Opus 5, you can add a new system instruction partway through a conversation without invalidating the system or message caches. Append a `{"role": "system"}` message to `messages` instead of editing the top-level `system` field, so the cached prefix stays unchanged. This feature is not available on Claude Sonnet 5. Use the top-level `system` field instead. See [Mid-conversation system messages](build-with-claude-mid-conversation-system-messages.md).
### Tracking cache performance
Monitor cache performance using these API response fields, within `usage` in the response (or `message_start` event if [streaming](build-with-claude-streaming.md)):
- `cache_creation_input_tokens`: Number of tokens written to the cache when creating a new entry.
- `cache_read_input_tokens`: Number of tokens retrieved from the cache for this request.
- `input_tokens`: Number of input tokens which were not read from or used to create a cache (that is, tokens after the last cache breakpoint).
**Understanding the token breakdown**
The `input_tokens` field represents only the tokens that come **after the last cache breakpoint** in your request, not all the input tokens you sent.
To calculate total input tokens:
``` block
total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens
```
**Spatial explanation:**
- `cache_read_input_tokens` = tokens before breakpoint already cached (reads)
- `cache_creation_input_tokens` = tokens before breakpoint being cached now (writes)
- `input_tokens` = tokens after your last breakpoint (not eligible for cache)
**Example:** If you have a request with 100,000 tokens of cached content (read from cache), 0 tokens of new content being cached, and 50 tokens in your user message (after the cache breakpoint):
- `cache_read_input_tokens`: 100,000
- `cache_creation_input_tokens`: 0
- `input_tokens`: 50
- **Total input tokens processed:** 100,050 tokens
This is important for understanding both costs and rate limits, as `input_tokens` will typically be much smaller than your total input when using caching effectively.
### Caching with thinking blocks
When using [thinking](build-with-claude-thinking.md) with prompt caching, thinking blocks have special behavior:
**Automatic caching alongside other content:** While thinking blocks cannot be explicitly marked with `cache_control`, they get cached as part of the request content when you make subsequent API calls with tool results. This commonly happens during tool use when you pass thinking blocks back to continue the conversation.
**Input token counting:** When thinking blocks are read from cache, they count as input tokens in your usage metrics. This is important for cost calculation and token budgeting.
**Cache invalidation patterns:**
- Cache remains valid when only tool results are provided as user messages
- On Opus 4.5+ and Sonnet 4.6+, thinking blocks are preserved by default even when non-tool-result user content is added, so the cache remains valid
- On earlier Opus/Sonnet models and all Haiku models, cache gets invalidated when non-tool-result user content is added, causing all previous thinking blocks to be stripped from context
- This caching behavior occurs even without explicit `cache_control` markers
For more details on cache invalidation, see [What invalidates the cache](#what-invalidates-the-cache).
**Example with tool use:**
```python
Request 1: User: "What's the weather in Paris?"
Response: [thinking_block_1] + [tool_use block 1]
Request 2:
User: ["What's the weather in Paris?"],
Assistant: [thinking_block_1] + [tool_use block 1],
User: [tool_result_1, cache=True]
Response: [thinking_block_2] + [text block 2]
# Request 2 caches its request content (not the response)
# The cache includes: user message, thinking_block_1, tool_use block 1, and tool_result_1
Request 3:
User: ["What's the weather in Paris?"],
Assistant: [thinking_block_1] + [tool_use block 1],
User: [tool_result_1, cache=True],
Assistant: [thinking_block_2] + [text block 2],
User: [Text response, cache=True]
# On earlier Opus/Sonnet and all Haiku models, non-tool-result user block causes prior thinking blocks to be stripped; on Opus 4.5+/Sonnet 4.6+ they are kept
```
On earlier Opus/Sonnet models and all Haiku models, all previous thinking blocks are removed from context at this point. On Opus 4.5+ and Sonnet 4.6+, prior thinking blocks are kept by default and remain part of the cached prefix.
For more detailed information, see [Thinking and prompt caching](build-with-claude-thinking.md#thinking-and-prompt-caching).
### Cache storage and sharing
Prompt caching uses [workspace](../Other/manage-claude-workspaces.md)-level isolation. Caches are isolated per workspace, ensuring data separation between workspaces within the same organization. This applies to the Claude API, Claude Platform on AWS, and Microsoft Foundry; Bedrock and Google Cloud maintain organization-level cache isolation. If you use multiple workspaces, review your caching strategy to account for this difference.
- **Organization and workspace isolation:** Caches are isolated between organizations. Different organizations never share caches, even if they use identical prompts. Caches are also isolated per workspace within an organization on the Claude API, Claude Platform on AWS, and Microsoft Foundry; Bedrock and Google Cloud use organization-level isolation only.
- **Exact matching:** Cache hits require 100% identical prompt segments, including all text and images up to and including the block marked with cache control.
- **Output token generation:** Prompt caching has no effect on output token generation. The response you receive is identical to what you would get if prompt caching were not used.
### Best practices for effective caching
To optimize prompt caching performance:
- Start with [automatic caching](#automatic-caching) for multi-turn conversations. It handles breakpoint management automatically.
- Use [explicit block-level breakpoints](#explicit-cache-breakpoints) when you need to cache different sections with different change frequencies.
- Cache stable, reusable content like system instructions, background information, large contexts, or frequent tool definitions.
- Place cached content at the prompt's beginning for best performance.
- Use cache breakpoints strategically to separate different cacheable prefix sections.
- Place the breakpoint on the last block that stays identical across requests. For a prompt with a static prefix and a varying suffix (timestamps, per-request context, the incoming message), that is the end of the prefix, not the varying block.
- Regularly analyze cache hit rates and adjust your strategy as needed.
### Optimizing for different use cases
Tailor your prompt caching strategy to your scenario:
- Conversational agents: Reduce cost and latency for extended conversations, especially those with long instructions or uploaded documents.
- Coding assistants: Improve autocomplete and code base Q&A by keeping relevant sections or a summarized version of the code base in the prompt.
- Large document processing: Incorporate complete long-form material including images in your prompt without increasing response latency.
- Detailed instruction sets: Share extensive lists of instructions, procedures, and examples to fine-tune Claude's responses. Developers often include an example or two in the prompt, but with prompt caching you can get even better performance by including 20+ diverse examples of high quality answers.
- Agentic tool use: Enhance performance for scenarios involving multiple tool calls and iterative code changes, where each step typically requires a new API call.
- Talk to books, papers, documentation, podcast transcripts, and other longform content: Bring any knowledge base alive by embedding the entire document(s) into the prompt, and letting users ask it questions.
### Troubleshooting common issues
If experiencing unexpected behavior:
[Cache diagnostics](build-with-claude-cache-diagnostics.md) has the API compare consecutive requests and report where the prompt prefix diverged, which automatically handles many of the steps in this list.
- Ensure cached sections are identical across calls. For explicit breakpoints, verify that `cache_control` markers are in the same locations
- Check that calls are made within the cache lifetime (5 minutes by default)
- Verify that `tool_choice`, image usage, the thinking configuration, and `output_config.effort` remain consistent between calls
- Validate that you are caching at least the minimum number of tokens for your model and platform (see [Cache limitations](#cache-limitations))
- Confirm your breakpoint is on a block that stays identical across requests. Cache writes happen only at the breakpoint, and if that block changes (timestamps, per-request context, the incoming message), the prefix hash never matches. The lookback does not find stable content behind the breakpoint; it only finds entries that earlier requests wrote at their own breakpoints
- Verify that the keys in your `tool_use` content blocks have stable ordering as some languages (for example, Swift, Go) randomize key order during JSON conversion, breaking caches
- Use [cache diagnostics](build-with-claude-cache-diagnostics.md) to have the API compare consecutive requests and report which part of the prompt diverged
Changes to `tool_choice` or the presence/absence of images anywhere in the prompt will invalidate the cache, requiring a new cache entry to be created. For more details on cache invalidation, see [What invalidates the cache](#what-invalidates-the-cache).
------------------------------------------------------------------------
## 1-hour cache duration
If you find that 5 minutes is too short, Anthropic also offers a 1-hour cache duration [at additional cost](#pricing).
The 1-hour cache duration is available on the Claude API, [Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md), [Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md), [Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md), [Google Cloud](build-with-claude-claude-on-vertex-ai.md), and [Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md).
To use the extended cache, include `ttl` in the `cache_control` definition like this:
```python
"cache_control": {
"type": "ephemeral",
"ttl": "1h"
}
```
The response includes detailed cache information like the following:
Output
```python
{
"usage": {
"input_tokens": 2048,
"cache_read_input_tokens": 1800,
"cache_creation_input_tokens": 248,
"output_tokens": 503,
"cache_creation": {
"ephemeral_5m_input_tokens": 148,
"ephemeral_1h_input_tokens": 100
}
}
}
```
Note that the current `cache_creation_input_tokens` field equals the sum of the values in the `cache_creation` object.
If you see `ephemeral_5m_input_tokens` writes you didn't request while using server tools such as web search, see [Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md#server-tool-results-are-cached-automatically).
### When to use the 1-hour cache
If you have prompts that are used at a regular cadence (that is, system prompts that are used more frequently than every 5 minutes), continue to use the 5-minute cache, because this will continue to be refreshed at no additional charge.
The 1-hour cache is best used in the following scenarios:
- When you have prompts that are likely used less frequently than 5 minutes, but more frequently than every hour. For example, when an agentic side-agent will take longer than 5 minutes, or when storing a long chat conversation with a user and you generally expect that user may not respond in the next 5 minutes.
- When latency is important and your follow-up prompts may be sent beyond 5 minutes.
- When you want to improve your rate limit utilization, because cache hits are not deducted against your rate limit.
The 5-minute and 1-hour cache behave the same with respect to latency. You will generally see improved time-to-first-token for long documents.
### Mixing different TTLs
You can use both 1-hour and 5-minute cache controls in the same request, but with an important constraint: Cache entries with longer TTL must appear before shorter TTLs (that is, a 1-hour cache entry must appear before any 5-minute cache entries).
When mixing TTLs, the API determines three billing locations in your prompt:
1. Position `A`: The token count at the highest cache hit (or 0 if no hits).
2. Position `B`: The token count at the highest 1-hour `cache_control` block after `A` (or equals `A` if none exist).
3. Position `C`: The token count at the last `cache_control` block.
If `B` or `C` is larger than `A`, it is necessarily a cache miss, because `A` is the highest cache hit.
You'll be charged for:
1. Cache read tokens for `A`.
2. 1-hour cache write tokens for `(B - A)`.
3. 5-minute cache write tokens for `(C - B)`.
Here are three examples. This depicts the input tokens of 3 requests, each of which has different cache hits and cache misses. Each has a different calculated pricing, shown in the colored boxes, as a result.
------------------------------------------------------------------------
## Pre-warming the cache
Cache pre-warming lets you load your system prompt or tool definitions into the prompt cache before a user triggers a real request. This eliminates the cache-miss latency penalty on the first user interaction, reducing time-to-first-token (TTFT) for latency-sensitive applications.
### How it works
Set `max_tokens: 0` in your request. The API reads your prompt into the model and writes the cache at any `cache_control` breakpoint, then returns immediately without generating any output. The response has an empty `content` array, `stop_reason: "max_tokens"`, and a fully populated `usage` block.
Place the `cache_control` breakpoint on the last block that is shared with the follow-up request (typically your system prompt or tool definitions), not on the placeholder user message. Otherwise the cache entry is keyed to the placeholder and the follow-up request won't hit it. Use the same thinking configuration and `output_config.effort` as your follow-up requests too: those values are rendered into the prompt (see [What invalidates the cache](#what-invalidates-the-cache)), so a pre-warm with a different configuration can write an entry your real traffic never hits. This means using an [explicit cache breakpoint](#explicit-cache-breakpoints) rather than [automatic caching](#automatic-caching), since automatic caching places the breakpoint on the last block, which here is the placeholder. The placeholder user message can be any string with non-whitespace content (the examples here use `"warmup"`); its content is read into the model but never answered.
A pre-warm request incurs a **cache write** charge if the prefix is not already cached, the same as any other request. Check `usage.cache_creation_input_tokens` in the response to confirm a write occurred. Zero output tokens are billed.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Fire this before users arrive to warm the shared system-prompt cache.
prewarm = client.messages.create(
model="claude-opus-5-5",
max_tokens=0,
system=[
{
"type": "text",
"text": "You are an expert software engineer with deep knowledge of distributed systems...",
"cache_control": {"type": "ephemeral"},
}
],
messages=[{"role": "user", "content": "warmup"}],
)
print(prewarm.stop_reason) # "max_tokens"
print(prewarm.content) # []
print(prewarm.usage)
```
The API returns an empty `content` array:
Output
```python
{
"id": "msg_01XFDUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"content": [],
"model": "claude-opus-5-5",
"stop_reason": "max_tokens",
"stop_sequence": null,
"usage": {
"input_tokens": 8,
"cache_creation_input_tokens": 5120,
"cache_read_input_tokens": 0,
"cache_creation": {
"ephemeral_5m_input_tokens": 5120,
"ephemeral_1h_input_tokens": 0
},
"iterations": [
{
"input_tokens": 8,
"output_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 5120,
"cache_creation": {
"ephemeral_5m_input_tokens": 5120,
"ephemeral_1h_input_tokens": 0
},
"type": "message"
}
],
"output_tokens": 0,
"service_tier": "standard",
"inference_geo": "global"
}
}
```
### Typical usage pattern
Fire a pre-warm request when your application starts (or on a scheduled interval), then send real user requests after the pre-warm completes:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
SYSTEM_PROMPT = [
{
"type": "text",
"text": "You are an expert software engineer with deep knowledge of distributed systems...",
"cache_control": {"type": "ephemeral"},
}
]
def prewarm_cache() -> None:
"""Call this at application startup or on a scheduled interval."""
client.messages.create(
model="claude-opus-5-5",
max_tokens=0,
system=SYSTEM_PROMPT,
messages=[{"role": "user", "content": "warmup"}],
)
def respond(user_message: str) -> anthropic.types.Message:
"""The real user request; benefits from a warm cache."""
return client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
system=SYSTEM_PROMPT,
messages=[{"role": "user", "content": user_message}],
)
# Warm the cache before any user traffic arrives.
prewarm_cache()
# Later, when the user submits a message, the system-prompt prefix is already cached.
response = respond("How do I implement a binary search tree?")
for block in response.content:
if block.type == "text":
print(block.text)
```
Keep in mind that the cache TTL still applies. For the default 5-minute cache, send a new pre-warm request at least every 5 minutes to keep the cache warm. For longer gaps between user requests, use the [1-hour cache duration](#1-hour-cache-duration) instead.
### Limitations
A `max_tokens: 0` request is rejected with an `invalid_request_error` if any of the following are set, since each implies output that a zero-token budget cannot produce:
- `stream: true`
- [Extended thinking](build-with-claude-extended-thinking.md) (`thinking.type: "enabled"`)
- [Structured outputs](build-with-claude-structured-outputs.md) (`output_config.format`)
- `tool_choice` of `{"type": "tool", ...}` or `{"type": "any"}`
`max_tokens: 0` is also rejected inside a [Message Batches](build-with-claude-batch-processing.md) request. Pre-warming targets time-to-first-token, which does not apply to batch processing, and a cache entry written during batch processing would likely expire before the follow-up request runs.
### Replacing the max_tokens=1 workaround
Before `max_tokens: 0` was available, some applications used `max_tokens: 1` warm-up calls to achieve the same effect. The `max_tokens: 0` approach is preferred: no output is produced, so there is no single-token reply to discard, no output tokens are billed, and the intent of the request is unambiguous.
------------------------------------------------------------------------
## Prompt caching examples
To help you get started with prompt caching, the [prompt caching cookbook](https://platform.claude.com/cookbook/misc-prompt-caching) provides detailed examples and best practices.
The following code snippets showcase various prompt caching patterns. These examples demonstrate how to implement caching in different scenarios, helping you understand the practical applications of this feature:
### Large context caching example
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": "You are an AI assistant tasked with analyzing legal documents.",
},
{
"type": "text",
"text": "Here is the full text of a complex legal agreement: [Insert full text of a 50-page legal agreement here]",
"cache_control": {"type": "ephemeral"},
},
],
messages=[
{
"role": "user",
"content": "What are the key terms and conditions in this agreement?",
}
],
)
print(response.usage.model_dump_json())
```
This example demonstrates basic prompt caching usage, caching the full text of the legal agreement as a prefix while keeping the user instruction uncached.
For the first request:
- `input_tokens`: Number of tokens in the user message only
- `cache_creation_input_tokens`: Number of tokens in the entire system message, including the legal document
- `cache_read_input_tokens`: 0 (no cache hit on first request)
For subsequent requests within the cache lifetime:
- `input_tokens`: Number of tokens in the user message only
- `cache_creation_input_tokens`: 0 (no new cache creation)
- `cache_read_input_tokens`: Number of tokens in the entire cached system message
### Caching tool definitions
Tool definitions can be cached by placing `cache_control` on the last tool in your `tools` array. All tools defined before and including that tool are cached as a single prefix.
```python
{
"model": "claude-opus-5-5",
"max_tokens": 1024,
"tools": [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": { "location": { "type": "string" } },
"required": ["location"]
}
},
{
"name": "get_time",
"description": "Get the current time in a given time zone",
"input_schema": {
"type": "object",
"properties": { "timezone": { "type": "string" } },
"required": ["timezone"]
},
"cache_control": { "type": "ephemeral" }
}
],
"messages": [{ "role": "user", "content": "What is the weather and time in New York?" }]
}
```
On the first request, `cache_creation_input_tokens` reflects the token count of all tool definitions. On subsequent requests within the cache lifetime, those tokens appear under `cache_read_input_tokens` instead.
For detailed interaction between tool definitions, `defer_loading`, and cache invalidation, see [Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md).
### Continuing a multi-turn conversation
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": "...long system prompt",
"cache_control": {"type": "ephemeral"},
}
],
messages=[
# ...long conversation so far
{
"role": "user",
"content": [
{
"type": "text",
"text": "Hello, can you tell me more about the solar system?",
}
],
},
{
"role": "assistant",
"content": "Certainly! The solar system is the collection of celestial bodies that orbit our Sun. It consists of eight planets, numerous moons, asteroids, comets, and other objects. The planets, in order from closest to farthest from the Sun, are: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune. Each planet has its own unique characteristics and features. Is there a specific aspect of the solar system you'd like to know more about?",
},
{
"role": "user",
"content": [
{"type": "text", "text": "Good to know."},
{
"type": "text",
"text": "Tell me more about Mars.",
"cache_control": {"type": "ephemeral"},
},
],
},
],
)
print(response.usage.model_dump_json())
```
This example demonstrates how to use prompt caching in a multi-turn conversation.
During each turn, the final block of the final message is marked with `cache_control` so the conversation can be incrementally cached. The system automatically looks up and uses the longest previously cached sequence of blocks for follow-up messages. That is, blocks that were previously marked with a `cache_control` block are later not marked with this, but they will still be considered a cache hit (and also a cache refresh!) if they are hit within 5 minutes.
In addition, note that the `cache_control` parameter is placed on the system message. This is to ensure that if this gets evicted from the cache (after not being used for more than 5 minutes), it will get added back to the cache on the next request.
This approach is useful for maintaining context in ongoing conversations without repeatedly processing the same information.
When this is set up properly, you should see the following in the usage response of each request:
- `input_tokens`: Number of tokens in the new user message (will be minimal)
- `cache_creation_input_tokens`: Number of tokens in the new assistant and user turns
- `cache_read_input_tokens`: Number of tokens in the conversation up to the previous turn
### Putting it all together: Multiple cache breakpoints
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
tools=[
{
"name": "search_documents",
"description": "Search through the knowledge base",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"}
},
"required": ["query"],
},
},
{
"name": "get_document",
"description": "Retrieve a specific document by ID",
"input_schema": {
"type": "object",
"properties": {
"doc_id": {"type": "string", "description": "Document ID"}
},
"required": ["doc_id"],
},
"cache_control": {"type": "ephemeral"},
},
],
system=[
{
"type": "text",
"text": "You are a helpful research assistant with access to a document knowledge base.\n\n# Instructions\n- Always search for relevant documents before answering\n- Provide citations for your sources\n- Be objective and accurate in your responses\n- If multiple documents contain relevant information, synthesize them\n- Acknowledge when information is not available in the knowledge base",
"cache_control": {"type": "ephemeral"},
},
{
"type": "text",
"text": "# Knowledge Base Context\n\nHere are the relevant documents for this conversation:\n\n## Document 1: Solar System Overview\nThe solar system consists of the Sun and all objects that orbit it...\n\n## Document 2: Planetary Characteristics\nEach planet has unique features. Mercury is the smallest planet...\n\n## Document 3: Mars Exploration\nMars has been a target of exploration for decades...\n\n[Additional documents...]",
"cache_control": {"type": "ephemeral"},
},
],
messages=[
{
"role": "user",
"content": "Can you search for information about Mars rovers?",
},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "tool_1",
"name": "search_documents",
"input": {"query": "Mars rovers"},
}
],
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "tool_1",
"content": "Found 3 relevant documents: Document 3 (Mars Exploration), Document 7 (Rover Technology), Document 9 (Mission History)",
}
],
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I found 3 relevant documents about Mars rovers. Let me get more details from the Mars Exploration document.",
}
],
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "Yes, please tell me about the Perseverance rover specifically.",
"cache_control": {"type": "ephemeral"},
}
],
},
],
)
print(response.usage.model_dump_json())
```
This comprehensive example demonstrates how to use all 4 available cache breakpoints to optimize different parts of your prompt:
1. **Tools cache** (cache breakpoint 1): The `cache_control` parameter on the last tool definition caches all tool definitions.
2. **Reusable instructions cache** (cache breakpoint 2): The static instructions in the system prompt are cached separately. These instructions rarely change between requests.
3. **RAG context cache** (cache breakpoint 3): The knowledge base documents are cached independently, allowing you to update the RAG documents without invalidating the tools or instructions cache.
4. **Conversation history cache** (cache breakpoint 4): The final user message is marked with `cache_control` to enable incremental caching of the conversation as it progresses.
This approach provides maximum flexibility:
- If you append a new turn to the conversation without changing earlier content, all four cache segments are reused
- If you update the RAG documents but keep the same tools and instructions, the first two cache segments are reused
- If you change the conversation but keep the same tools, instructions, and documents, the first three segments are reused
- Changes at any breakpoint invalidate that segment and everything after it, while earlier cached segments remain valid
For the first request:
- `input_tokens`: Minimal (tokens after the final cache breakpoint, near 0 in this example)
- `cache_creation_input_tokens`: Tokens in all cached segments (tools + instructions + RAG documents + conversation history)
- `cache_read_input_tokens`: 0 (no cache hits)
For subsequent requests with only a new user message (and the fourth breakpoint moved to that new final message, as in the example):
- `input_tokens`: Minimal (tokens after the final cache breakpoint, near 0 in this example)
- `cache_creation_input_tokens`: Tokens in the new user message and the previous assistant turn (the new conversation segment being cached)
- `cache_read_input_tokens`: All previously cached tokens (tools + instructions + RAG documents + previous conversation)
This pattern is especially powerful for:
- RAG applications with large document contexts
- Agent systems that use multiple tools
- Long-running conversations that need to maintain context
- Applications that need to optimize different parts of the prompt independently
## Data retention
Prompt caching (both automatic and explicit) is ZDR eligible. Anthropic does not store the raw text of your prompts or Claude's responses.
KV (key-value) cache representations and cryptographic hashes of cached content are held in memory only and are not stored at rest. Cached entries have a minimum lifetime of 5 minutes (standard) or 1 hour (extended), after which they are promptly, though not immediately, deleted. Cache entries are isolated between organizations and, on the Claude API, Claude Platform on AWS, and Microsoft Foundry, between workspaces within an organization.
For ZDR eligibility across all features, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
------------------------------------------------------------------------
## FAQ
### Do I need multiple cache breakpoints or is one at the end sufficient?
**In most cases, a single cache breakpoint at the end of your static content is sufficient.** Cache writes happen only at the block you mark. Place it on the last block that stays identical across requests, and every subsequent request reads that same entry. If a later block varies per request (a timestamp, the incoming message), keep the breakpoint before it, on the last stable block.
You only need multiple breakpoints if:
- A growing conversation pushes your breakpoint 20 or more blocks past the last cache write, putting the prior entry outside the lookback window
- You want to cache sections that update at different frequencies independently
- You need explicit control over what gets cached for cost optimization
Example: If you have system instructions (rarely change) and RAG context (changes daily), you might use two breakpoints to cache them separately.
### Do cache breakpoints add extra cost?
No, cache breakpoints themselves are free. You only pay for:
- Writing content to cache (25% more than base input tokens for 5-minute TTL)
- Reading from cache (a fraction of the base input token price, see [Pricing](#pricing))
- Regular input tokens for uncached content
The number of breakpoints doesn't affect pricing; only the amount of content cached and read matters.
### How do I calculate total input tokens from the usage fields?
The usage response includes three separate input token fields that together represent your total input:
``` block
total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens
```
- `cache_read_input_tokens`: Tokens retrieved from cache (everything before cache breakpoints that was cached)
- `cache_creation_input_tokens`: New tokens being written to cache (at cache breakpoints)
- `input_tokens`: Tokens **after the last cache breakpoint** that aren't cached
**Important:** `input_tokens` does NOT represent all input tokens, only the portion after your last cache breakpoint. If you have cached content, `input_tokens` will typically be much smaller than your total input.
**Example:** With a 200k token document cached and a 50 token user question:
- `cache_read_input_tokens`: 200,000
- `cache_creation_input_tokens`: 0
- `input_tokens`: 50
- **Total:** 200,050 tokens
This breakdown is critical for understanding both your costs and rate limit usage. See [Tracking cache performance](#tracking-cache-performance) for more details.
### What is the cache lifetime?
The cache's default minimum lifetime (TTL) is 5 minutes. This lifetime is refreshed each time the cached content is used.
If you find that 5 minutes is too short, Anthropic also offers a [1-hour cache TTL](#1-hour-cache-duration).
### When does the cache lifetime start?
The lifetime is measured from the start of the request that writes or reads the cache entry, not from the end of its response. Time spent generating a response counts against the lifetime, so the window for a follow-up request to reuse the cache is the lifetime minus the generation time.
If your requests produce long responses and the next request might not start until after the lifetime elapses, use the [1-hour cache TTL](#1-hour-cache-duration).
### How many cache breakpoints can I use?
You can define up to 4 cache breakpoints (using `cache_control` parameters) in your prompt.
### Is prompt caching available for all models?
Prompt caching is supported on all [active Claude models](../../20-Models/about-claude-models-overview.md).
### How does prompt caching work with thinking?
Changing thinking parameters (switching modes, or changing the budget in extended mode) invalidates cached message prefixes, and can invalidate cached system prompts and tools as well, because the thinking configuration is rendered into the prompt. The [`output_config.effort`](build-with-claude-effort.md) value behaves the same way.
For more details on cache invalidation, see [What invalidates the cache](#what-invalidates-the-cache).
For more on thinking, including its interaction with tool use and prompt caching, see [Thinking and prompt caching](build-with-claude-thinking.md#thinking-and-prompt-caching).
### How do I enable prompt caching?
The easiest way is to add `"cache_control": {"type": "ephemeral"}` at the top level of your request body ([automatic caching](#automatic-caching)). Alternatively, include at least one `cache_control` breakpoint on individual content blocks ([explicit cache breakpoints](#explicit-cache-breakpoints)).
### Can I use prompt caching with other API features?
Yes, prompt caching can be used alongside other API features like tool use and vision capabilities. However, changing whether there are images in a prompt or modifying tool use settings will break the cache.
For more details on cache invalidation, see [What invalidates the cache](#what-invalidates-the-cache).
### How does prompt caching affect pricing?
Prompt caching introduces a new pricing structure where 5-minute cache writes cost 25% more than base input tokens, 1-hour cache writes cost 2x base input tokens, and cache hits cost a fraction of the base input token price (see [Pricing](#pricing) for the per-model multiplier).
### Can I manually clear the cache?
Currently, there's no way to manually clear the cache. Cached prefixes automatically expire after a minimum of 5 minutes of inactivity.
### How can I track the effectiveness of my caching strategy?
You can monitor cache performance using the `cache_creation_input_tokens` and `cache_read_input_tokens` fields in the API response.
### What can break the cache?
See [What invalidates the cache](#what-invalidates-the-cache) for more details on cache invalidation, including a list of changes that require creating a new cache entry.
### How does prompt caching handle privacy and data separation?
Prompt caching is designed with strong privacy and data separation measures:
1. Cache keys are generated using a cryptographic hash of the prompts up to the cache control point. This means only requests with identical prompts can access a specific cache.
2. On the Claude API, Claude Platform on AWS, and Microsoft Foundry, caches are isolated per workspace within an organization. On Bedrock and Google Cloud, caches are isolated per organization. In every case, caches are never shared across organizations, even for identical prompts. See [Cache storage and sharing](#cache-storage-and-sharing) for details.
3. The caching mechanism is designed to maintain the integrity and privacy of each unique conversation or context.
4. It's safe to use `cache_control` anywhere in your prompts. For caching to produce reads, place the breakpoint at the end of a stable prefix: placing it on a block that changes every request (such as a timestamp or the user's arbitrary input) writes a fresh entry each time and never hits.
These measures ensure that prompt caching maintains data privacy and security while offering performance benefits.
### Can I use prompt caching with the Batches API?
Yes, it is possible to use prompt caching with your [Batches API](build-with-claude-batch-processing.md) requests. However, because asynchronous batch requests can be processed concurrently and in any order, cache hits are provided on a best-effort basis.
The [1-hour cache](#1-hour-cache-duration) can help improve your cache hits. The most cost effective way of using it is the following:
- Gather a set of message requests that have a shared prefix.
- Send a batch request with a single request that has this shared prefix and a 1-hour cache block. This writes the prefix to the 1-hour cache.
- As soon as this is complete, submit the rest of the requests. You will have to monitor the job to know when it completes.
This is typically better than using the 5-minute cache because it's common for batch requests to take between 5 minutes and 1 hour to complete.
### Why am I seeing the error \`AttributeError: 'Beta' object has no attribute 'prompt_caching'\` in Python?
This error typically appears when you have upgraded your SDK or you are using outdated code examples. Prompt caching no longer requires the beta prefix. Instead of:
Python
```python
client.beta.prompt_caching.messages.create(**params)
```
Use:
Python
```python
client.messages.create(**params)
```
### Why am I seeing 'TypeError: Cannot read properties of undefined (reading 'messages')'?
This error typically appears when you have upgraded your SDK or you are using outdated code examples. Prompt caching no longer requires the beta prefix. Instead of:
TypeScript
```python
client.beta.promptCaching.messages.create(/* ... */);
```
Use:
```python
client.messages.create(/* ... */);
```
---
## Rate Limits API
Source: https://platform.claude.com/docs/en/build-with-claude/rate-limits-api
Path: 04-API-Reference/Guides/build-with-claude-rate-limits-api.md
# Rate Limits API
Programmatically query your organization's API rate limits with the Rate Limits API.
---
<Tip>
**The Admin API is unavailable for individual accounts.** To collaborate with teammates and add members, set up your organization in **Console → Settings → Organization**.
</Tip>
The Rate Limits API provides programmatic access to the rate limits configured for your organization and its workspaces. This is the same information shown on the [Limits](../Other/usage-limits.md) page in the Claude Console.
Use this API to:
- **Keep gateways and proxies in sync:** Read your current limits at startup and on a schedule instead of hardcoding values that drift when Anthropic adjusts them.
- **Power internal alerting:** Compare usage data from the [Usage and Cost API](build-with-claude-usage-cost-api.md) against your configured limits.
- **Audit workspace configuration:** Verify that workspace overrides match what your provisioning automation expects.
<Check>
**Admin API key required**
This API is part of the [Admin API](build-with-claude-administration-api.md). These endpoints require an Admin API key (starting with `sk-ant-admin...`) that differs from standard API keys. Only organization members with the admin role can provision Admin API keys through the [Claude Console](../Other/usage-limits.md).
</Check>
## Quick start
List the rate limits configured for your organization:
```bash cURL
curl "https://api.anthropic.com/v1/organizations/rate_limits" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
## Organization rate limits
The `/v1/organizations/rate_limits` endpoint returns the rate limits applied at the organization level for the Messages API and its supporting resources. Limits for other products, such as [Claude Managed Agents](../Other/managed-agents-overview.md), are not included.
### Key concepts
- **Rate limit groups:** Each entry in the response represents one rate limit group. Model rate limits are grouped so that several model versions share a single set of limits, and other groups cover resources such as the Message Batches API, the Files API, the Token Counting API, agent skills, and the web search tool.
- **`group_type`:** Identifies which category of limits the entry covers. See [Filtering by group type](#filtering-by-group-type) for the list of values.
- **`models` list:** For `model_group` entries, the `models` field lists every model ID and alias that counts against that group's limits. Use this list to look up which group any model string falls under. For other group types, `models` is `null`.
- **`limits` list:** Each group carries a list of `{type, value}` pairs. The `type` field identifies the limiter (such as `requests_per_minute`, `input_tokens_per_minute`, or `output_tokens_per_minute`) and `value` is the configured limit. See [Rate limits](../Endpoints/rate-limits.md) for how each limiter is measured and enforced.
For complete parameter details and response schemas, see the [Organization Rate Limits API reference](../Admin/admin-rate-limits-list.md).
### List all organization rate limits
```bash cURL
curl "https://api.anthropic.com/v1/organizations/rate_limits" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
```json
{
"data": [
{
"type": "rate_limit",
"group_type": "model_group",
"models": [
"claude-opus-4-5",
"claude-opus-4-5-20251101",
"claude-opus-4-6",
"claude-opus-4-7"
],
"limits": [
{ "type": "requests_per_minute", "value": 4000 },
{ "type": "input_tokens_per_minute", "value": 2000000 },
{ "type": "output_tokens_per_minute", "value": 400000 }
]
},
{
"type": "rate_limit",
"group_type": "batch",
"models": null,
"limits": [{ "type": "enqueued_batch_requests", "value": 500000 }]
}
],
"next_page": null
}
```
### Look up the limits for a specific model
Pass any model ID or alias as the `model` query parameter to return only the entry that contains it:
```bash cURL
curl "https://api.anthropic.com/v1/organizations/rate_limits?model=claude-opus-4-7" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
If the model string doesn't match any group, the endpoint returns a 404 error. The `model` parameter is supported on the organization endpoint only; the workspace endpoint doesn't accept it.
## Workspace rate limits
The `/v1/organizations/workspaces/{workspace_id}/rate_limits` endpoint returns the rate limit overrides configured for a single workspace.
The response only includes overrides, so anything missing from it is inherited from the organization:
- A group that is absent from `data` has no workspace override at all. The workspace inherits the organization-level limits for that group (it is not unlimited).
- Within a group that is present, a limiter type that is absent from `limits[]` has no workspace override for that limiter. The workspace inherits the organization value for it.
- For each limiter that is present, `org_limit` is the organization-level value for the same limiter, or `null` if the organization has no configured limit for that limiter type.
For complete parameter details and response schemas, see the [Workspace Rate Limits API reference](../Admin/admin-workspaces-rate-limits-list.md).
<Tip>
To retrieve your organization's workspace IDs, use the [List Workspaces](../Admin/admin-workspaces-list.md) endpoint, or find them in the [Claude Console](../Other/usage-limits.md). The default workspace cannot have rate limit overrides, so it has no entry on this endpoint; use the organization endpoint to read its limits.
</Tip>
```bash cURL
curl "https://api.anthropic.com/v1/organizations/workspaces/wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ/rate_limits" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
```json
{
"data": [
{
"type": "workspace_rate_limit",
"group_type": "model_group",
"models": [
"claude-opus-4-5",
"claude-opus-4-5-20251101",
"claude-opus-4-6",
"claude-opus-4-7"
],
"limits": [
{ "type": "requests_per_minute", "value": 1000, "org_limit": 4000 },
{ "type": "input_tokens_per_minute", "value": 500000, "org_limit": 2000000 }
]
}
],
"next_page": null
}
```
## Filtering by group type
Both endpoints accept an optional `group_type` query parameter that restricts the response to a single category:
```bash cURL
curl "https://api.anthropic.com/v1/organizations/rate_limits?group_type=batch" \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
Valid values are `model_group`, `batch`, `token_count`, `files`, `skills`, and `web_search`.
## Pagination
Both endpoints accept a `page` query parameter and return a `next_page` field. Responses are currently always a single page, so `next_page` is `null`. Loop on `next_page` so your client paginates correctly without changes when the response grows.
## Frequently asked questions
### Which model strings appear in the `models` list?
Every model ID and alias that counts against the group, including dated IDs (such as `claude-sonnet-4-5-20250929`) and undated aliases (such as `claude-sonnet-4-5`). Look up any model string you pass to the Messages API and you'll find it in exactly one `model_group` entry.
### What does it mean if a group is missing from the workspace response?
The workspace has no override for that group and inherits the organization-level limit. Query the organization endpoint to see the inherited values.
### Can I update rate limits with this API?
No. To set workspace rate limits, open the workspace in the [Claude Console](../Other/usage-limits.md) and use the **Limits** tab.
## See also
- [Rate limits](../Endpoints/rate-limits.md)
- [Admin API overview](build-with-claude-administration-api.md)
- [Admin API reference](../Admin/admin.md)
- [Workspaces](../Other/manage-claude-workspaces.md)
- [Usage and Cost API](build-with-claude-usage-cost-api.md)
---
## Refusals and fallback - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback
Path: 04-API-Reference/Guides/build-with-claude-refusals-and-fallback.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Frefusals-and-fallback)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Building with Claude
# Refusals and fallback
Copy page
How Claude Fable and Claude Opus models return classifier refusals and how to retry refused requests on a fallback model.
Copy page
Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, and Claude Opus 5 include safety classifiers that can decline a request. When that happens, you receive a normal response, not an error, with `stop_reason: "refusal"`. Its `stop_details.category` names the policy area (see [What a refusal looks like](#refusal-response)). You can usually still get an answer by sending the same request to another Claude model. This page shows you how to recognize a refusal and how to set up that retry.
Read this page when you build on any of these models and want declined requests to fall through to another model automatically. It also applies when you have seen `"refusal"` in a response and want to know what to do next.
Related pages:
- [Stop reasons and fallback](build-with-claude-handling-stop-reasons.md): the full list of `stop_reason` values.
- [Fallback credit](build-with-claude-fallback-credit.md): how to avoid paying the prompt-cache cost twice when you build the retry yourself.
- [SDK middleware](../Other/cli-sdks-libraries-middleware.md): the SDK helper that wraps all of this.
- [Fallback and billing cookbook](https://platform.claude.com/cookbook/fable-5-fallback-billing-guide): a worked end-to-end example.
The simplest setup, in beta on the Claude API: set `fallbacks` to `"default"`, and the API retries a declined request on the fallback model Anthropic recommends for its refusal category. For categories with no recommended fallback, the refusal stands.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = Anthropic()
response = client.beta.messages.create(
model="claude-fable-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
fallbacks="default",
betas=["server-side-fallback-2026-07-01"],
)
print(response.model)
```
The following sections cover what a refusal response contains, when to use server-side or client-side fallback, and how each is billed.
## What a refusal looks like
A refusal is a successful HTTP 200 response with `stop_reason: "refusal"`:
```python
{
"id": "msg_01XFUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"model": "claude-fable-5",
"content": [],
"stop_reason": "refusal",
"stop_details": {
"type": "refusal",
"category": "cyber",
"explanation": "This request was declined because it could enable cyber harm."
},
"usage": {
"input_tokens": 412,
"output_tokens": 0
}
}
```
The `stop_details` object explains the decline:
- **`category`:** names the policy area that triggered the classifier.
- **`explanation`:** a human-readable description. The text is not stable, so display it rather than parse it.
- **`recommended_model`:** present only on requests that set `fallbacks` ([server-side fallback](#server-side-fallback), beta). It names a model to retry directly when the API skipped the fallback attempt (for example, the fallback model was rate limited), and is `null` otherwise. It's a hint, not a guarantee.
- `category` and `explanation` are both `null` when the refusal does not map to a named category. That `null` is a normal, permanent value, not a placeholder.
- `stop_details` itself is `null` for every stop reason other than `refusal`.
| `category` | What it means | Billed before any output |
|:-------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------|
| `"cyber"` | The request could enable cyber harm, such as malware or exploit development. Benign cybersecurity work can also trigger this category. | No |
| `"bio"` | The request could enable biological harm, such as dangerous lab methods. Beneficial life sciences work can also trigger this category. | Yes |
| `"frontier_llm"` | The request could assist the development of competing AI models, which is restricted under [Anthropic's commercial terms](https://www.anthropic.com/legal/commercial-terms). Benign machine learning work can also trigger this category. | Yes |
| `"reasoning_extraction"` | The request asks the model to reproduce its internal reasoning in the response text. To get reasoning in a structured form instead, use [adaptive thinking](build-with-claude-thinking.md). | Yes |
| `"general_harms"` | The request falls under a usage-policy area outside the four named categories. Benign work can also trigger this category. | No |
A refusal can arrive before any output, or mid-stream after partial output. In either case, treat any partial output as incomplete and discard it.
## How refusals are billed
These billing rules apply on every platform: the Claude API, Amazon Bedrock, Claude Platform on AWS, Google Cloud, and Microsoft Foundry.
**Refusals before any output:** To disrupt attempts to circumvent Anthropic's safeguards at scale, a refusal that arrives before any output is billed when its `stop_details.category` is `"bio"`, `"frontier_llm"`, or `"reasoning_extraction"`. These are the categories where Anthropic measures low volumes of false positives, as of September 2026. These refusals are billed like any other request, at the rates of the model that ran it. A refusal before any output in any other category, or with a `null` category, is not billed. Either way, `content` is empty and token counts appear in `usage`. The request still counts against your rate limits.
**Mid-stream refusals:** A mid-stream refusal bills the input tokens and the output already streamed at normal rates.
**Fallback:** When you use fallback, the refusal that triggered it is billed, in addition to the fallback request, when it arrived mid-stream or is in one of the billed categories. [Fallback credit](build-with-claude-fallback-credit.md) compensates for the fallback request's prompt-cache miss, so you don't pay to cache the conversation twice. For how server-side fallback reports each attempt, see [Billing and rate limits](#billing-and-rate-limits).
The billed categories may change as Anthropic keeps measuring and refining its safeguards' false positive rates. The **Billed before any output** column in the [refusal category table](#refusal-response) lists the billed categories.
## Picking a fallback approach
There are three ways to retry a refused request on another model. The right one depends on where you are running and how much control you need.
| Your situation | Use | Why |
|:-------------------------------------|:---------------------------------------------------------------------------------------------------|:------------------------------------------------------------|
| Claude API, simplest setup | [Server-side fallback](#server-side-fallback) | One request, one response. The API handles the retry. |
| Any platform, using an Anthropic SDK | [The SDK middleware](#client-side-fallback) | Configure once on the client. Retries happen automatically. |
| Raw HTTP or custom retry logic | [A manual retry](#manual-retry) with [fallback credit](build-with-claude-fallback-credit.md) | Full control. Fallback credit keeps the cost down. |
Server-side fallback and the SDK middleware apply fallback credit for you. You only need the [Fallback credit](build-with-claude-fallback-credit.md) page when you build the retry yourself.
## Server-side fallback
Server-side fallback retries a refused request inside a single API call. In the default mode, when the primary model declines and the refusal category has a recommended fallback, the API runs the same request on the model Anthropic recommends for that category. You can instead [name up to three fallback models of your own](#naming-your-own-fallback-models). Either way, you get back one response that names the model that answered, so your user gets an answer in one round trip.
Server-side fallback is in beta on the Claude API. The `fallbacks` parameter is not supported on the [Message Batches API](build-with-claude-batch-processing.md) (a batch item that includes it comes back as an errored result) and is not available on Amazon Bedrock, Google Cloud, or Microsoft Foundry. On those platforms, use [client-side fallback with the SDK middleware](#client-side-fallback) instead.
### Making the request
Set the `fallbacks` parameter to the string `"default"` and send the `server-side-fallback-2026-07-01` beta header. The API then applies the requested model's server-defined default routing, which selects a recommended fallback model based on the refusal category the classifier reports, so refused requests are served without you maintaining a model list as recommendations change.
Default routing never draws the up-front [oversized-image rejection](build-with-claude-vision-coordinates.md#oversized-image-error) for models you did not choose: a routed model that would resize an image marked `"oversized_image": "error"` is dropped from the routing instead, so a marked image is never served resized.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = Anthropic()
response = client.beta.messages.create(
model="claude-fable-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
fallbacks="default",
betas=["server-side-fallback-2026-07-01"],
)
# A fallback_message entry in usage.iterations means a fallback model ran;
# pair it with stop_reason to confirm the fallback served the response.
fallback_ran = any(
iteration.type == "fallback_message"
for iteration in response.usage.iterations or []
)
served_by_fallback = fallback_ran and response.stop_reason != "refusal"
print(
json.dumps(
{
"stop_reason": response.stop_reason,
"model": response.model,
"served_by_fallback": served_by_fallback,
}
)
)
```
Anthropic sets safeguards for each model individually and for each policy category, in line with the model's capability: depending on the category, a flagged request may fall back to a less capable model or be declined. The `"default"` mode encodes these per-model, per-category recommendations for you, so a refused request is retried on the model Anthropic recommends for that category. Fallbacks are visible either way: the response names the model that served it, and the `fallback` content block marks the handoff.
The routing is applied server-side and is not published per model on the [Models API](../Endpoints/models-list.md). To see which model served a refused request, check the response's top-level `model` field and look for a `fallback_message` entry in `usage.iterations`, as this page's samples do.
Only a safety classifier decline triggers the fallback. A rate limit, overload, or server error on the requested model is returned to you as-is.
The beta header must carry exactly the date `2026-07-01`, which supports both `"default"` and the explicit-list form, or `2026-06-01`, which accepts only the explicit-list form. Under any other `server-side-fallback-*` value, the `fallbacks` parameter is rejected with a 400 error. If you built against an earlier preview of this feature, update the beta header and the request and response shapes together to the ones on this page.
### Naming your own fallback models
Instead of default routing, you can set `fallbacks` to a list of up to three models. When the requested model declines, the API runs the next model in the chain on the same request. Use this form when you want to control exactly which models serve refused requests, such as pinning a model your application has qualified.
Named fallback models count toward the [oversized-image check](build-with-claude-vision-coordinates.md#oversized-image-error): a request whose image block sets `"oversized_image": "error"` is checked up front against the requested model and every named fallback, is rejected if any of them would resize that image, and the rejection's reported rescale target fits them all.
The highlighted lines are the only difference from the default-routing request.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = Anthropic()
response = client.beta.messages.create(
model="claude-fable-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
fallbacks=[{"model": "claude-opus-4-8"}],
betas=["server-side-fallback-2026-07-01"],
)
print(response.model)
```
A few rules apply to the `fallbacks` list:
- Entries are tried in order. Each must be distinct from the other entries and from the requested model.
- Each entry must be one of the requested model's permitted targets. With the beta header set, that list is published as `allowed_fallback_models` on the model's entry in the [Models API](../Endpoints/models-list.md).
- Each entry names a `model` and can override `max_tokens`, `thinking`, `output_config`, and `speed` for that attempt only.
- The request must be valid as a direct request to every model named. If a fallback model does not support a feature the request uses, the API rejects the request up front.
- As with the default mode, only a safety classifier decline triggers the fallback. A rate limit, overload, or server error on the requested model is returned to you as-is.
- If a fallback model is rate limited or overloaded, the fallback attempt is not made and the preceding refusal is returned instead. The refusal's `stop_details.recommended_model` then names a model to retry directly. Size the fallback model's rate limits for the refusal volume you expect, or fallbacks degrade to refusals under load.
The response has the same shape in both modes: the model that served the turn appears in the top-level `model` field, a `fallback` content block marks the handoff, and `usage.iterations` records each attempt.
### What the response contains
The response looks like any other message, with two additions:
- The top-level `model` field reports the model that produced the returned message, whether that is the requested model or a fallback.
- A `fallback` content block marks each point in `content` where one model's output gives way to the next: `{"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}`.
- `from.model` echoes the model string you sent when the declining hop is the requested model.
- `to.model` is always the resolved ID of the model that continues.
On a refusal before any output, the `fallback` block is the first content block. For example, when default routing selects Claude Opus 4.8 for the refusal's category:
```python
{
"id": "msg_01XFUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"model": "claude-opus-4-8",
"content": [
{
"type": "fallback",
"from": { "model": "claude-fable-5" },
"to": { "model": "claude-opus-4-8" }
},
{ "type": "text", "text": "Hi! How can I help you today?" }
],
"stop_reason": "end_turn",
"stop_details": null,
"usage": {
"input_tokens": 412,
"output_tokens": 264,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0,
"iterations": [
{
"type": "message",
"model": "claude-fable-5",
"input_tokens": 535,
"output_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0
},
{
"type": "fallback_message",
"model": "claude-opus-4-8",
"input_tokens": 412,
"output_tokens": 264,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0
}
]
}
}
```
The `usage.iterations` array records every attempt. A model that declined appears as an ordinary `message` entry, and the model that served the turn appears as a `fallback_message` entry. If every model in the chain declines, the response is the last model's refusal, with a `message` entry for each earlier hop and a `fallback_message` entry for the last.
[Sticky routing](#sticky-routing) can send a later turn straight to the fallback model. Such a turn carries no `fallback` content block, because no model declined that turn. Identify it by the `fallback_message` entry in `usage.iterations`, the absence of a `message` entry for the requested model, and the response's `model` field.
### Continuing the conversation
On the next turn, send the assistant content back as you received it. After a mid-output fallback, `content` can include block types the declining model produced before the handoff. The following table covers which to keep and which to drop when you echo the turn.
| Block type | On the next turn |
|:---------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `fallback` | Keep it exactly where it appeared. The API uses its position to validate the thinking blocks around it, so a request that echoes thinking blocks from both sides of the boundary is rejected if the block is omitted or moved. |
| `text` | Keep. |
| Any block after the final `fallback` block | Keep. |
| `thinking`, `redacted_thinking`, or `connector_text` before the final `fallback` block | Drop. |
| Client-side `tool_use` before the final `fallback` block | Drop. |
| `server_tool_use` before the final `fallback` block | Keep when paired with its result. Drop when it has no matching result. |
A `connector_text` block carries narration text that some tool-using responses include between tool calls.
### Streaming
On a streaming request, the retry happens on the same stream, and nothing you have already received is invalidated. What you see depends on when the decline happens.
**When the decline happens before any output:**
- `message_start` names the fallback model, and the `fallback` block is the first content block.
- Because `message_start` waits for the fallback attempt to start, time to first byte includes the declined attempt.
**When the decline happens mid-output:**
- The open content block closes, and the `fallback` block (an ordinary `content_block_start` and `content_block_stop` pair with no deltas) marks the boundary.
- The fallback model continues from the partial output. Only the partial output's `text` blocks are passed to the fallback model as context. Other block types remain in `content`.
- `message_start` already named the requested model, so read the serving model from the `fallback` block's `to.model` and from the `fallback_message` entry in the final `message_delta`'s `usage.iterations`.
### Non-streaming responses
On a non-streaming request, a mid-output decline behaves differently: the response omits the declined model's partial output, and the fallback model answers from scratch. The result looks like a decline before any output, with the `fallback` block first. The declined attempt and its output tokens still appear in `usage.iterations`.
**Declines during tool use:** completed tool work does not block fallback. When a decline fires after server tools (for example, web search or code execution) have finished executing within a request, the fallback attempt proceeds: the completed tool results carry over, and the fallback model can keep invoking server tools. The one case that does not retry is a streaming decline that fires while a tool-use block of any type (a client tool, a server tool, or an MCP tool call) is still open on the stream: that refusal is returned directly, and if the `fallback-credit-2026-07-01` header is set it still carries a credit token redeemable by continuing the partial response. Non-streaming requests are unaffected; the API clears the partial work and retries before responding.
### Billing and rate limits
Each attempt follows the rules in [How refusals are billed](#how-refusals-are-billed), at the rates of the model that ran it. An attempt that declined before producing any output is billed only when its refusal category is billed, and its tokens are reported on its `usage.iterations` entry either way. Every attempt that produced output, including one that declined partway through its response, is billed separately. The `usage.iterations` array is the per-attempt record of what you're billed. The top-level `usage` counts describe only the attempt that produced the returned message. Tokens from different models are never summed into one field.
Every attempt that runs, including one that declined, counts against its own model's rate limits.
### Sticky routing
After a conversation falls back, the API records which model served it. Later requests for that conversation that include `fallbacks` go directly to that fallback model, without running the requested model. This avoids paying for an attempt that would predictably be declined again on every turn.
A few properties of the routing decision:
- It is retained for approximately 1 hour and is scoped to your organization.
- It is stored as a content hash of the conversation prefix plus the model that served it. The message content itself is not stored.
- It is best-effort, so your code must handle the requested model being tried again at any time.
Sticky routing applies to both streaming and non-streaming requests. On a streaming request, the routing decision is made before the stream opens, so the `message_start` event's `model` field already carries the fallback model's ID.
## Client-side fallback with the SDK middleware
Every Anthropic SDK includes a refusal-fallback middleware. You configure it once on the client with your list of fallback models. Calls through `client.beta.messages` then retry refused requests automatically, on any platform. The middleware also sends the `fallback-credit-2026-07-01` beta header on every request it handles, so retries are repriced without per-request setup.
### Setting it up
Pass `BetaRefusalFallbackMiddleware` to the client constructor, and share one `BetaFallbackState` instance across the requests of a conversation.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic import Anthropic, BetaFallbackState, BetaRefusalFallbackMiddleware
# On a refusal, the middleware retries on the listed fallback model and
# automatically sends the fallback-credit beta header on every request it handles.
client = Anthropic(
middleware=[BetaRefusalFallbackMiddleware([{"model": "claude-opus-4-8"}])],
)
state = BetaFallbackState() # pins follow-ups to the model that accepted
# Streaming: on a refusal the middleware retries on the fallback model and
# splices its events onto the open stream.
with (
state,
client.beta.messages.stream(
max_tokens=1024,
model="claude-fable-5",
messages=[{"role": "user", "content": "Hello, Claude"}],
) as stream,
):
for text in stream.text_stream:
print(text, end="", flush=True)
final_message = stream.get_final_message()
print(f"\nserved by: {final_message.model}")
# Non-streaming: reusing the state keeps the conversation pinned.
with state:
message = client.beta.messages.create(
max_tokens=1024,
model="claude-fable-5",
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(f"served by: {message.model}")
```
### How it behaves
- Retries walk your fallback list in order. A fallback model that itself refuses passes the request to the next entry.
- When every model in the list has declined, the middleware returns the final refusal (the last model's refusal response) rather than raising an error.
- Thinking blocks from Claude Fable 5.1, Claude Opus 5.5, or Claude Fable 5 pass through unchanged. Each retry re-sends your original request body, and the only blocks the middleware removes from conversation history on later requests are the `fallback` boundary blocks it added itself. The fallback model can't read Claude Fable 5.1 blocks, which are [preserved only for that model or a newer one](build-with-claude-thinking.md#preserved-for-model), so the API drops them. The API also drops Claude Opus 5.5 blocks for every fallback model except Claude Fable 5.1 and Claude Mythos 5.1 (see [Switching models mid-conversation](build-with-claude-preserved-thinking.md#switching-models)).
- Responses served through the middleware include a `fallback` content block at each model boundary, the same as server-side fallback responses. The middleware manages those blocks for you on later requests.
- The model that accepted is recorded in `BetaFallbackState`, so follow-up requests that share the state stay pinned to it rather than re-asking a model that refused.
The middleware and the server-side `fallbacks` parameter do the same job. Configure one or the other, never both on the same request. To send a server-side `fallbacks` request from an application that installs the middleware, use a separate client instance without it.
## Writing the retry yourself
Over raw HTTP or with custom retry logic, implement the pattern the middleware wraps:
1. 1
### Detect the refusal
Check the response for `stop_reason: "refusal"`.
2. 2
### Re-send on a fallback model
Send the same request with `model` set to a fallback model, such as Claude Opus 4.8. Another model can normally serve a request that Claude Fable 5.1 or Claude Fable 5 declines. How you handle the conversation history depends on whether you redeem a [fallback credit](build-with-claude-fallback-credit.md):
- **Not redeeming a credit:** you can leave the earlier `thinking` and `redacted_thinking` blocks in place or strip them to save input tokens. The fallback model normally can't use them either way: it ignores Claude Fable 5 blocks, and Claude Fable 5.1 blocks are [preserved only for that model or a newer one](build-with-claude-thinking.md#preserved-for-model), so the API drops them. The API also drops Claude Opus 5.5 blocks for every fallback model except Claude Fable 5.1 and Claude Mythos 5.1 (see [Switching models mid-conversation](build-with-claude-preserved-thinking.md#switching-models)).
- **Redeeming a credit:** send the body unchanged, because redemption requires an exact match. The server handles the earlier model's thinking blocks on a redemption, so do not strip them (see [Fields that must match the refused request](build-with-claude-fallback-credit.md#reference)).
3. 3
### Stay on the fallback model
For multi-turn conversations, keep using the fallback model for subsequent turns rather than switching back.
A manual retry writes the fallback model's prompt cache from scratch, which costs more than reading an existing cache. [Fallback credit](build-with-claude-fallback-credit.md) refunds that cost; redeem it on every retry you build yourself.
## Refusals in Message Batches
A refused request in a [Message Batch](build-with-claude-batch-processing.md) comes back as `result.type: "succeeded"` with `stop_reason: "refusal"`. Batch results carry the same `stop_details` object as synchronous responses, so you can detect refusals through either `stop_reason` or `stop_details.type`. One difference: batch refusals don't mint fallback credits, so `stop_details` on a batch result never includes a `fallback_credit_token`.
Server-side fallback is not available for batches (a batch request that includes `fallbacks` produces a per-item errored result). To retry refused batch items:
1. Collect the refused items from the results.
2. Strip the Claude Fable 5.1 or Claude Fable 5 thinking blocks from any multi-turn histories.
3. Resubmit them on a fallback model as a new batch or as direct requests.
## Common pitfalls
- **Retry on a different model.** Re-sending a refused request to the same model usually earns another refusal. Point the retry at the fallback model.
- **Budget retries per request, not per turn or per session.** A single turn can produce several refusals, for example an agent plus its sub-agents.
- **Configure fallback on every request path.** Retry handlers, error-recovery branches, and background workers all need it. A handler that re-issues a request without fallback loses the protection on exactly the requests most likely to need it.
- **Give sub-agent calls their own fallback.** The `fallbacks` parameter does not propagate into model calls made from inside tool execution.
- **Make fallback a property of the request, not of ambient state.** A shared flag, cached config value, or global toggle can drift out of sync and silently leave a request unprotected. When you cannot confirm fallback is active, configure it rather than assume it is on.
- **Instrument refusals as their own signal.** A refusal is an HTTP 200, so monitoring built on error rates or 5xx responses never sees it. Emit one event per refusal and one per fallback-served response (the `fallback_message` entry in `usage.iterations` marks the latter), then alert on the gap between the two counts.
- **Branch on `stop_reason` or `stop_details.type`, not on `content` or the inner `stop_details` fields.** The `stop_details` object is always present on a refusal, but its `category` and `explanation` fields can be `null`. Check for `stop_reason` equal to `"refusal"` directly.
## Next steps
[Fallback credit](build-with-claude-fallback-credit.md)
Avoid paying the prompt-cache cost twice when you build the retry yourself.
[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)
Every `stop_reason` value and how to handle it.
[SDK middleware](../Other/cli-sdks-libraries-middleware.md)
How SDK middleware works, including the refusal-fallback helper.
[Migration guide](../../20-Models/models-fable-5-1-migration-guide.md)
Move an existing application to Claude Fable 5.1.
---
## Search results - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/search-results
Path: 04-API-Reference/Guides/build-with-claude-search-results.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fsearch-results)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Model capabilities
# Search results
Copy page
Enable natural citations for RAG applications by providing search results with source attribution
Copy page
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
Search result content blocks let Claude cite your own content the same way it cites web search results: each citation carries the source and title you provided. Use them in RAG (Retrieval-Augmented Generation) applications where Claude needs to attribute answers to your documents.
All [active models](../../20-Models/about-claude-models-overview.md) support search results with citations, with the exception of Claude Haiku 3. No beta header is required: search results are part of the standard Messages API.
## How it works
Search results can be provided in two ways:
1. **From tool calls:** Your custom tools return search results, enabling dynamic RAG applications
2. **As top-level content:** You provide search results directly in user messages for pre-fetched or cached content
In both cases, Claude cites the search results automatically when citations are enabled. No special prompting is needed: ask your question, and citations appear on the text blocks that draw on your content.
### Search result schema
Search results use the following structure:
```python
{
"type": "search_result",
"source": "https://example.com/article", // Required: Source URL or identifier
"title": "Article Title", // Required: Title of the result
"content": [
// Required: Array of text blocks
{
"type": "text",
"text": "The actual content of the search result..."
}
],
"citations": {
// Optional: Citation configuration
"enabled": true // Enable/disable citations for this result
}
}
```
### Required fields
| Field | Type | Description |
|-----------|--------|------------------------------------------------------------------------------------------------------------------|
| `type` | string | Must be `"search_result"` |
| `source` | string | The source of the content. Any stable string works: a URL, or an internal identifier such as `kb://article-1234` |
| `title` | string | A descriptive title for the search result |
| `content` | array | An array of text blocks containing the actual content |
### Optional fields
| Field | Type | Description |
|-----------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `citations` | object | Citation configuration with `enabled` Boolean field. Citations are disabled by default; every example on this page sets `"enabled": true` explicitly. All search results in a request must use the same setting (see [Citation control](#citation-control)) |
| `cache_control` | object | Cache control settings (for example, `{"type": "ephemeral"}`) |
Each item in the `content` array must be a text block with:
- `type`: Must be `"text"`
- `text`: The actual text content (non-empty string)
Search results hold text only. Images and other media are not supported inside the `content` array.
## Method 1: Search results from tool calls
Returning search results from your custom tools enables dynamic RAG applications: tools fetch content at runtime, and Claude cites it in the response. The following example forces the tool call with [`tool_choice`](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md#forcing-tool-use), so the retrieval step runs every time.
### Example: Knowledge base tool
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.types import (
MessageParam,
TextBlockParam,
SearchResultBlockParam,
ToolResultBlockParam,
)
client = Anthropic()
# Define a knowledge base search tool
knowledge_base_tool = {
"name": "search_knowledge_base",
"description": "Search the company knowledge base for information",
"input_schema": {
"type": "object",
"properties": {"query": {"type": "string", "description": "The search query"}},
"required": ["query"],
},
}
# Function to handle the tool call
def search_knowledge_base(query):
# Your search logic here
# Returns search results in the correct format
return [
SearchResultBlockParam(
type="search_result",
source="https://docs.company.com/product-guide",
title="Product Configuration Guide",
content=[
TextBlockParam(
type="text",
text="To configure the product, navigate to Settings > Configuration. The default timeout is 30 seconds, but can be adjusted between 10-120 seconds based on your needs.",
)
],
citations={"enabled": True},
),
SearchResultBlockParam(
type="search_result",
source="https://docs.company.com/troubleshooting",
title="Troubleshooting Guide",
content=[
TextBlockParam(
type="text",
text="If you encounter timeout errors, first check the configuration settings. Common causes include network latency and incorrect timeout values.",
)
],
citations={"enabled": True},
),
]
# Build up the conversation in a list, starting with the user's question
messages = [
MessageParam(role="user", content="How do I configure the timeout settings?")
]
# Create a message with the tool
response = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
tools=[knowledge_base_tool],
tool_choice={"type": "tool", "name": "search_knowledge_base"},
messages=messages,
)
# When Claude calls the tool, provide the search results.
# The tool_use block is not always first: iterate to find it.
tool_use = next((block for block in response.content if block.type == "tool_use"), None)
if tool_use is not None:
tool_result = search_knowledge_base(tool_use.input["query"])
# Append Claude's turn, then the tool result, to the running conversation
messages.append(MessageParam(role="assistant", content=response.content))
messages.append(
MessageParam(
role="user",
content=[
ToolResultBlockParam(
type="tool_result",
tool_use_id=tool_use.id,
content=tool_result, # Search results go here
)
],
)
)
# Send the tool result back
final_response = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
messages=messages,
)
print(final_response)
```
## Method 2: Search results as top-level content
You can also provide search results directly in user messages. This is useful for:
- Pre-fetched content from your search infrastructure
- Cached search results from previous queries
- Content from external search services
- Testing and development
### Example: Direct search results
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.types import MessageParam, TextBlockParam, SearchResultBlockParam
client = Anthropic()
# Provide search results directly in the user message
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
MessageParam(
role="user",
content=[
SearchResultBlockParam(
type="search_result",
source="https://docs.company.com/api-reference",
title="API Reference - Authentication",
content=[
TextBlockParam(
type="text",
text="All API requests must include an API key in the Authorization header. Keys can be generated from the dashboard. Rate limits: 1000 requests per hour for standard tier, 10000 for premium.",
)
],
citations={"enabled": True},
),
SearchResultBlockParam(
type="search_result",
source="https://docs.company.com/quickstart",
title="Getting Started Guide",
content=[
TextBlockParam(
type="text",
text="To get started: 1) Sign up for an account, 2) Generate an API key from the dashboard, 3) Install our SDK using pip install company-sdk, 4) Initialize the client with your API key.",
)
],
citations={"enabled": True},
),
TextBlockParam(
type="text",
text="Based on these search results, how do I authenticate API requests and what are the rate limits?",
),
],
)
],
)
print(response)
```
## Claude's response with citations
Regardless of how search results are provided, Claude automatically includes citations when using information from them:
```python
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "All API requests must include an API key in the Authorization header. Keys can be generated from the dashboard.",
"citations": [
{
"type": "search_result_location",
"cited_text": "All API requests must include an API key in the Authorization header. Keys can be generated from the dashboard. Rate limits: 1000 requests per hour for standard tier, 10000 for premium.",
"source": "https://docs.company.com/api-reference",
"title": "API Reference - Authentication",
"search_result_index": 0,
"start_block_index": 0,
"end_block_index": 1
}
]
},
{
"type": "text",
"text": "\n\nTo set this up from scratch, you'll need to "
},
{
"type": "text",
"text": "sign up for an account, generate an API key from the dashboard, install the SDK using `pip install company-sdk`, and initialize the client with your API key.",
"citations": [
{
"type": "search_result_location",
"cited_text": "To get started: 1) Sign up for an account, 2) Generate an API key from the dashboard, 3) Install our SDK using pip install company-sdk, 4) Initialize the client with your API key.",
"source": "https://docs.company.com/quickstart",
"title": "Getting Started Guide",
"search_result_index": 1,
"start_block_index": 0,
"end_block_index": 1
}
]
}
]
}
```
### Citation fields
Each citation includes:
| Field | Type | Description |
|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `type` | string | Always `"search_result_location"` for search result citations |
| `source` | string | The source from the original search result |
| `title` | string or null | The title from the original search result |
| `cited_text` | string | The full text of the cited block(s), concatenated. Equals the contents of `content[start_block_index:end_block_index]` joined together. Not counted toward output tokens. |
| `search_result_index` | integer | 0-based index of the cited search result among all `search_result` blocks in the request, in the order they appear (across all messages and tool results). |
| `start_block_index` | integer | 0-based index of the first cited block in the search result's `content` array. |
| `end_block_index` | integer | Exclusive end index of the cited block range in the search result's `content` array. Always greater than `start_block_index`. |
The block indices identify a slice of the search result's `content` array, and `cited_text` is the full text of that slice. The text block is the minimal citable unit: Claude cites whole blocks, not substrings within a block. To get finer-grained citations, split your search result content into smaller blocks (see [Multiple content blocks](#multiple-content-blocks)).
## Multiple content blocks
Search results can contain multiple text blocks in the `content` array:
```python
{
"type": "search_result",
"source": "https://docs.company.com/api-guide",
"title": "API Documentation",
"content": [
{
"type": "text",
"text": "Authentication: All API requests require an API key."
},
{
"type": "text",
"text": "Rate Limits: The API allows 1000 requests per hour per key."
},
{
"type": "text",
"text": "Error Handling: The API returns standard HTTP status codes."
}
],
"citations": { "enabled": true }
}
```
A citation referencing the rate limits block looks like:
```python
{
"type": "search_result_location",
"cited_text": "Rate Limits: The API allows 1000 requests per hour per key.",
"source": "https://docs.company.com/api-guide",
"title": "API Documentation",
"search_result_index": 0,
"start_block_index": 1,
"end_block_index": 2
}
```
When this search result is cited, `start_block_index` and `end_block_index` identify which of these blocks the citation covers, and `cited_text` contains exactly those blocks' text. Splitting content into smaller, focused blocks gives Claude finer citation boundaries; combining content into one block means every citation returns the full text. This is the same model used by [custom content documents](build-with-claude-citations.md#custom-content-documents) in the Citations feature.
## Advanced usage
### Combining both methods
You can mix both methods in the same conversation. Claude cites from either source, and `search_result_index` counts all `search_result` blocks in request order, regardless of source.
The following example replays a complete conversation. The first user message carries a pre-fetched search result, the assistant turn calls a knowledge base tool, and the tool result returns a second search result. Claude's answer cites both sources:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.types import (
MessageParam,
SearchResultBlockParam,
TextBlockParam,
ToolResultBlockParam,
ToolUseBlockParam,
)
client = Anthropic()
knowledge_base_tool = {
"name": "search_knowledge_base",
"description": "Search the company knowledge base for information",
"input_schema": {
"type": "object",
"properties": {"query": {"type": "string", "description": "The search query"}},
"required": ["query"],
},
}
# Replay a conversation that provides search results both ways: the first
# user message carries a pre-fetched result, the tool result returns another
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
tools=[knowledge_base_tool],
messages=[
MessageParam(
role="user",
content=[
SearchResultBlockParam(
type="search_result",
source="https://docs.company.com/overview",
title="Product Overview",
content=[
TextBlockParam(
type="text",
text="Acme Dashboard is a monitoring tool for distributed systems. It supports real-time alerting and custom metric dashboards.",
)
],
citations={"enabled": True},
),
TextBlockParam(
type="text",
text="What does Acme Dashboard do, and what plans is it available on?",
),
],
),
MessageParam(
role="assistant",
content=[
TextBlockParam(
type="text", text="Let me check the pricing information."
),
ToolUseBlockParam(
type="tool_use",
id="toolu_01A09q90qw90lq917835lq9",
name="search_knowledge_base",
input={"query": "Acme Dashboard pricing plans"},
),
],
),
MessageParam(
role="user",
content=[
ToolResultBlockParam(
type="tool_result",
tool_use_id="toolu_01A09q90qw90lq917835lq9",
content=[
SearchResultBlockParam(
type="search_result",
source="https://docs.company.com/pricing",
title="Pricing Plans",
content=[
TextBlockParam(
type="text",
text="Acme Dashboard is available on the Starter plan at $10 per user per month and the Enterprise plan with custom pricing.",
)
],
citations={"enabled": True},
)
],
)
],
),
],
)
print(response)
```
The response cites both sources. The pre-fetched result is `search_result_index: 0` and the tool-returned result is `search_result_index: 1`, matching the order the `search_result` blocks appear in the conversation:
```python
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "Here's what I found about Acme Dashboard:\n\n**What it does:** "
},
{
"type": "text",
"text": "Acme Dashboard is a monitoring tool for distributed systems. It supports real-time alerting and custom metric dashboards.",
"citations": [
{
"type": "search_result_location",
"cited_text": "Acme Dashboard is a monitoring tool for distributed systems. It supports real-time alerting and custom metric dashboards.",
"source": "https://docs.company.com/overview",
"title": "Product Overview",
"search_result_index": 0,
"start_block_index": 0,
"end_block_index": 1
}
]
},
{
"type": "text",
"text": "\n\n**Available plans:** "
},
{
"type": "text",
"text": "Acme Dashboard is available on the Starter plan at $10 per user per month and the Enterprise plan with custom pricing.",
"citations": [
{
"type": "search_result_location",
"cited_text": "Acme Dashboard is available on the Starter plan at $10 per user per month and the Enterprise plan with custom pricing.",
"source": "https://docs.company.com/pricing",
"title": "Pricing Plans",
"search_result_index": 1,
"start_block_index": 0,
"end_block_index": 1
}
]
}
]
}
```
### Mixing with other content types
In user messages, `search_result` blocks can sit alongside any other content block. The Method 2 example pairs search results with a `text` question, and image or document blocks can join them the same way.
Tool results are stricter: if any block in a `tool_result` content array is a `search_result`, all of its blocks must be `search_result`. Mixing search results with other block types in the same tool result returns a validation error. To return supporting text alongside tool-sourced search results, include it as a text block inside one of the search results' `content` arrays, where it also becomes citable.
### Cache control
Add `cache_control` on the search result block to cache it for reuse across requests. It sits alongside `citations` on the same block:
```python
{
"type": "search_result",
"source": "https://docs.company.com/guide",
"title": "User Guide",
"content": [{ "type": "text", "text": "..." }],
"citations": { "enabled": true },
"cache_control": { "type": "ephemeral" }
}
```
See [Prompt caching](build-with-claude-prompt-caching.md) for minimum cacheable lengths and other requirements.
### Citation control
By default, citations are disabled for search results. You can enable citations by explicitly setting the `citations` configuration:
```python
{
"type": "search_result",
"source": "https://docs.company.com/guide",
"title": "User Guide",
"content": [{ "type": "text", "text": "Important documentation..." }],
"citations": {
"enabled": true // Enable citations for this result
}
}
```
When `citations.enabled` is set to `true`, Claude attaches citation references to the text blocks that draw on the search result.
Citations are all-or-nothing: either all search results in a request must have citations enabled, or all must have them disabled. Mixing search results with different citation settings results in an error.
## Best practices
### For tool-based search (Method 1)
- **Dynamic content:** Use for real-time searches and dynamic RAG applications
- **Error handling:** Return appropriate messages when searches fail
- **Result limits:** Return only the most relevant results to avoid context overflow
### For top-level search (Method 2)
- **Pre-fetched content:** Use when you already have search results
- **Batch processing:** Ideal for processing multiple search results at once
- **Testing:** Great for testing citation behavior with known content
### General best practices
1. **Structure results effectively:**
- Use clear, permanent source URLs
- Provide descriptive titles
- Break long content into logical text blocks to give Claude finer citation boundaries
2. **Maintain consistency:**
- Use consistent source formats across your application
- Ensure titles accurately reflect content
- Keep formatting consistent
3. **Handle errors gracefully:** when a search fails or returns nothing, return a plain text block describing the outcome (for example, `{"type": "text", "text": "No results found."}`) instead of raising an error: Claude explains the empty result to the user, and the conversation continues.
## Limitations
- Search result content blocks are available on Claude API, Amazon Bedrock, and Google Cloud.
- Only text content is supported within search results (no images or other media).
- `search_result` blocks can only appear in user messages (including inside tool results). Assistant messages with search results are rejected.
- When the [web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md) is enabled in the same request, citations must be enabled on all `search_result` blocks.
## Next steps
[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)
Detect and handle refusal stop reasons in streaming responses, and retry refused requests on a fallback model.
[Citations](build-with-claude-citations.md)
Ground Claude's responses in your source documents. Citations return the exact passages that support each claim, so you can verify answers and surface sources to your users.
[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)
Give Claude access to current web content with cited sources, optional dynamic filtering, and domain controls.
[Messages API reference](../Endpoints/messages-create.md)
See the complete Messages API documentation, including content block types.
[Prompt caching](build-with-claude-prompt-caching.md)
Cache search results with `cache_control` to reduce cost and latency on repeated requests.
---
## Using Agent Skills with the API - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/skills-guide
Path: 04-API-Reference/Guides/build-with-claude-skills-guide.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fskills-guide)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Skills
# Using Agent Skills with the API
Copy page
Learn how to use Agent Skills to extend Claude's capabilities through the API.
Copy page
Agent Skills extend Claude's capabilities through organized folders of instructions, scripts, and resources. This guide shows you how to use both pre-built and custom Skills with the Claude API.
For complete API reference including request/response schemas and all parameters, see:
- [Skill Management API Reference](../Endpoints/skills-list.md) - CRUD operations for Skills
- [Skill Versions API Reference](../Endpoints/skills-versions-list.md) - Version management
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
## Quick links
[Get started with Agent Skills in the API](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)
Learn how to use Agent Skills to create documents with the Claude API in under 10 minutes.
[Skill authoring best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)
Learn how to write effective Skills that Claude can discover and use successfully.
## Overview
For a detailed look at the architecture and real-world applications of Agent Skills, read the engineering blog post: [Equipping agents for the real world with Agent Skills](https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills).
Skills integrate with the Messages API through the [code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md). Whether using pre-built Skills managed by Anthropic or custom Skills you've uploaded, the integration shape is identical: both require code execution and use the same `container` structure.
### Using Skills
Skills integrate identically in the Messages API regardless of source. You specify Skills in the `container` parameter with a `skill_id`, `type`, and optional `version`, and they run in the code execution environment.
You can use Skills from two sources:
| Aspect | Anthropic Skills | Custom Skills |
|--------------------|--------------------------------------------|------------------------------------------------------------------------|
| **Type value** | `anthropic` | `custom` |
| **Skill IDs** | Short names: `pptx`, `xlsx`, `docx`, `pdf` | Generated: `skill_01AbCdEfGhIjKlMnOpQrStUv` |
| **Version format** | Date-based: `20251013` or `latest` | Version ID: `skver_01AbCdEfGhIjKlMnOpQrStUv` or `latest` |
| **Management** | Pre-built and maintained by Anthropic | Upload and manage through the [Skills API](../Endpoints/skills-create.md) |
| **Availability** | Available to all users | Private to your workspace |
Both skill sources are returned by the [List Skills endpoint](../Endpoints/skills-list.md) (use the `source` parameter to filter). The integration shape and execution environment are identical. The only difference is where the Skills come from and how they're managed.
### Prerequisites
To use Skills, you need:
1. **Claude API key** from the [Claude Console](../Other/usage-limits.md)
2. **[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)** enabled in your requests
Skills require the code execution tool, so use a model from its [model compatibility list](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md#compatibility).
------------------------------------------------------------------------
## Using Skills in Messages
### Container parameter
Skills are specified using the `container` parameter in the Messages API. You can include up to 20 Skills for each request.
The structure is identical for both Anthropic and custom Skills. Specify the required `type` and `skill_id`, and optionally include `version` to pin to a specific version:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [{"type": "anthropic", "skill_id": "pptx", "version": "latest"}]
},
messages=[
{"role": "user", "content": "Create a presentation about renewable energy"}
],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
```
### Downloading generated files
When Skills create documents (Excel, PowerPoint, PDF, Word), they return `file_id` attributes in the response. You must use the Files API to download these files.
**How it works:**
1. Skills create files during code execution.
2. The response includes a `file_id` for each created file, inside code-execution tool result blocks (see [Response format](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md#response-format)).
3. Use the Files API to download the actual file content.
4. Save locally or process as needed.
To provide input files for Skills to work on, [upload them with the Files API](build-with-claude-files.md#uploading-a-file) and reference them in your request with a [container upload block](build-with-claude-files.md#container-upload-blocks).
**Example: creating and downloading an Excel file**
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Step 1: Use a Skill to create a file
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [{"type": "anthropic", "skill_id": "xlsx", "version": "latest"}]
},
messages=[
{
"role": "user",
"content": "Create an Excel file with a simple budget spreadsheet",
}
],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
# Step 2: Extract file IDs from the response
def extract_file_ids(response):
file_ids = []
for item in response.content:
if item.type == "bash_code_execution_tool_result":
content_item = item.content
if content_item.type == "bash_code_execution_result":
# each content item is a bash_code_execution_output block carrying a file_id
for file in content_item.content:
file_ids.append(file.file_id)
return file_ids
# Step 3: Download the file using Files API
for file_id in extract_file_ids(response):
file_metadata = client.files.retrieve_metadata(file_id=file_id)
file_content = client.files.download(file_id=file_id)
# Step 4: Save to disk
file_content.write_to_file(file_metadata.filename)
print(f"Downloaded: {file_metadata.filename}")
```
**Additional Files API operations:**
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
file_id = "file_011CNha8iCJcU1wXNR6q4V8w"
# Get file metadata
file_info = client.files.retrieve_metadata(file_id=file_id)
print(f"Filename: {file_info.filename}, Size: {file_info.size_bytes} bytes")
# List all files
for file in client.files.list():
print(f"{file.filename} - {file.created_at}")
# Delete a file
client.files.delete(file_id=file_id)
```
For complete details, see [Files API](build-with-claude-files.md).
### Multi-turn conversations
The response's `container` object carries the container's `id` and `expires_at` timestamp (see [Container reuse](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md#container-reuse) for lifetime details). Reuse the same container across multiple messages by specifying the container ID:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# First request creates container
response1 = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [{"type": "anthropic", "skill_id": "xlsx", "version": "latest"}]
},
messages=[
{"role": "user", "content": "Create a sample sales dataset and analyze it"}
],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
# Continue conversation with same container
messages = [
{"role": "user", "content": "Create a sample sales dataset and analyze it"},
{
# Carry the assistant's text forward; container.id carries the execution state
"role": "assistant",
"content": "\n".join(
block.text for block in response1.content if block.type == "text"
),
},
{"role": "user", "content": "What was the total revenue?"},
]
response2 = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"id": response1.container.id, # Reuse container
"skills": [{"type": "anthropic", "skill_id": "xlsx", "version": "latest"}],
},
messages=messages,
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
```
### Long-running operations
Skills may perform operations that require multiple turns. Handle `pause_turn` stop reasons:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Generate and process a large sample dataset"}]
max_retries = 10
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
}
]
},
messages=messages,
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
# Handle pause_turn for long operations
for _ in range(max_retries):
if response.stop_reason != "pause_turn":
break
messages.append({"role": "assistant", "content": response.content})
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"id": response.container.id,
"skills": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
}
],
},
messages=messages,
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
```
The response may include a `pause_turn` stop reason, which indicates that the API paused a long-running Skill operation. You can provide the response back as-is in a subsequent request to let Claude continue its turn, or modify the content if you want to interrupt the conversation and provide additional guidance.
### Using multiple Skills
Combine multiple Skills in a single request to handle complex workflows:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [
{"type": "anthropic", "skill_id": "xlsx", "version": "latest"},
{"type": "anthropic", "skill_id": "pptx", "version": "latest"},
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
},
]
},
messages=[
{"role": "user", "content": "Analyze sales data and create a presentation"}
],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
```
------------------------------------------------------------------------
## Managing custom Skills
**Custom Skills are accessible to your entire workspace, not scoped to an end user, conversation, or session.** Any API key with access to a workspace can read, invoke, and delete every custom Skill uploaded to that workspace. Every service account, and every user whose organization role allows API access, can use the Default Workspace in addition to any workspace you add them to, so keep Skills that must stay separate in their own [workspace](../Other/manage-claude-workspaces.md#api-keys-and-resource-scoping) and access them only with keys scoped to that workspace.
If you are building a multi-tenant platform on the Skills API, create a separate [workspace](../Other/manage-claude-workspaces.md) for each tenant. The workspace is the isolation boundary for custom Skills, so a workspace per tenant gives each tenant's Skills hard isolation from every other tenant. Each organization can have up to 100 workspaces by default (see [How workspaces work](../Other/manage-claude-workspaces.md#how-workspaces-work)); if you need more for tenant isolation, contact your account team.
### Creating a Skill
A Skill bundle is a directory containing a `SKILL.md` file at the top level with `name` and `description` YAML frontmatter, plus any supporting scripts or resources. See [Get started with Agent Skills in the API](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md) to author one, and the **Requirements** list following the examples for the full constraints.
Upload your custom Skill to make it available in your workspace. You can upload a zip archive or individual file objects. The Python SDK also provides a `files_from_dir` helper that accepts a directory path, and the CLI's `ant apply` uploads the directory itself.
Files are identified by the filename you attach (the `;filename=` suffix in the cURL example and the filename arguments in the SDK examples). For the walkthrough's skill, create a zip with `zip -r financial_skill.zip financial_skill/` and substitute it for the `example_skill.zip` placeholder in the zip-upload options.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
ant apply financial_skill
```
financial_skill/SKILL.md
```python
---
name: financial-skill
description: Docs example skill.
---
```
financial_skill/analyze.py
```python
print("financial analysis helper")
```
**Requirements:**
- Must include a `SKILL.md` file at the upload root (or at the top of a single enclosing folder)
- `display_name` is optional: when omitted, it derives from the `SKILL.md` `name`; an explicit value may be up to 255 characters and does not need to be unique within the workspace
- Total upload size must be under 30 MB (uncompressed)
- YAML frontmatter requirements:
- `name`: Maximum 64 characters, lowercase letters/numbers/hyphens only, no XML tags, no reserved words ("anthropic", "claude")
- `description`: Maximum 1024 characters, non-empty, no XML tags
For complete request/response schemas, see the [Create Skill API reference](../Endpoints/skills-create.md).
### Listing Skills
Retrieve all Skills available to your workspace, including both Anthropic pre-built Skills and your custom Skills. Use the `source` parameter to filter by skill type:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# List all Skills
for skill in client.skills.list():
print(f"{skill.id}: {skill.display_name} (source: {skill.source.type})")
# List only custom Skills
custom_skills = client.skills.list(source="custom")
```
See the [List Skills API reference](../Endpoints/skills-list.md) for pagination and filtering options.
### Retrieving a Skill
Get details about a specific Skill:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
skill = client.skills.retrieve(skill_id="skill_01AbCdEfGhIjKlMnOpQrStUv")
print(f"Skill: {skill.display_name}")
print(f"Latest version: {skill.latest_version_id}")
print(f"Created: {skill.created_at}")
```
### Deleting a Skill
Deleting a Skill also removes all of its versions.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
client.skills.delete(skill_id="skill_01AbCdEfGhIjKlMnOpQrStUv")
```
### Versioning
Skills support versioning to manage updates safely:
**Anthropic Skills:**
- Versions use date format: `20251013`
- New versions released as updates are made
- Specify exact versions for stability
**Custom Skills:**
- Auto-generated version IDs: `skver_01AbCdEfGhIjKlMnOpQrStUv`
- Use `"latest"` to always get the most recent version
- Create new versions when updating Skill files
A new version is a complete snapshot, not a delta: upload the Skill's full file set each time. Files you omit are not carried over, and the `name` in the new version's `SKILL.md` must match the Skill's existing name. The following examples re-upload the complete `financial_skill/` bundle from [Creating a Skill](#creating-a-skill).
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from anthropic.lib import files_from_dir
client = anthropic.Anthropic()
# Create a new version
new_version = client.skills.versions.create(
skill_id="skill_01AbCdEfGhIjKlMnOpQrStUv",
files=files_from_dir("financial_skill"),
)
# Use specific version
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": new_version.id,
}
]
},
messages=[{"role": "user", "content": "Use updated Skill"}],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
# Use latest version
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
}
]
},
messages=[{"role": "user", "content": "Use latest Skill version"}],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
```
See the [Create Skill Version API reference](../Endpoints/skills-versions-create.md) for complete details.
------------------------------------------------------------------------
## How Skills are loaded
When you specify Skills in a container:
1. **Metadata discovery:** Claude sees metadata for each Skill (name, description) in the system prompt.
2. **File loading:** Skill files are copied into the container at `/skills/{skill-name}/`. The directory is the Skill's name (`pptx` for an Anthropic Skill, the `SKILL.md` `name` for a custom Skill), not its `skill_01...` ID.
3. **Automatic use:** Claude automatically loads and uses Skills when relevant to your request.
4. **Composition:** Multiple Skills compose together for complex workflows.
Claude loads full Skill instructions only when needed.
------------------------------------------------------------------------
## Use cases
Skills fit both organizational and personal work. Organizations use them to apply brand formatting to documents, structure notes and reports around company templates, and run company-specific analytical procedures. Individuals use them for custom document templates, specialized data pipelines, and code generation or deployment conventions.
### Example: financial modeling
Combine Excel and custom DCF analysis Skills. First, create the custom DCF analysis Skill:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
ant apply dcf_skill
```
Then use it with the Excel Skill to create a financial model. Pass the ID of the Skill you created as the custom Skill's `skill_id`:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Custom DCF analysis Skill (ID obtained from Skills API create response)
dcf_skill_id = "skill_01AbCdEfGhIjKlMnOpQrStUv"
# Use with Excel to create financial model
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [
{"type": "anthropic", "skill_id": "xlsx", "version": "latest"},
{"type": "custom", "skill_id": dcf_skill_id, "version": "latest"},
]
},
messages=[
{
"role": "user",
"content": "Build a DCF valuation model for a SaaS company",
}
],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
print(response)
```
------------------------------------------------------------------------
## Limits and constraints
### Request limits
- **Maximum Skills per request:** 20
- **Maximum Skill upload size:** 30 MB (all files combined, uncompressed)
- **YAML frontmatter requirements:**
- `name`: Maximum 64 characters, lowercase letters/numbers/hyphens only, no XML tags, no reserved words ("anthropic", "claude")
- `description`: Maximum 1024 characters, non-empty, no XML tags
### Environment constraints
Skills run in the code execution container with these limitations:
- **No network access:** Cannot make external API calls
- **No runtime package installation:** Only pre-installed packages available
- **Isolated environment:** A fresh container is created unless you specify an existing container ID
See [Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md) for available packages.
------------------------------------------------------------------------
## Best practices
### When to use multiple Skills
Combine Skills when tasks involve multiple document types or domains:
**Good use cases:**
- Data analysis (Excel) + presentation creation (PowerPoint)
- Report generation (Word) + export to PDF
- Custom domain logic + document generation
**Avoid:**
- Including unused Skills (impacts performance)
### Version management strategy
The SDK tabs in this section show the `container` value to include in a Messages request. The cURL and CLI tabs show the full request.
**For production:** pin a specific version, so Skill updates never change your deployed behavior. If you omit `version` or set it to `"latest"`, requests use the newest version of the Skill, so a version uploaded by anyone in the [workspace](#workspace-scoped-access) immediately changes what your production agents run. The version ID comes from the create-version response in [Versioning](#versioning) or from the [List Skill Versions API](../Endpoints/skills-versions-list.md). The ID is always a string, so quote it in JSON or YAML even when it looks numeric.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
# Pin to specific versions for stability
container = {
"skills": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "skver_01AbCdEfGhIjKlMnOpQrStUv",
}
]
}
```
**For development:** use `latest` to pick up the newest version automatically as you iterate.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
# Use latest for active development
container = {
"skills": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
}
]
}
```
### Prompt caching considerations
If you use [Prompt caching](build-with-claude-prompt-caching.md), changing the Skills list in your container breaks the cache. Skills render into the system prompt in a fixed order, so the same list produces the same cacheable prefix:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Skills render into the system prompt in a fixed, cache-friendly order
response1 = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [{"type": "anthropic", "skill_id": "xlsx", "version": "latest"}]
},
messages=[{"role": "user", "content": "Analyze sales data"}],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
# Changing the Skills list ([xlsx] vs [xlsx, pptx]) changes the prefix: a cache miss, while an identical list is a cache hit
response2 = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [
{"type": "anthropic", "skill_id": "xlsx", "version": "latest"},
{
"type": "anthropic",
"skill_id": "pptx",
"version": "latest",
}, # prefix change: cache miss
]
},
messages=[{"role": "user", "content": "Create a presentation"}],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
```
For best caching performance, keep your Skills list, including its order, consistent across requests. Pinning custom Skill versions also helps: with `"latest"`, publishing a new version can invalidate the cached prefix if it changes the Skill's description.
### Error handling
Handle Skill-related errors gracefully:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
try:
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
container={
"skills": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
}
]
},
messages=[{"role": "user", "content": "Process data"}],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
except anthropic.BadRequestError as e:
if "skill" in str(e):
print(f"Skill error: {e}")
# Handle skill-specific errors
else:
raise
```
------------------------------------------------------------------------
## Migrate from `skills-2025-10-02`
The Skills API is out of beta and needs no beta header. Migrating off `skills-2025-10-02` is optional: requests that still send it keep working and keep returning the beta response shapes, so an existing integration keeps working until you change it. Removing the header switches those requests to the shapes documented on this page:
| | With `skills-2025-10-02` | Without the header |
|---------------------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
| Skill label | `display_title` (up to 64 characters, unique per workspace) | `display_name` (up to 255 characters, not unique); derived from the `SKILL.md` `name` when omitted |
| Newest version pointer | `latest_version`, an epoch-microsecond string such as `"1759178010641129"` | `latest_version_id`, a version ID such as `"skver_01AbCdEfGhIjKlMnOpQrStUv"`; `GET /v1/skills/{skill_id}/versions/latest` resolves it in one call |
| Version identifier in URLs | Epoch-microsecond string | Version ID (`skver_...`). IDs captured under the beta with the `skill_version_` prefix are accepted as input. |
| Version object | Includes `directory` (always equal to the Skill `name`) | No `directory` field |
| `source` | A string, `"custom"` or `"anthropic"` | An object, for example `{"type": "custom"}`; the example catalog value is `"anthropic_example"` |
| List responses | `{ data, has_more, next_page }` | `{ data, next_page }`; `limit` from 1 to 1,000 (default 20) |
| Versions list order | Oldest first | Newest first, default `limit` 20. Page cursors from one shape are not valid on the other. |
| Deleting a Skill | Returns a 400 error while any version exists | Deletes the Skill and all of its versions |
| Deleting a Skill's only version | Allowed, leaving a Skill with no versions | Returns a 400 error; upload a replacement version first, or delete the Skill |
| Upload layout | Files must sit inside a top-level directory whose name matches the Skill `name` | `SKILL.md` may sit at the root of the upload; stored paths are the same either way |
| Response types | `CreateSkillResponse`, `GetSkillResponse`, and one type per operation | `Skill`, `SkillVersion`, `DeletedSkill`, `DeletedSkillVersion` |
To migrate:
1. **Remove the beta header.** Drop `anthropic-beta: skills-2025-10-02` from your requests. In the SDKs, call `client.skills` instead of `client.beta.skills`; keeping `client.beta.skills` works only on the [SDK releases that no longer send the header](#sdk-beta-namespace). Earlier releases send it from `client.beta.skills` even with no `betas` argument.
2. **Rename fields** in your code: `display_title` to `display_name`, `latest_version` to `latest_version_id`, and read `source.type` instead of comparing `source` to a string.
3. **Use version IDs.** Wherever you stored an epoch-microsecond version, store the version's `id` instead, or use `latest`. Skill references in Messages requests accept a version ID, `latest`, or (for Anthropic Skills) the catalog version.
4. **Review delete calls.** `DELETE /v1/skills/{skill_id}` now removes every version with the Skill. If you relied on the beta's refusal as a safeguard, add your own check.
After migrating, `client.skills.delete(skill_id)` and `client.beta.skills.delete(skill_id)` delete the Skill together with all of its versions in one call.
A Skill whose versions were all deleted under the beta has no current version to return: `GET /v1/skills/{skill_id}` returns a 400 error and the Skill is omitted from list responses until you upload a version to it. You can still delete it.
### SDK beta namespace
Starting with Python SDK 1.2.0, TypeScript SDK 0.122.0, Go SDK 1.68.0, Java SDK 2.59.0, Ruby SDK 1.67.0, and C# SDK 12.44.0, `client.beta.skills` no longer sends `skills-2025-10-02` and returns the same shapes as `client.skills`, with `Beta`-prefixed type names (`BetaSkill`, `BetaSkillVersion`, `BetaDeletedSkill`, `BetaDeletedSkillVersion`). It accepts a `betas` argument for Skills features that are still in beta. In the beta Messages types, the container Skill reference type is renamed from `BetaSkill` to `BetaContainerSkill` (same fields: `type`, `skill_id`, `version`); `BetaSkill` now names the Skill resource, matching `Skill` and `ContainerSkill` in the non-beta types. Earlier SDK releases are typed to the beta shapes; if you depend on those types, stay on an earlier release until you migrate.
## Data retention
Agent Skills are not covered by ZDR arrangements. Skill definitions and execution data are retained according to Anthropic's standard data retention policy.
For ZDR eligibility across all features, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
## Audit logging
If your organization has the [Compliance API](../Other/manage-claude-compliance-api.md) enabled, its [Activity Feed](../Other/manage-claude-compliance-activity-feed.md) records the creation and deletion of Skills and Skill versions made with a Claude API key or from the Claude Console. Operations that occur while the Compliance API is off are not recorded and cannot be recovered later, so [set up the Compliance API](../Other/manage-claude-compliance-api-access.md) before you rely on this audit trail.
## Next steps
[API reference](../Endpoints/skills-create.md)
Complete API reference with all endpoints
[Skill authoring best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)
Learn how to write effective Skills that Claude can discover and use successfully.
[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)
Run Python and bash code in a sandboxed container to analyze data, generate files, and iterate on solutions.
---
## Streaming messages - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/streaming
Path: 04-API-Reference/Guides/build-with-claude-streaming.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fstreaming)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Model capabilities
# Streaming messages
Copy page
Stream Messages API responses incrementally with server-sent events, including text, tool use, and extended thinking deltas.
Copy page
When creating a Message, you can set `"stream": true` to incrementally stream the response using [server-sent events](https://developer.mozilla.org/en-US/Web/API/Server-sent%5Fevents/Using%5Fserver-sent%5Fevents) (SSE).
## Streaming with SDKs
The [Python SDK](https://github.com/anthropics/anthropic-sdk-python) and [TypeScript SDK](https://github.com/anthropics/anthropic-sdk-typescript) offer multiple ways of streaming. The [PHP SDK](https://github.com/anthropics/anthropic-sdk-php) provides streaming through `createStream()`. The Python SDK allows both sync and async streams. See the documentation in each SDK for details.
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
with client.messages.stream(
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
model="claude-opus-5-5",
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
```
## Get the final message without handling events
If you don't need to process text as it arrives, the SDKs provide a way to use streaming internally while returning the complete `Message` object, identical to what `.create()` returns. This is especially useful for requests with large `max_tokens` values, where the SDKs require streaming to avoid HTTP timeouts.
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
with client.messages.stream(
max_tokens=128000,
messages=[{"role": "user", "content": "Write a detailed analysis..."}],
model="claude-opus-5-5",
) as stream:
message = stream.get_final_message()
for block in message.content:
if block.type == "text":
print(block.text)
```
The `.stream()` call keeps the HTTP connection alive with server-sent events, then `.get_final_message()` (Python) or `.finalMessage()` (TypeScript) accumulates all events and returns the complete `Message` object. In Go, you call `message.Accumulate(event)` inside the stream loop to build the same complete `Message`. In Java, use `MessageAccumulator.create()` and call `accumulator.accumulate(event)` on each event. In C#, await the stream's `.Aggregate()` extension method to get the complete `Message`, or pass a `MessageContentAggregator` to `.CollectAsync()` to aggregate while handling events. In Ruby, call `.accumulated_message` on the stream. In the PHP SDK, you iterate over stream events manually to accumulate the response.
## Event types
Each server-sent event includes a named event type and associated JSON data. Each event uses an SSE event name (for example, `event: message_stop`), and includes the matching event `type` in its data.
Each stream uses the following event flow:
1. `message_start`: contains a `Message` object with empty `content`. Under the [`thinking-binding-controls-2026-08-01`](build-with-claude-thinking.md#preserved-thinking-controls) beta header, this `Message` object also carries the `input_transformations` array. After a mid-stream [server-side fallback](build-with-claude-refusals-and-fallback.md#server-side-fallback), the final `message_delta` event carries the array again with the serving model's entries.
2. A series of content blocks, each of which has a `content_block_start`, one or more `content_block_delta` events, and a `content_block_stop` event. Each content block has an `index` that corresponds to its index in the final Message `content` array. One exception: during [server-side fallback](build-with-claude-refusals-and-fallback.md#server-side-fallback) responses, a `fallback` content block arrives at each model boundary as a `content_block_start` and `content_block_stop` pair with no deltas in between.
3. One or more `message_delta` events, indicating top-level changes to the final `Message` object.
4. A final `message_stop` event.
The token counts shown in the `usage` field of the `message_delta` event are *cumulative*.
### Ping events
Event streams may also include any number of `ping` events.
### Error events
The API may occasionally send [errors](../Endpoints/errors.md) in the event stream. For example, during periods of high usage, you may receive an `overloaded_error`, which would normally correspond to an HTTP 529 in a non-streaming context:
Example error
```python
event: error
data: {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}
```
### Other events
In accordance with the [versioning policy](../Endpoints/versioning.md), new event types may be added, and your code should handle unknown event types gracefully.
## Content block delta types
Each `content_block_delta` event contains a `delta` of a type that updates the `content` block at a given `index`.
### Text delta
A `text` content block delta looks like:
Text delta
```python
event: content_block_delta
data: {"type": "content_block_delta","index": 0,"delta": {"type": "text_delta", "text": "ello frien"}}
```
### Input JSON delta
The deltas for `tool_use` content blocks correspond to updates for the `input` field of the block. To support maximum granularity, the deltas are *partial JSON strings*, whereas the final `tool_use.input` is always an *object*.
You can accumulate the string deltas and parse the JSON once you receive a `content_block_stop` event, by using a library like [Pydantic](https://docs.pydantic.dev/latest/concepts/json/#partial-json-parsing) to do partial JSON parsing, or by using the [SDKs](../Other/cli-sdks-libraries-overview.md), which provide helpers to access parsed incremental values.
A `tool_use` content block delta looks like:
Input JSON delta
```python
event: content_block_delta
data: {"type": "content_block_delta","index": 1,"delta": {"type": "input_json_delta","partial_json": "{\"location\": \"San Fra"}}}
```
Note: Current models only support emitting one complete key and value property from `input` at a time. As such, when using tools, there may be delays between streaming events while the model is working. Once an `input` key and value are accumulated, they are emitted as multiple `content_block_delta` events with chunked partial JSON so that the format can automatically support finer granularity in future models.
### Thinking delta
When using [thinking](build-with-claude-thinking.md#streaming-thinking) with streaming enabled, you'll receive thinking content through `thinking_delta` events. These deltas correspond to the `thinking` field of the `thinking` content blocks.
For thinking content, a special `signature_delta` event is sent just before the `content_block_stop` event. This signature is used to verify the integrity of the thinking block.
When `display: "omitted"` is set on the thinking configuration, no thinking text is streamed. The thinking block opens, receives a `thinking_delta` with an empty `thinking` string and then a single `signature_delta`, and closes. With `display: "updates"` (beta), reasoning blocks stream the same way, and only the [progress updates](build-with-claude-thinking.md#progress-updates) that some models write between tool calls stream `thinking_delta` events that carry text. See [Controlling thinking display](build-with-claude-thinking.md#controlling-thinking-display).
A typical thinking delta looks like:
Thinking delta
```python
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "I need to find the GCD of 1071 and 462 using the Euclidean algorithm.\n\n1071 = 2 × 462 + 147"}}
```
The signature delta looks like:
Signature delta
```python
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "signature_delta", "signature": "EqQBCgIYAhIM1gbcDa9GJwZA2b3hGgxBdjrkzLoky3dl1pkiMOYds..."}}
```
## Full HTTP stream response
Use the [client SDKs](../Other/cli-sdks-libraries-overview.md) when using streaming mode. However, if you are building a direct API integration, you need to handle these events yourself.
A stream response consists of:
1. A `message_start` event
2. Potentially multiple content blocks, each of which contains:
- A `content_block_start` event
- Potentially multiple `content_block_delta` events
- A `content_block_stop` event
3. One or more `message_delta` events
4. A `message_stop` event
There may be `ping` events dispersed throughout the response as well. See [Event types](#event-types) for more details on the format.
### Basic streaming request
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-5-5",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=256,
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
```
Response
```python
event: message_start
data: {"type": "message_start", "message": {"id": "msg_1nZdL29xx5MUA1yADyHTEsnR8uuvGzszyY", "type": "message", "role": "assistant", "content": [], "model": "claude-opus-5-5", "stop_reason": null, "stop_sequence": null, "usage": {"input_tokens": 25, "output_tokens": 1}}}
event: content_block_start
data: {"type": "content_block_start", "index": 0, "content_block": {"type": "text", "text": ""}}
event: ping
data: {"type": "ping"}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta", "text": "Hello"}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta", "text": "!"}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 0}
event: message_delta
data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence":null}, "usage": {"output_tokens": 15}}
event: message_stop
data: {"type": "message_stop"}
```
### Streaming request with tool use
Tool use supports [fine-grained streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md) for parameter values. Enable it per tool with `eager_input_streaming`.
This request asks Claude to use a tool to report the weather.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
tools = [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
},
}
]
with client.messages.stream(
model="claude-opus-5",
max_tokens=1024,
tools=tools,
tool_choice={"type": "any"},
messages=[
{"role": "user", "content": "What is the weather like in San Francisco?"}
],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
```
Response
```python
event: message_start
data: {"type":"message_start","message":{"id":"msg_014p7gG3wDgGV9EUtLvnow3U","type":"message","role":"assistant","model":"claude-opus-5","stop_sequence":null,"usage":{"input_tokens":472,"output_tokens":2},"content":[],"stop_reason":null}}
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
event: ping
data: {"type": "ping"}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Okay"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":","}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" let"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"'s"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" check"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" weather"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" San"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Francisco"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":","}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" CA"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":":"}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_01T1x1fJ34qAmk2tNTrN7Up6","name":"get_weather","input":{}}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"location\":"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" \"San"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" Francisc"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"o,"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" CA\"}"}}
event: content_block_stop
data: {"type":"content_block_stop","index":1}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"output_tokens":89}}
event: message_stop
data: {"type":"message_stop"}
```
### Streaming request with thinking
This request enables thinking with streaming. The `display: "summarized"` setting streams a condensed summary of Claude's reasoning rather than the full chain of thought.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-5-5",
max_tokens=20000,
thinking={"type": "adaptive", "display": "summarized"},
messages=[
{
"role": "user",
"content": "What is the greatest common divisor of 1071 and 462?",
}
],
) as stream:
for event in stream:
if event.type == "content_block_delta":
delta = event.delta
match delta.type:
case "thinking_delta":
print(delta.thinking, end="", flush=True)
case "text_delta":
print(delta.text, end="", flush=True)
```
Response
```python
event: message_start
data: {"type": "message_start", "message": {"id": "msg_01...", "type": "message", "role": "assistant", "content": [], "model": "claude-opus-5-5", "stop_reason": null, "stop_sequence": null}}
event: content_block_start
data: {"type": "content_block_start", "index": 0, "content_block": {"type": "thinking", "thinking": "", "signature": ""}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "I need to find the GCD of 1071 and 462 using the Euclidean algorithm.\n\n1071 = 2 × 462 + 147"}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\n462 = 3 × 147 + 21"}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\n147 = 7 × 21 + 0"}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\nThe remainder is 0, so GCD(1071, 462) = 21."}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "signature_delta", "signature": "EqQBCgIYAhIM1gbcDa9GJwZA2b3hGgxBdjrkzLoky3dl1pkiMOYds..."}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 0}
event: content_block_start
data: {"type": "content_block_start", "index": 1, "content_block": {"type": "text", "text": ""}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 1, "delta": {"type": "text_delta", "text": "The greatest common divisor of 1071 and 462 is **21**."}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 1}
event: message_delta
data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence": null}}
event: message_stop
data: {"type": "message_stop"}
```
### Streaming request with web search tool use
This request asks Claude to search the web for current weather information.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-5-5",
max_tokens=1024,
tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 5}],
messages=[
{"role": "user", "content": "What is the weather like in New York City today?"}
],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
```
Response
```python
event: message_start
data: {"type":"message_start","message":{"id":"msg_01G...","type":"message","role":"assistant","model":"claude-opus-5-5","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":2679,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":3}}}
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"I'll check"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the current weather in New York City for you"}}
event: ping
data: {"type": "ping"}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"."}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"server_tool_use","id":"srvtoolu_014hJH82Qum7Td6UV8gDXThB","name":"web_search","input":{}}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"query"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"\":"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" \"weather"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" NY"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"C to"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"day\"}"}}
event: content_block_stop
data: {"type":"content_block_stop","index":1 }
event: content_block_start
data: {"type":"content_block_start","index":2,"content_block":{"type":"web_search_tool_result","tool_use_id":"srvtoolu_014hJH82Qum7Td6UV8gDXThB","content":[{"type":"web_search_result","title":"Weather in New York City in May 2025 (New York) - detailed Weather Forecast for a month","url":"https://world-weather.info/forecast/usa/new_york/may-2025/","encrypted_content":"Ev0DCioIAxgCIiQ3NmU4ZmI4OC1k...","page_age":null},...]}}
event: content_block_stop
data: {"type":"content_block_stop","index":2}
event: content_block_start
data: {"type":"content_block_start","index":3,"content_block":{"type":"text","text":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":"Here's the current weather information for New York"}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":" City:\n\n# Weather"}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":" in New York City"}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":"\n\n"}}
...
event: content_block_stop
data: {"type":"content_block_stop","index":17}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":10682,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":510,"server_tool_use":{"web_search_requests":1}}}
event: message_stop
data: {"type":"message_stop"}
```
## Error recovery
### Claude 4.5 and earlier
For Claude 4.5 models and earlier, you can recover a streaming request that was interrupted because of network issues, timeouts, or other errors by resuming from where the stream was interrupted. This approach saves you from re-processing the entire response.
The basic recovery strategy involves:
1. **Capture the partial response:** Save all content that was successfully received before the error occurred.
2. **Construct a continuation request:** Create a new API request that includes the partial assistant response as the beginning of a new assistant message.
3. **Resume streaming:** Continue receiving the rest of the response from where it was interrupted.
### Claude 4.6 and later
For Claude 4.6 and later models, the same capture-and-resume strategy applies, but step 2 changes: instead of placing the partial response in an assistant message, add a user message that instructs the model to continue from where it left off.
1. **Capture the partial response:** Save all content that was successfully received before the error occurred.
2. **Construct a continuation request:** Create a new API request with a user message containing the partial response and an instruction to continue, for example:
Sample prompt
``` block
Your previous response was interrupted and ended with [previous_response]. Continue from where you left off.
```
3. **Resume streaming:** Continue receiving the rest of the response from where it was interrupted.
### Error recovery best practices
1. **Use SDK features:** Leverage the SDK's built-in message accumulation and error handling capabilities.
2. **Handle content types:** Be aware that messages can contain multiple content blocks (`text`, `tool_use`, `thinking`). Tool use and extended thinking blocks cannot be partially recovered. You can resume streaming from the most recent text block.
## Next steps
[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)
Handle each `stop_reason` value once a stream completes.
[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Stream tool input JSON without server-side buffering for lower latency.
[Thinking](build-with-claude-thinking.md)
Stream thinking output with `thinking_delta` and `signature_delta` events.
[Client SDKs](../Other/cli-sdks-libraries-overview.md)
Use the official SDKs, which handle streaming, accumulation, and reconnection for you.
[Batch processing](build-with-claude-batch-processing.md)
Process large volumes of requests asynchronously when you don't need real-time responses.
---
## Structured outputs - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/structured-outputs
Path: 04-API-Reference/Guides/build-with-claude-structured-outputs.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fstructured-outputs)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Model capabilities
# Structured outputs
Copy page
Get validated JSON results from agent workflows
Copy page
Structured outputs
[ZDR](../Other/manage-claude-api-and-data-retention.md)
Eligible
excludes [Covered Models](../Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements)
Structured outputs constrain Claude's responses to follow a specific schema, ensuring valid, parseable output for downstream processing. Structured outputs provide two complementary features:
- **JSON outputs** (`output_config.format`): Get Claude's response in a specific JSON format
- **Strict tool use** (`strict: true`): Guarantee schema validation on tool names and inputs
You can use these features independently or together in the same request.
**Migrating from beta?** The `output_format` parameter has moved to `output_config.format`, and beta headers are no longer required. The `output_format` parameter is deprecated and will be removed in the future. To use it anyway, add the `structured-outputs-2025-11-13` beta header. Without it, the API returns a 400 error. The Python SDK (v1.0 and later) does not accept `output_format={...}` on `client.beta.messages.create()` or `count_tokens()` and raises a `TypeError`; use `output_config` instead. See the following code examples for the updated API shape.
## Why use structured outputs
Without structured outputs, Claude can generate malformed JSON responses or invalid tool inputs that break your applications. Even with careful prompting, you may encounter:
- Parsing errors from invalid JSON syntax
- Missing required fields
- Inconsistent data types
- Schema violations requiring error handling and retries
Structured outputs guarantee schema-compliant responses through constrained decoding:
- **Always valid:** No more `JSON.parse()` errors
- **Type safe:** Guaranteed field types and required fields
- **Reliable:** No retries needed for schema violations
## JSON outputs
JSON outputs control Claude's response format, ensuring Claude returns valid JSON matching your schema. Use JSON outputs when you need to:
- Control Claude's response format
- Extract data from images or text
- Generate structured reports
- Format API responses
### Quick start
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Extract the key information from this email: John Smith (john@example.com) is interested in our Enterprise plan and wants to schedule a demo for next Tuesday at 2pm.",
}
],
output_config={
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
"plan_interest": {"type": "string"},
"demo_requested": {"type": "boolean"},
},
"required": ["name", "email", "plan_interest", "demo_requested"],
"additionalProperties": False,
},
}
},
)
print(next(block.text for block in response.content if block.type == "text"))
```
**Response format:** Valid JSON matching your schema in the response's text content block
Output
```python
{
"name": "John Smith",
"email": "john@example.com",
"plan_interest": "Enterprise",
"demo_requested": true
}
```
### How it works
1. 1
### Define your JSON schema
Create a JSON schema that describes the structure you want Claude to follow. The schema uses standard JSON Schema format with some limitations (see [JSON Schema limitations](#json-schema-limitations)).
2. 2
### Add the output_config.format parameter
Include the `output_config.format` parameter in your API request with `type: "json_schema"` and your schema definition.
3. 3
### Parse the response
Claude's response is valid JSON matching your schema, returned in the response's text content block.
### Working with JSON outputs in SDKs
The SDKs provide helpers that make it easier to work with JSON outputs, including schema transformation, automatic validation, and integration with popular schema libraries.
The Python SDK's `client.messages.parse()` still accepts `output_format` as a convenience parameter and translates it to `output_config.format` internally. Other SDKs require `output_config` directly. The following examples show the SDK helper syntax.
#### Using native schema definitions
Instead of writing raw JSON schemas, you can use familiar schema definition tools in your language:
- **Python:** [Pydantic](https://docs.pydantic.dev/) models with `client.messages.parse()`
- **TypeScript:** [Zod](https://zod.dev/) schemas with `zodOutputFormat()` or typed JSON Schema literals with `jsonSchemaOutputFormat()`
- **Java:** Plain Java classes with automatic schema derivation through `outputConfig(Class<T>)`
- **Ruby:** `Anthropic::BaseModel` classes with `output_config: {format: Model}`
- **PHP:** Classes implementing `StructuredOutputModel` with `outputConfig: ['format' => MyClass::class]`
- **C#:** Plain C# classes with the generic `Create<T>()` overload, which derives the schema automatically
- **Go:** Go structs reflected into JSON schemas automatically on the beta API, or raw JSON schemas through `output_config`
- **CLI:** Raw JSON schemas passed through `output_config`
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from pydantic import BaseModel
from anthropic import Anthropic
class ContactInfo(BaseModel):
name: str
email: str
plan_interest: str
demo_requested: bool
client = Anthropic()
response = client.messages.parse(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Extract the key information from this email: John Smith (john@example.com) is interested in our Enterprise plan and wants to schedule a demo for next Tuesday at 2pm.",
}
],
output_format=ContactInfo,
)
print(response.parsed_output)
```
#### SDK-specific methods
Each SDK provides helpers that make working with structured outputs easier. See individual SDK pages for full details.
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
**`client.messages.parse()` (Recommended)**
The `parse()` method automatically transforms your Pydantic model, validates the response, and returns a `parsed_output` attribute.
```python
from pydantic import BaseModel
# ...
class ContactInfo(BaseModel):
name: str
email: str
plan_interest: str
# ...
response = client.messages.parse(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Extract contact info: John Smith, john@example.com, interested in the Pro plan",
}
],
output_format=ContactInfo,
)
# Access the parsed output directly
contact = response.parsed_output
print(contact.name, contact.email)
```
**`transform_schema()` helper**
For when you need to manually transform schemas before sending, or when you want to modify a Pydantic-generated schema. Unlike `client.messages.parse()`, which transforms provided schemas automatically, this gives you the transformed schema so you can further customize it.
```python
from anthropic import transform_schema
from pydantic import TypeAdapter
# ...
# First convert Pydantic model to JSON schema, then transform
schema = TypeAdapter(ContactInfo).json_schema()
schema = transform_schema(schema)
# Modify schema if needed
schema["properties"]["custom_field"] = {"type": "string"}
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "..."}],
output_config={
"format": {"type": "json_schema", "schema": schema},
},
)
```
#### How SDK transformation works
The Python, TypeScript, Ruby, and PHP SDKs automatically transform schemas with unsupported features. The C# and Go SDKs apply the same transformations when the schema is derived from a native type (`Create<T>()` in C#; struct reflection or `BetaJSONSchemaOutputFormat()` on the Go beta API). The transformation steps:
1. **Remove unsupported constraints** (for example, `minimum`, `maximum`, `minLength`, `maxLength`)
2. **Update descriptions** with constraint info (for example, "Must be at least 100"), when the constraint is not directly supported with structured outputs
3. **Add `additionalProperties: false`** to all objects
4. **Filter string formats** to supported list only
5. **Validate responses** against your original schema (with all constraints)
This means Claude receives a simplified schema, but your code still enforces all constraints through validation.
**Example:** A Pydantic field with `minimum: 100` becomes a plain integer in the sent schema, but the SDK updates the description to "Must be at least 100" and validates the response against the original constraint.
### Common use cases
### Data extraction
Extract structured data from unstructured text:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from pydantic import BaseModel
class Invoice(BaseModel):
invoice_number: str
date: str
total_amount: float
line_items: list[dict]
customer_name: str
client = anthropic.Anthropic()
invoice_text = "Invoice #12345, Date: 2024-01-15, Total: $500.00"
response = client.messages.parse(
model="claude-opus-5-5",
max_tokens=4096,
output_format=Invoice,
messages=[
{"role": "user", "content": f"Extract invoice data from: {invoice_text}"}
],
)
print(response.parsed_output)
```
### Classification
Classify content with structured categories:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from pydantic import BaseModel
client = Anthropic()
class Classification(BaseModel):
category: str
confidence: float
tags: list[str]
sentiment: str
feedback_text = "Great product, but the delivery was slow."
response = client.messages.parse(
model="claude-opus-5-5",
max_tokens=1024,
output_format=Classification,
messages=[{"role": "user", "content": f"Classify this feedback: {feedback_text}"}],
)
print(response.parsed_output)
```
### API response formatting
Generate API-ready responses:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
from pydantic import BaseModel
client = Anthropic()
class APIResponse(BaseModel):
status: str
data: dict
errors: list[dict] | None
metadata: dict
response = client.messages.parse(
model="claude-opus-5-5",
max_tokens=1024,
output_format=APIResponse,
messages=[{"role": "user", "content": "Process this request: ..."}],
)
print(response.parsed_output)
```
## Strict tool use
To enforce JSON Schema compliance on tool inputs with grammar-constrained sampling, see [Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md).
## Using both features together
JSON outputs and strict tool use solve different problems and work together:
- **JSON outputs** control Claude's response format (what Claude says)
- **Strict tool use** validates tool parameters (how Claude calls your functions)
When combined, Claude can call tools with guaranteed-valid parameters AND return structured JSON responses. This is useful for agentic workflows where you need both reliable tool calls and structured final outputs.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Help me plan a trip to Paris departing May 15, 2026",
}
],
# JSON outputs: structured response format
output_config={
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"summary": {"type": "string"},
"next_steps": {"type": "array", "items": {"type": "string"}},
},
"required": ["summary", "next_steps"],
"additionalProperties": False,
},
}
},
# Strict tool use: guaranteed tool parameters
tools=[
{
"name": "search_flights",
"strict": True,
"input_schema": {
"type": "object",
"properties": {
"destination": {"type": "string"},
"date": {"type": "string", "format": "date"},
},
"required": ["destination", "date"],
"additionalProperties": False,
},
}
],
)
print(response)
```
## Important considerations
### Grammar compilation and caching
Structured outputs use constrained sampling with compiled grammar artifacts. This introduces some performance characteristics to be aware of:
- **First request latency:** The first time you use a specific schema, there is additional latency while the grammar compiles
- **Automatic caching:** Compiled grammars are cached for 24 hours from last use, making subsequent requests much faster
- **Cache invalidation:** The cache is invalidated if you change:
- The JSON schema structure
- The set of tools in your request (when using both structured outputs and tool use)
- Changing only `name` or `description` fields does not invalidate the cache
### Prompt modification and token costs
When using structured outputs, Claude automatically receives an additional system prompt explaining the expected output format. This means:
- Your input token count is slightly higher
- The injected prompt costs you tokens like any other system prompt
- Changing the `output_config.format` parameter will invalidate any [prompt cache](build-with-claude-prompt-caching.md) for that conversation thread
### JSON Schema limitations
Structured outputs support standard JSON Schema with some limitations. Both JSON outputs and strict tool use share these limitations.
### Supported features
- All basic types: object, array, string, integer, number, boolean, null
- `enum` (strings, numbers, bools, or nulls only - no complex types; see [Invalid outputs](#invalid-outputs) for a capitalization caveat)
- `const`
- `anyOf` and `allOf` (with limitations - `allOf` with `$ref` not supported)
- `$ref`, `$def`, and `definitions` (external `$ref` not supported)
- `default` property for all supported types
- `required` and `additionalProperties` (must be set to `false` for objects)
- String formats: `date-time`, `time`, `date`, `duration`, `email`, `hostname`, `uri`, `ipv4`, `ipv6`, `uuid`
- Array `minItems` (only values 0 and 1 supported)
### Not supported
- Recursive schemas
- Complex types within enums
- External `$ref` (for example, `'$ref': 'http://...'`)
- Numerical constraints (such as `minimum`, `maximum`, `multipleOf`)
- String constraints (`minLength`, `maxLength`)
- Array constraints beyond `minItems` of 0 or 1
- `additionalProperties` set to anything other than `false`
If you use an unsupported feature, you'll receive a 400 error with details.
### Pattern support (regex)
**Supported regex features:**
- Full matching (`^...$`) and partial matching
- Quantifiers: `*`, `+`, `?`, simple `{n,m}` cases
- Character classes: `[]`, `.`, `\d`, `\w`, `\s`
- Groups: `(...)`
**NOT supported:**
- Backreferences to groups (for example, `\1`, `\2`)
- Lookahead/lookbehind assertions (for example, `(?=...)`, `(?!...)`)
- Word boundaries: `\b`, `\B`
- Complex `{n,m}` quantifiers with large ranges
Simple regex patterns work well. Complex patterns may result in 400 errors.
The Python, TypeScript, Ruby, and PHP SDKs can automatically transform schemas with unsupported features by removing them and adding constraints to field descriptions. The C# and Go SDKs do the same when the schema is derived from a native type. See [SDK-specific methods](#sdk-specific-methods) for details.
### Property ordering
When using structured outputs, properties in objects maintain their defined ordering from your schema, with one important caveat: **required properties appear first, followed by optional properties**.
For example, given this schema:
```python
{
"type": "object",
"properties": {
"notes": { "type": "string" },
"name": { "type": "string" },
"email": { "type": "string" },
"age": { "type": "integer" }
},
"required": ["name", "email"],
"additionalProperties": false
}
```
The output will order properties as:
1. `name` (required, in schema order)
2. `email` (required, in schema order)
3. `notes` (optional, in schema order)
4. `age` (optional, in schema order)
This means the output might look like:
```python
{
"name": "John Smith",
"email": "john@example.com",
"notes": "Interested in enterprise plan",
"age": 35
}
```
If property order in the output is important to your application, mark all properties as required, or account for this reordering in your parsing logic.
### Invalid outputs
While structured outputs guarantee schema compliance in most cases, there are scenarios where the output may not match your schema:
**Refusals** (`stop_reason: "refusal"`)
Claude maintains its safety and helpfulness properties even when using structured outputs. If Claude refuses a request for safety reasons:
- The response has `stop_reason: "refusal"`
- You'll receive a 200 status code
- You'll be billed for the tokens generated
- The output may not match your schema because the refusal message takes precedence over schema constraints
**Token limit reached** (`stop_reason: "max_tokens"`)
If the response is cut off due to reaching the `max_tokens` limit:
- The response has `stop_reason: "max_tokens"`
- The output may be incomplete and not match your schema
- Retry with a higher `max_tokens` value to get the complete structured output
**Enum value casing**
Structured outputs don't guarantee the capitalization of string `enum` and `const` values: Claude may return a value that differs from your schema only in capitalization, typically in the first letter of a word following a space. For example, given this schema:
```python
{
"type": "string",
"enum": ["Conversation Topic 1", "Conversation Topic 2", "Conversation topic 3"]
}
```
The output may contain `"Conversation Topic 3"` (capital "T") even though that exact value isn't in the enum. The response completes normally, with no error and no special `stop_reason`. This applies to both JSON outputs and strict tool use. Compare enum values case-insensitively, and avoid enum values that differ only in capitalization.
### Schema complexity limits
Structured outputs work by compiling your JSON schemas into a grammar that constrains Claude's output. More complex schemas produce larger grammars that take longer to compile. To protect against excessive compilation times, the API enforces several complexity limits.
#### Explicit limits
The following limits apply to all requests with `output_config.format` or `strict: true`:
| Limit | Value | Description |
|-----------------------------|-------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Strict tools per request | 20 | Maximum number of tools with `strict: true`. Non-strict tools don't count toward this limit. |
| Optional parameters | 24 | Total optional parameters across all strict tool schemas and JSON output schemas. Each parameter not listed in `required` counts toward this limit. |
| Parameters with union types | 16 | Total parameters that use `anyOf` or type arrays (for example, `"type": ["string", "null"]`) across all strict schemas. These are especially expensive because they create exponential compilation cost. |
These limits apply to the combined total across all strict schemas in a single request. For example, if you have 4 strict tools with 6 optional parameters each, you'll reach the 24-parameter limit even though no single tool seems complex.
#### Additional internal limits
Beyond the explicit limits in the preceding table, there are additional internal limits on the compiled grammar size. These limits exist because schema complexity doesn't reduce to a single dimension: features like optional parameters, union types, nested objects, and number of tools interact with each other in ways that can make the compiled grammar disproportionately large.
When these limits are exceeded, you'll receive a 400 error with the message "Schema is too complex for compilation." These errors mean the combined complexity of your schemas exceeds what can be efficiently compiled, even if each individual limit in the preceding table is satisfied. As a final stop-gap, the API also enforces a **compilation timeout of 180 seconds**. Schemas that pass all explicit checks but produce very large compiled grammars may hit this timeout.
#### Tips for reducing schema complexity
If you're hitting complexity limits, try these strategies in order:
1. **Mark only critical tools as strict.** If you have many tools, reserve it for tools where schema violations cause real problems, and rely on Claude's natural adherence for simpler tools.
2. **Reduce optional parameters.** Make parameters `required` where possible. Each optional parameter roughly doubles a portion of the grammar's state space. If a parameter always has a reasonable default, consider making it required and having Claude provide that default explicitly.
3. **Simplify nested structures.** Deeply nested objects with optional fields compound the complexity. Flatten structures where possible.
4. **Split into multiple requests.** If you have many strict tools, consider splitting them across separate requests or sub-agents.
For persistent issues with valid schemas, [contact support](https://platform.claude.com/docs/21-Account-Support/how-to-get-support-57c428239c.md) with your schema definition.
## Data retention
Prompts and responses are processed with ZDR when using structured outputs. However, the JSON schema itself is temporarily cached for up to 24 hours since last use for optimization purposes. No prompt or response data is retained beyond the API response.
Structured outputs are HIPAA eligible, but **PHI must not be included in JSON schema definitions**. The API compiles JSON schemas into grammars that are cached separately from message content, and these cached schemas do not receive the same PHI protections as prompts and responses. Do not include PHI in schema property names, `enum` values, `const` values, or `pattern` regular expressions. PHI should only appear in message content (prompts and responses), where it is protected under HIPAA safeguards.
For ZDR and HIPAA eligibility across all features, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
## Feature compatibility
**Works with:**
- **[Batch processing](build-with-claude-batch-processing.md):** Process structured outputs at scale with 50% discount
- **[Token counting](build-with-claude-token-counting.md):** Count tokens without compilation
- **[Streaming](build-with-claude-streaming.md):** Stream structured outputs like normal responses
- **Combined usage:** Use JSON outputs (`output_config.format`) and strict tool use (`strict: true`) together in the same request
**Incompatible with:**
- **[Citations](build-with-claude-citations.md):** Citations require interleaving citation blocks with text, which conflicts with strict JSON schema constraints. Returns 400 error if citations enabled with `output_config.format`.
- **Message Prefilling:** Incompatible with JSON outputs
**Grammar scope:** Grammars apply only to Claude's direct output, not to tool use calls, tool results, or thinking tags (when using [thinking](build-with-claude-thinking.md)). Grammar state resets between sections, allowing Claude to think freely while still producing structured output in the final response.
## Next steps
[Citations](build-with-claude-citations.md)
Have Claude cite its sources when answering questions about provided documents.
[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)
Enforce JSON Schema compliance on Claude's tool inputs with grammar-constrained sampling.
[Tool use with Claude](../Agents-Tools/agents-and-tools-tool-use-overview.md)
Connect Claude to external tools and APIs. Learn where tools execute and how the agentic loop works.
[Pricing](../../17-Billing-Plans/about-claude-pricing.md)
Learn about Anthropic's pricing structure for models and features.
## Compatibility
Supported models
- Fable 5 and 5.1
- Mythos 5, 5.1, and Preview
- Opus 4.5, 4.6, 4.7, 4.8, 5, and 5.5
- Sonnet 4.5, 4.6, and 5
- Haiku 4.5
Supported platforms
- Claude API
- Claude Platform on AWS
- Amazon Bedrock^([1](#compat-fn-1))
- Google Cloud
- Microsoft Foundry
1. On Amazon Bedrock, structured outputs are available for Claude Opus 4.6, Claude Sonnet 4.6, Claude Sonnet 4.5, Claude Opus 4.5, and Claude Haiku 4.5. [↩](#compat-fnref-1)
---
## Task budgets - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/task-budgets
Path: 04-API-Reference/Guides/build-with-claude-task-budgets.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Ftask-budgets)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Model capabilities
# Task budgets
Copy page
Give Claude an advisory token budget for the full agentic loop to help the model self-regulate on long agentic tasks.
Copy page
Task budgets
[Beta](build-with-claude-overview.md#feature-availability)
[Beta header](../Endpoints/beta-headers.md)
task-budgets-2026-03-13
Task budgets let you tell Claude how many tokens it has for a full agentic loop, including thinking, tool calls, tool results, and output. The model sees a running countdown and uses it to prioritize work and finish gracefully as the budget is consumed.
## When to use task budgets
Task budgets work best for agentic workflows where Claude makes multiple tool calls and decisions before finalizing its output to await the next human response. Use them when:
- You want Claude to self-regulate token spend on long-horizon tasks.
- You have a predictable per-task cost or latency ceiling to enforce.
- You want the model to finish gracefully (summarize findings, report progress) as it approaches the budget rather than cutting off mid-action.
Task budgets complement the [effort parameter](build-with-claude-effort.md): effort controls how thoroughly Claude reasons about each step, while task budgets cap the total work Claude can do across an agentic loop.
## Setting a task budget
Add `task_budget` to `output_config` and include the beta header:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
with client.beta.messages.stream(
model="claude-opus-5-5",
max_tokens=128000,
output_config={
"effort": "high",
"task_budget": {"type": "tokens", "total": 64000},
},
messages=[
{"role": "user", "content": "Review the codebase and propose a refactor plan."}
],
betas=["task-budgets-2026-03-13"],
) as stream:
response = stream.get_final_message()
print(response.usage)
```
The `task_budget` object has three fields:
- `type`: always `"tokens"`.
- `total`: the number of tokens Claude can spend across the agentic loop, including thinking, tool calls, tool results, and output.
- `remaining` (optional): the budget remainder carried over from a prior request. Defaults to `total` when omitted.
## How the budget countdown works
Claude sees a budget-countdown marker injected server-side throughout the conversation. The marker shows how many tokens remain in the current agentic loop and updates as the model generates thinking, tool calls, and output, and as it processes tool results. Claude uses this signal to pace itself and finish gracefully as the budget is consumed.
**The countdown is visible only to the model.** API responses do not include a remaining-budget field: there is no `task_budget` information in the response `usage` object, and SDKs have no accessor for it. To track spend client-side, sum token usage across the requests in your loop as shown in [Measure your current usage](#measure-your-current-usage), or pass your own figure forward with `remaining` when [carrying a budget across compaction](#carrying-a-budget-across-compaction-with-remaining).
**The countdown reflects tokens Claude has processed in the current agentic loop, not tokens you resend between requests.** If your client sends the full conversation history on every follow-up request, your client-side token count might differ from the budget Claude is tracking. If you also decrement `remaining` while resending full history, the model sees an under-reported budget and the countdown drops faster than it should, causing Claude to wrap up earlier than the budget actually allows. Set a generous budget and let the model self-regulate against the countdown rather than trying to mirror it client-side.
### What counts as a turn
The budget covers one agentic turn, also called an agentic loop: everything Claude does in response to one user message that carries no tool results. A turn can span several requests.
A user message that carries no tool results starts a new turn with a fresh budget. Today, the countdown still counts earlier turns' history while it remains in the context. A common case is a follow-up after Claude has ended its turn, for example because the budget ran out:
```python
{ "role": "user", "content": "Continue." }
```
A user message that contains `tool_result` blocks continues the current turn, because your client is resolving tool calls that are part of that turn:
```python
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "<npm audit output>" }
]
}
```
That holds even when the message adds new content alongside the tool results:
```python
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "<npm audit output>" },
{ "type": "text", "text": "Also check the Dockerfile." }
]
}
```
Server-side [compaction](build-with-claude-compaction-threshold.md) during a turn does not reset the budget: tokens the turn consumed before the compaction still count against it. Tokens from before the turn began do not count, even when a compaction at the start of a turn summarizes them. Today, that exclusion applies only to the budget carried across a server-side compaction; earlier turns' history still counts while it remains in the context.
### Worked example: budget counting across requests
The task budget counts what Claude **sees** (thinking, tool calls and results, and text), not what's in your request payload. In an agentic loop your client resends the full conversation on every request, so the payload keeps growing, but the budget only decrements by what is new: the tokens Claude generates and the content it has not seen before. The following example is one [agentic turn](#what-counts-as-a-turn) made of three requests: the first carries the user message, and the next two each resend the history with a tool result appended.
Consider a loop with `task_budget: {type: "tokens", total: 100000}` and a single `bash` tool.
**Request 1.** You send the initial request:
```python
{
"messages": [
{ "role": "user", "content": "Audit this repo for security issues and report findings." }
]
}
```
Claude thinks, then emits a tool call and stops with `stop_reason: "tool_use"`:
```python
{
"role": "assistant",
"content": [
{
"type": "thinking",
"thinking": "I'll start by listing dependencies to look for known-vulnerable packages..."
},
{
"type": "tool_use",
"id": "toolu_01",
"name": "bash",
"input": { "command": "cat package.json && npm audit --json" }
}
]
}
```
Suppose this assistant message (thinking plus the tool call) totals 5,000 generated tokens. The countdown Claude saw during generation ended near `remaining` ≈ 95,000.
**Request 2.** Your client runs the tool, then resends the full history with the tool result appended:
```python
{
"messages": [
{ "role": "user", "content": "Audit this repo for security issues and report findings." },
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "I'll start by listing dependencies..." },
{
"type": "tool_use",
"id": "toolu_01",
"name": "bash",
"input": { "command": "cat package.json && npm audit --json" }
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01",
"content": "<2,800 tokens of npm audit output>"
}
]
}
]
}
```
The resent messages from request 1 are not counted again, but the 2,800-token tool result is new content and counts against the budget. Claude spends another 4,000 tokens on thinking and a second tool call (`grep -rn "eval(" src/`). The countdown ends near `remaining` ≈ 88,200.
**Request 3.** Full history resent again with the second tool result (1,200 tokens of grep output) appended. Claude writes a 6,000-token final findings report and stops with `stop_reason: "end_turn"`. `remaining` ≈ 81,000.
Putting the three requests side by side makes the distinction between payload size and budget spend explicit:
| Request | Request payload (approx. input tokens you sent) | Tokens counted against budget this request | Budget `remaining` after |
|-----------|-------------------------------------------------|-----------------------------------------------------------|--------------------------|
| 1 | ~20 | 5,000 (thinking + `tool_use`) | ~95,000 |
| 2 | ~7,800 (messages from request 1 + tool result) | 6,800 (2,800 tool result + 4,000 thinking and `tool_use`) | ~88,200 |
| 3 | ~13,000 (full history + second tool result) | 7,200 (1,200 tool result + 6,000 `text`) | ~81,000 |
| **Total** | **~20,820 sent across requests** | **19,000 counted against budget** | N/A |
Your client sent the original user message three times and the first assistant message twice, but each was counted once. The budget spent 19,000 of 100,000 tokens, even though the cumulative payload your client transmitted was larger and the prompt-cached input on requests 2 and 3 was larger still.
### Carrying a budget across compaction with `remaining`
If your own code compacts or rewrites the message history between requests (for example, by summarizing earlier messages), the server has no memory of how much budget was spent before compaction. Pass `remaining` on the next request so the countdown continues from where you left off rather than resetting to `total`:
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
# Tokens spent before compaction, tracked client-side
tokens_spent_so_far = 45000
output_config = {
"effort": "high",
"task_budget": {
"type": "tokens",
"total": 128000,
"remaining": 128000 - tokens_spent_so_far,
},
}
```
In this example, the tokens spent before compaction are the usage of all the messages you have removed from the history so far, measured as in [Measure your current usage](#measure-your-current-usage). Leave out anything still present in the messages you send, including any summary you added, because the server counts those tokens itself. Update this figure only when you replace the history this way; don't decrement it per request. Pass the resulting `remaining` on every request, not only the one that compacts.
For loops that resend the full uncompacted history on every request, omit `remaining` and let the server track the countdown.
## Changing the budget mid-conversation
`task_budget` is a request-level setting. To change the budget partway through a task, for example to extend it when the user broadens the request, set a new `task_budget` in `output_config` on the next request. Keep the caching consequence in mind: the budget value participates in the rendered prompt, so a changed value does not match cache entries created under the old one (see [Feature support](#feature-support) below).
## Task budgets are advisory, not enforced
Task budgets are a **soft hint, not a hard cap**. Claude may occasionally exceed the budget if it is in the middle of an action that would be more disruptive to interrupt than to finish. The enforced limit on total output tokens is still `max_tokens`, which truncates the response with `stop_reason: "max_tokens"` when reached.
For a hard cap on cost or latency, combine task budgets with a reasonable `max_tokens` value:
- Use `task_budget` to give Claude a target to pace against.
- Use `max_tokens` as the absolute ceiling that prevents runaway generation.
Because `task_budget` spans the full agentic loop (potentially many requests) while `max_tokens` caps each individual request, the two values are independent; one is not required to be at or below the other.
**A budget that is too small for the task can cause refusal-like behavior.** When Claude sees a budget that is clearly insufficient for the work being asked (for example, a 20,000-token budget for a multihour agentic coding task), it may decline to attempt the task at all, scope it down aggressively, or stop early with a partial result rather than start work it cannot finish. If you observe unexpected refusals or premature stops after setting a budget, raise the budget before debugging other parameters. Size budgets against your actual task-length distribution rather than a fixed default; see [Choosing a budget](#choosing-a-budget).
## Choosing a budget
The right budget depends on how much work your agentic loop currently does. Rather than guessing, measure your existing token usage first and then tune from there.
### Measure your current usage
Run a representative sample of tasks **without** `task_budget` set and record the total tokens Claude spends per task. For an agentic loop, sum `usage.output_tokens` across every request in the loop, plus the tokens of the tool results you append between requests:
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
messages=[
{"role": "user", "content": "Review the codebase and propose a refactor plan."}
],
)
# Sum output_tokens (text + thinking + tool calls) across every request in your loop.
print(response.usage.output_tokens)
```
Run this across a representative set of tasks and record the distribution. Start with the p99 of your per-task token spend to understand how providing the model with a task budget might modify the model's behavior, then test up or down as needed.
The minimum accepted `task_budget.total` is **20,000 tokens** on every model that supports task budgets (see [Feature support](#feature-support)). Smaller values return a 400 error.
## Interaction with other parameters
- **`max_tokens`:** Orthogonal to task budgets. `max_tokens` is a hard per-request cap on generated tokens, while `task_budget` is an advisory cap across the full agentic loop (potentially spanning many requests). At `xhigh` or `max` effort, set `max_tokens` to at least 64k to give Claude room to think and act on each request.
- **[Effort](build-with-claude-effort.md):** Effort controls how deeply Claude reasons per step. Task budgets control how much total work Claude does across an agentic loop. The two are complementary: effort tunes depth, task budgets tune breadth.
- **[Adaptive thinking](build-with-claude-thinking.md):** Task budgets include thinking tokens in the count, so adaptive thinking scales down as the budget depletes.
- **[Prompt caching](build-with-claude-prompt-caching.md):** The budget-countdown marker is injected server-side on each request, so it does not match across requests. If your client decrements `task_budget.remaining` on each follow-up request, the changed value invalidates any cache prefix that contains it. To preserve caching, set the budget once on the initial request and let the model self-regulate against the server-side countdown rather than mutating the budget client-side.
## Feature support
| Model | Support |
|-------------------|---------------------------------------------|
| Claude Fable 5.1 | Beta (set `task-budgets-2026-03-13` header) |
| Claude Mythos 5.1 | Beta (set `task-budgets-2026-03-13` header) |
| Claude Opus 5.5 | Beta (set `task-budgets-2026-03-13` header) |
| Claude Opus 5 | Beta (set `task-budgets-2026-03-13` header) |
| Claude Fable 5 | Beta (set `task-budgets-2026-03-13` header) |
| Claude Mythos 5 | Beta (set `task-budgets-2026-03-13` header) |
| Claude Sonnet 5 | Not supported |
| Claude Opus 4.8 | Beta (set `task-budgets-2026-03-13` header) |
| Claude Opus 4.7 | Beta (set `task-budgets-2026-03-13` header) |
| Claude Opus 4.6 | Not supported |
| Claude Sonnet 4.6 | Not supported |
| Claude Haiku 4.5 | Not supported |
Task budgets are not supported on [Claude Code](https://platform.claude.com/docs/01-Getting-Started/overview.md) or Cowork surfaces. Use task budgets directly through the Messages API on a [supported model](#feature-support).
## Next steps
[Effort](build-with-claude-effort.md)
Control how thoroughly Claude reasons about each step of an agentic loop.
[Adaptive thinking](build-with-claude-thinking.md)
Let Claude decide when and how much to use extended thinking.
[Compaction](build-with-claude-compaction.md)
Manage context in long-running conversations with server-side compaction.
[Prompt caching](build-with-claude-prompt-caching.md)
Reduce cost and latency on repeated prompts by caching prompt prefixes.
## Compatibility
Supported models
- Fable 5 and 5.1
- Mythos 5 and 5.1
- Opus 4.7, 4.8, 5, and 5.5
---
## Steering thinking - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/thinking-steering-and-cost
Path: 04-API-Reference/Guides/build-with-claude-thinking-steering-and-cost.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fthinking-steering-and-cost)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
[Overview](build-with-claude-thinking.md)[Steering and cost control](build-with-claude-thinking-steering-and-cost.md)[Tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md)[Preserved thinking](build-with-claude-preserved-thinking.md)[Troubleshooting](build-with-claude-thinking-troubleshooting.md)[Extended thinking (legacy)](build-with-claude-extended-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Thinking
# Steering thinking
Copy page
Steer how often and how deeply Claude thinks with effort levels, system prompt guidance, and per-message steering, and understand thinking's cost and pricing.
Copy page
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
Claude's thinking is adaptive: the model evaluates each request and decides for itself whether to think and how much. You set an intent, optionally specify the effort, and the model allocates reasoning where it judges reasoning will help.
This makes thinking a strong fit for workloads that mix trivial and complex requests, and for long-horizon agentic workflows where the right amount of reasoning varies from step to step.
To learn how to turn thinking on, how to read thinking output, and about [thinking output on Claude Fable 5 and Claude Mythos 5](build-with-claude-thinking.md#thinking-output-on-claude-fable-5-and-claude-mythos-5), see the [Thinking](build-with-claude-thinking.md) overview. This page covers how Claude decides when to think, how to steer that decision, and the caching, cost, and pricing mechanics that follow from it.
## How Claude decides when to think
Thinking is optional for the model. On each request, Claude weighs the complexity of the input and decides whether deeper reasoning would improve the answer. A simple factual question may get a direct response with no thinking block at all; a multistep math problem or a tricky debugging task triggers deeper reasoning.
The decision happens per request. The same conversation can contain turns with and without thinking, and a turn where Claude chose not to think contains no thinking block. Don't build application logic that assumes every assistant turn starts with one.
The primary control over this decision is the [effort](build-with-claude-effort.md) parameter, which acts as soft guidance for how willing Claude should be to think and how deeply; see [Effort levels](#effort-levels) on this page for what each level does.
If you want Claude to think less often, lower the effort level before reaching for prompt-based steering.
Thinking also interleaves with tool use automatically: Claude can think between tool calls, reflecting on each tool result before deciding what to do next ([interleaved thinking](build-with-claude-thinking.md#interleaved-thinking)). You don't need a beta header or any additional configuration for this.
For the full picture of how the thinking configuration and the effort parameter interact, see [Thinking and effort](build-with-claude-thinking.md#thinking-and-effort).
## Steering how often Claude thinks
Whether Claude thinks on a given turn is promptable. Effort sets the overall posture, but you can also shape the decision directly with natural-language guidance, either globally in the system prompt or per message from the user turn.
Use the two levers together in this order:
1. Set the effort level that matches your workload's default balance of quality and latency.
2. Add prompt guidance only if Claude's triggering still doesn't match your needs at that level.
For broader prompting guidance with thinking, see [leverage thinking and interleaved thinking capabilities](../../10-Prompting-Guides/build-with-claude-prompt-engineering-claude-prompting-best-practices.md#leverage-thinking-and-interleaved-thinking-capabilities).
### Effort levels
Effort is the primary steering lever for thinking. Each level sets a different default for how often Claude thinks and how deeply:
| Effort level | Thinking behavior |
|:--------------------------------------|:-------------------------------------------------------------------------------------------------|
| `max` | Claude thinks the most readily and at the greatest depth, with no constraint on thinking length. |
| `xhigh` | Claude thinks more readily and at greater depth than at `high`, suited to extended exploration. |
| `high` (default on most models) | Claude thinks on most requests that benefit from it. Provides deep reasoning on complex tasks. |
| `medium` (default on Claude Opus 5.5) | Claude uses moderate thinking. May skip thinking for simple queries. |
| `low` | Claude minimizes thinking. Skips thinking for simple tasks where speed matters most. |
At every level, Claude decides per request whether to think. In a tool-use loop, the first request after new user input typically carries most of the reasoning, and follow-up requests that only process tool results can skip thinking, including at `xhigh` and `max`. Thinking per request also tends to decrease as a conversation grows longer. No level guarantees a thinking block on every request.
This table describes how each level changes thinking behavior. For guidance on which level to choose for a given workload, including per-model recommendations, see [When to adjust the effort parameter](build-with-claude-effort.md#when-to-adjust-the-effort-parameter) on the effort page.
Effort is set at `output_config.effort`, not inside the `thinking` object; for full per-language examples, see [Effort](build-with-claude-effort.md#basic-usage).
```python
{
"model": "claude-opus-5-5",
"max_tokens": 4096,
"output_config": { "effort": "medium" },
"messages": [{ "role": "user", "content": "..." }]
}
```
Level availability varies by model; the [effort availability table](build-with-claude-effort.md#effort-levels) on the effort page is the authority for which levels each model supports.
### System prompt guidance
System prompt guidance shifts Claude's thinking threshold for every request in the conversation. If Claude is thinking more often than your workload needs, add guidance like this to your system prompt:
``` block
Extended thinking adds latency and should only be used when it
will meaningfully improve answer quality, typically for problems
that require multistep reasoning. When in doubt, respond directly.
```
To encourage thinking instead, use a phrase like:
``` block
This task involves multistep reasoning. Think carefully before responding.
```
Steering effectiveness can be sensitive to exact wording. If one phrasing doesn't produce the behavior you want, try a more direct variant.
### Per-message steering
You can also steer thinking on a per-message basis from the user turn, independently of the system prompt. Appending `"Please think hard before responding."` to a user message encourages Claude to think on that turn; `"Answer directly without deliberating."` suppresses it.
Per-message steering is useful when only some requests in a conversation warrant extended reasoning. An agent harness, for example, can append the encouraging phrase on planning steps and the suppressing phrase on routine confirmations, without touching the system prompt or changing any request parameters between turns.
### Verify steering on your workload
Prompt-based steering changes model behavior, so treat it like any other prompt change: measure before you ship. Run a representative sample of your traffic with and without the guidance, and compare how often thinking triggers (the presence of thinking blocks in responses), output token usage, latency, and answer quality on the cases that matter to you.
Steering Claude to think less often may reduce quality on tasks that benefit from reasoning. Lowering the [effort](build-with-claude-effort.md) level is usually the better first lever, since it is a calibrated control rather than a wording-sensitive instruction. Measure the impact on your specific workloads before deploying prompt-based tuning to production.
## Mechanics
Three mechanics follow from Claude managing its own thinking: turn validation, prompt caching, and how you bound cost.
### Turn validation
Assistant turns don't need to start with a thinking block. (Models using a legacy manual thinking budget enforce that the final assistant turn of a thinking-enabled request begins with one; see [Turn structure in manual mode](build-with-claude-extended-thinking.md#turn-structure-in-manual-mode).)
For multi-turn applications, this means you can pass back conversation history in whatever shape you have it:
- Assistant turns where Claude chose not to think are valid history as-is.
- You can resume a conversation that began without thinking, or that used a different thinking configuration, without rewriting its history.
- History assembled from mixed sources doesn't need thinking blocks reinserted at the start of each assistant turn to pass validation.
The relaxation is about validation, not about what you should send. When you have thinking blocks, pass them back unmodified, particularly during tool use, where they carry the reasoning behind Claude's tool calls. See the [Thinking](build-with-claude-thinking.md) overview for the full rules.
### Prompt caching
Consecutive requests that keep the same thinking configuration and effort level preserve prompt caching; see [Thinking and prompt caching](build-with-claude-thinking.md#thinking-and-prompt-caching) for the full rules. The resolved effort value is rendered into the prompt, so changing it between requests invalidates cache breakpoints, just as changing the legacy [`budget_tokens`](build-with-claude-extended-thinking.md#extended-thinking-with-prompt-caching) parameter does on models that use it. Setting `effort` explicitly to the model's default is equivalent to omitting it and does not break the cache.
The practical consequence: pick a thinking configuration and an effort level per conversation and keep them. If some turns need more or less thinking, steer with [per-message prompting](#tuning-thinking-behavior): guidance appended to the newest user message leaves earlier cache breakpoints intact, where a configuration or effort change does not.
The following example demonstrates the invalidation with a multi-turn script you can run yourself:
### Effort changes invalidate the prompt cache
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import requests
client = Anthropic()
def fetch_article_content(url):
text = requests.get(url).text
lines = (line.strip() for line in text.splitlines())
return "\n".join(line for line in lines if line)
# Fetch the content of the article
book_url = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
book_content = fetch_article_content(book_url)
# Use just enough text for caching (first few chapters)
LARGE_TEXT = book_content[:10000]
# No system prompt - caching in messages instead
MESSAGES = [
{
"role": "user",
"content": [
{
"type": "text",
"text": LARGE_TEXT,
"cache_control": {"type": "ephemeral"},
},
{"type": "text", "text": "Analyze the tone of this passage."},
],
}
]
# First request - establish cache
print("First request - establishing cache")
response1 = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
thinking={"type": "adaptive"},
messages=MESSAGES,
)
print(f"First response usage: {response1.usage}")
MESSAGES.append({"role": "assistant", "content": response1.content})
MESSAGES.append({"role": "user", "content": "Analyze the characters in this passage."})
# Second request - same configuration (cache hit expected)
print("\nSecond request - same configuration (cache hit expected)")
response2 = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
thinking={"type": "adaptive"},
messages=MESSAGES,
)
print(f"Second response usage: {response2.usage}")
MESSAGES.append({"role": "assistant", "content": response2.content})
MESSAGES.append({"role": "user", "content": "Analyze the setting in this passage."})
# Third request - different effort level (cache miss expected)
print("\nThird request - different effort level (cache miss expected)")
response3 = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
thinking={"type": "adaptive"},
output_config={"effort": "low"},
messages=MESSAGES,
)
print(f"Third response usage: {response3.usage}")
```
Here is the output of the script (you may see slightly different numbers):
Output
``` block
First request - establishing cache
First response usage: { cache_creation_input_tokens: 3546, cache_read_input_tokens: 0, input_tokens: 15, output_tokens: 1033 }
Second request - same configuration (cache hit expected)
Second response usage: { cache_creation_input_tokens: 0, cache_read_input_tokens: 3546, input_tokens: 1062, output_tokens: 1630 }
Third request - different effort level (cache miss expected)
Third response usage: { cache_creation_input_tokens: 3546, cache_read_input_tokens: 0, input_tokens: 2706, output_tokens: 1468 }
```
With the cache breakpoint in the messages array, changing effort from `medium`, the default on Claude Opus 5.5, to `low` invalidates it: the third request shows `cache_creation_input_tokens=3546` and `cache_read_input_tokens=0` where the second showed a full cache read.
### Cost control
You don't set a thinking token budget. Two controls bound cost:
- `max_tokens` is a hard cap on total output for the request, thinking and response text combined. Claude never generates past it. In a tool-use loop, each request in the turn has its own `max_tokens`, so it doesn't bound the whole turn's spend.
- `effort` is soft guidance on how much of that output Claude allocates to thinking. It shapes behavior but doesn't guarantee a token count.
Because thinking counts toward `max_tokens`, set it high enough to leave room for both the reasoning and the answer. A `max_tokens` sized for a response with no thinking is often too small once Claude starts thinking on hard requests.
At `high` effort and above, Claude may think extensively and is more likely to exhaust the budget. If you see [`stop_reason: "max_tokens"`](build-with-claude-thinking-troubleshooting.md#stopped-at-max-tokens) in responses, you have two remedies:
- Raise `max_tokens` to give the model more room for thinking plus the answer.
- Lower the effort level so Claude thinks less and leaves more of the budget for response text.
Which one is right depends on whether the truncated responses needed the reasoning. If quality on those requests matters, raise the cap; if they were over-thought, lower the effort.
## Pricing
Thinking incurs charges for:
- Tokens Claude uses while thinking (billed as output tokens)
- Thinking blocks from prior assistant turns that remain in context, per the [preservation default](build-with-claude-thinking.md#thinking-block-preservation-by-model): all turns by default on keep-all models, only the last turn elsewhere (billed as input tokens)
- Standard text output tokens
When thinking is active, a specialized system prompt is automatically included to support this feature.
What you're billed for is the same regardless of the `display` setting; only what you see changes:
| | `display: "summarized"` | `display: "omitted"` |
|:----------------------------|:-----------------------------------------------------|:-----------------------------------------------------|
| **Input tokens** | Tokens in your original request | Same as summarized |
| **Output tokens (billed)** | The full thinking tokens Claude generated internally | Same as summarized |
| **Output tokens (visible)** | The summarized thinking text | Zero thinking tokens (the `thinking` field is empty) |
| **Summary generation** | No charge | Not applicable |
The billed output token count does **not** match the visible token count in the response. You are billed for the full thinking process, not the thinking content visible in the response.
To see how many billed output tokens were spent on internal reasoning, read `usage.output_tokens_details.thinking_tokens` in the response. This value reflects the raw reasoning the model generated (not the summarized text returned in the body) and is always less than or equal to `output_tokens`. Subtract it from `output_tokens` to approximate the non-reasoning portion of the output. When streaming, this breakdown appears only on the final `message_delta` event.
```python
{
"usage": {
"input_tokens": 25,
"output_tokens": 348,
"output_tokens_details": {
"thinking_tokens": 312
}
}
}
```
`output_tokens` remains the inclusive, authoritative total used for billing. `output_tokens_details` is a read-only breakdown for observability. For complete pricing information including base rates, cache writes, cache hits, and output tokens, see [Pricing](../../17-Billing-Plans/about-claude-pricing.md).
## Next steps
[Thinking](build-with-claude-thinking.md)
Turn thinking on, read thinking output, and check per-model support.
[Thinking in tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md)
Preserve thinking blocks across tool calls and manage thinking in multi-turn conversations.
[Effort](build-with-claude-effort.md)
Control how much thinking and output Claude allocates per request.
---
## Thinking in tool and multi-turn workflows - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/thinking-tool-workflows
Path: 04-API-Reference/Guides/build-with-claude-thinking-tool-workflows.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fthinking-tool-workflows)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
[Overview](build-with-claude-thinking.md)[Steering and cost control](build-with-claude-thinking-steering-and-cost.md)[Tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md)[Preserved thinking](build-with-claude-preserved-thinking.md)[Troubleshooting](build-with-claude-thinking-troubleshooting.md)[Extended thinking (legacy)](build-with-claude-extended-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Thinking
# Thinking in tool and multi-turn workflows
Copy page
Walk through a complete two-turn tool-use round trip that preserves thinking blocks correctly, and see how interleaved thinking changes the flow.
Copy page
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
This page walks through a complete two-turn tool-use round trip with thinking enabled: Claude thinks, requests a tool call, receives the result, and finishes its answer, with the thinking blocks handled correctly at every step. The full rules live on the [Thinking](build-with-claude-thinking.md) page, in [Thinking with tool use](build-with-claude-thinking.md#thinking-with-tool-use) and [Preserving thinking blocks](build-with-claude-thinking.md#preserving-thinking-blocks); this page shows those rules applied in runnable code.
## The rules this walkthrough applies
Each link leads to the full statement on the Thinking page:
- [Limit tool choice to `auto` or `none` in manual mode](build-with-claude-thinking.md#thinking-with-tool-use): `tool_choice` options that force tool use return an error with manual extended thinking (`thinking: {type: "enabled"}`); adaptive thinking supports forced tool use.
- [Keep one thinking configuration per assistant turn](build-with-claude-thinking.md#thinking-with-tool-use): a tool-use loop is one assistant turn, so change the configuration only between turns.
- [Pass thinking blocks back complete and unmodified](build-with-claude-thinking.md#preserving-thinking-blocks): when you return a tool result, the thinking blocks from the assistant message must come back with it.
- [Echo the assistant message exactly as received](build-with-claude-thinking.md#preserving-thinking-blocks): rebuilding the message or filtering out `redacted_thinking` blocks triggers a 400 error.
The samples use adaptive thinking; on models that support only extended thinking, substitute `thinking: {type: "enabled", budget_tokens: N}`. The round-trip rules are identical.
## Walk through a two-turn tool-use round trip
The example defines a `get_weather` tool, lets Claude think and request a tool call, then returns the tool result along with the assistant turn echoed exactly as received, thinking block included.
1. 1
### Make the first request with a tool available
Send a request with adaptive thinking enabled and the tool defined. Apart from the `thinking` parameter, this is a standard [tool use](../Agents-Tools/agents-and-tools-tool-use-overview.md) request:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
``` shiki
client = anthropic.Anthropic()
weather_tool = {
"name": "get_weather",
"description": "Get current weather for a location",
"input_schema": {
"type": "object",
"properties": {"location": {"type": "string", "description": "City name"}},
"required": ["location"],
},
}
# First request - Claude responds with thinking and tool request
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=16000,
thinking={"type": "adaptive"},
tools=[weather_tool],
messages=[{"role": "user", "content": "What's the weather in Paris?"}],
)
print(response)
```
2. 2
### Capture the content array to echo back
You should see `thinking`, `text`, and `tool_use` blocks in the response content on a run where Claude chose to think (on simpler requests, adaptive mode may skip the thinking block). Keep this content array intact: the next step sends it back verbatim.
To see thinking text like this output, add `display: "summarized"` to the request. On models where display defaults to omitted, including claude-opus-4-8, the `thinking` field otherwise comes back as an empty string with only the `signature` populated. Either way, echo the content array back unchanged; see [Controlling thinking display](build-with-claude-thinking.md#controlling-thinking-display).
Output
``` shiki
{
"content": [
{
"type": "thinking",
"thinking": "The user wants to know the current weather in Paris. I have access to a function `get_weather`...",
"signature": "BDaL4VrbR2Oj0hO4XpJxT28J5T...."
},
{
"type": "text",
"text": "I can help you get the current weather information for Paris. Let me check that for you"
},
{
"type": "tool_use",
"id": "toolu_01CswdEQBMshySk6Y9DFKrfq",
"name": "get_weather",
"input": {
"location": "Paris"
}
}
]
}
```
3. 3
### Return the tool result, echoing the assistant turn verbatim
Run the tool on your side, then send a second request that appends two messages to the conversation. The first is the assistant content echoed back exactly as received, so the thinking block stays unchanged alongside the `tool_use` block. The second is a user message carrying the `tool_result`.
Each sample is a self-contained script: it repeats the first request, then immediately sends the follow-up using the response it just received.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
``` shiki
client = anthropic.Anthropic()
weather_tool = {
"name": "get_weather",
"description": "Get current weather for a location",
"input_schema": {
"type": "object",
"properties": {"location": {"type": "string", "description": "City name"}},
"required": ["location"],
},
}
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=16000,
thinking={"type": "adaptive"},
tools=[weather_tool],
messages=[{"role": "user", "content": "What's the weather in Paris?"}],
)
# Extract the tool use block to get its ID for the tool result
tool_use_block = next(block for block in response.content if block.type == "tool_use")
# Call your actual weather API, here is where your actual API call would go
# Let's pretend this is what we get back
weather_data = {"temperature": 88}
# Second request - Include the assistant turn and the tool result
continuation = client.messages.create(
model="claude-opus-4-8",
max_tokens=16000,
thinking={"type": "adaptive"},
tools=[weather_tool],
messages=[
{"role": "user", "content": "What's the weather in Paris?"},
# Echo the assistant content exactly as received. When a thinking
# block is present, it must accompany the tool_use block.
{"role": "assistant", "content": response.content},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": tool_use_block.id,
"content": f"Current temperature: {weather_data['temperature']}°F",
}
],
},
],
)
print(continuation)
```
4. 4
### Read the final response
You should see Claude complete the turn with text. Because [interleaved thinking](build-with-claude-thinking.md#interleaved-thinking) is automatic in adaptive mode, the continuation can also open with a new thinking block before the final text:
Output
``` shiki
{
"content": [
{
"type": "text",
"text": "Currently in Paris, the temperature is 88°F (31°C)"
}
]
}
```
## How interleaved thinking changes the flow
Interleaved thinking lets Claude think between tool calls, reasoning about each tool result before acting on it. The concept and per-model availability are covered in [Interleaved thinking](build-with-claude-thinking.md#interleaved-thinking) on the Thinking page; interleaving changes where thinking blocks appear, not whether tool calls can chain. The following comparison shows what interleaved thinking changes in a two-tool workflow:
### Tool use without interleaved thinking
Without interleaved thinking, Claude thinks once at the start of the assistant turn. Subsequent responses after tool results continue without new thinking blocks.
``` inline-block
User: "What's the total revenue if we sold 150 units at $50 each,
and how does this compare to our average monthly revenue?"
Response 1: [thinking] "I need to calculate 150 * $50, then check the database..."
[tool_use: calculator] { "expression": "150 * 50" }
↓ tool result: "7500"
Response 2: [tool_use: database_query] { "query": "SELECT AVG(revenue)..." }
↑ no thinking block
↓ tool result: "5200"
Response 3: [text] "The total revenue is $7,500, which is 44% above your
average monthly revenue of $5,200."
↑ no thinking block
```
### Tool use with interleaved thinking
With interleaved thinking enabled, Claude can think after receiving each tool result, allowing it to reason about intermediate results before continuing.
``` inline-block
User: "What's the total revenue if we sold 150 units at $50 each,
and how does this compare to our average monthly revenue?"
Response 1: [thinking] "I need to calculate 150 * $50 first..."
[tool_use: calculator] { "expression": "150 * 50" }
↓ tool result: "7500"
Response 2: [thinking] "Got $7,500. Now I should query the database to compare..."
[tool_use: database_query] { "query": "SELECT AVG(revenue)..." }
↑ thinking after receiving calculator result
↓ tool result: "5200"
Response 3: [thinking] "$7,500 vs $5,200 average - that's a 44% increase..."
[text] "The total revenue is $7,500, which is 44% above your
average monthly revenue of $5,200."
↑ thinking before final answer
```
## Next steps
[Thinking](build-with-claude-thinking.md)
The overview: turn thinking on, read thinking output, and review the full rules for tool use, caching, and streaming.
[Steering thinking](build-with-claude-thinking-steering-and-cost.md)
Steer how often and how deeply Claude thinks with effort levels and prompt-based guidance.
[Extended thinking](build-with-claude-extended-thinking.md)
Manual thinking budgets on older models: `budget_tokens` mechanics and migration to adaptive.
---
## Troubleshooting thinking - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting
Path: 04-API-Reference/Guides/build-with-claude-thinking-troubleshooting.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fthinking-troubleshooting)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
[Overview](build-with-claude-thinking.md)[Steering and cost control](build-with-claude-thinking-steering-and-cost.md)[Tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md)[Preserved thinking](build-with-claude-preserved-thinking.md)[Troubleshooting](build-with-claude-thinking-troubleshooting.md)[Extended thinking (legacy)](build-with-claude-extended-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Thinking
# Troubleshooting thinking
Copy page
Diagnose and fix the most common thinking failures: configuration 400 errors, empty or missing thinking blocks, max_tokens stops, and cache misses.
Copy page
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
This page covers the most common failures when configuring thinking or round-tripping thinking blocks (sending returned thinking blocks back in later requests). The first section maps each model to its supported thinking configurations and the ones it rejects; the sections after it each start from a symptom you observe, so you can match an error message or unexpected response directly to its cause and fix. To learn how thinking works, see the [Thinking](build-with-claude-thinking.md) overview.
## Thinking support, defaults, and rejected configurations by model
Most thinking configuration errors are a mismatch between the `thinking.type` value in the request and what the model supports. On most models, thinking runs as `thinking: {type: "adaptive"}`, and many have it on by default. Some earlier models instead use [extended thinking](build-with-claude-extended-thinking.md), a legacy manual mode configured as `thinking: {type: "enabled", budget_tokens: N}`.
Extended thinking (`thinking.type: "enabled"` with `budget_tokens`) is deprecated on the Claude 4.6 models (requests using it still succeed). Claude 4.7 and later models do not support it and reject requests that use it, returning a 400 error. On Claude 4.5 and earlier models that support thinking, extended thinking is the only available thinking mode. Claude Mythos Preview supports both modes. Where both modes are available, use [adaptive thinking](build-with-claude-thinking.md) instead.
The table lists what each model supports, what it defaults to, and which `thinking.type` values it rejects with a 400 error; any value not listed as rejected is accepted.
| Model | Thinking types | Default | Rejected with 400 |
|:----------------------|:---------------------------------|:----------|:---------------------------|
| Claude Fable 5.1 | Adaptive only | Always on | `"enabled"`, `"disabled"` |
| Claude Mythos 5.1 | Adaptive only | Always on | `"enabled"`, `"disabled"` |
| Claude Fable 5 | Adaptive only | Always on | `"enabled"`, `"disabled"` |
| Claude Mythos 5 | Adaptive only | Always on | `"enabled"`, `"disabled"` |
| Claude Mythos Preview | Adaptive, extended | Always on | `"disabled"` |
| Claude Opus 5.5 | Adaptive only | Always on | `"enabled"`, `"disabled"` |
| Claude Opus 5 | Adaptive only | On | `"enabled"`, `"disabled"`² |
| Claude Opus 4.8 | Adaptive only | Off | `"enabled"` |
| Claude Opus 4.7 | Adaptive only | Off | `"enabled"` |
| Claude Sonnet 5 | Adaptive only | On | `"enabled"` |
| Claude Opus 4.6 | Adaptive, extended (deprecated)¹ | Off | None |
| Claude Sonnet 4.6 | Adaptive, extended (deprecated)¹ | Off | None |
| Claude Opus 4.5 | Extended only | Off | `"adaptive"` |
| Claude Haiku 4.5 | Extended only | Off | `"adaptive"` |
| Claude Sonnet 4.5 | Extended only | Off | `"adaptive"` |
*¹ `enabled` and `budget_tokens` still work on these models but are deprecated; use adaptive thinking instead.*
*² Claude Opus 5 accepts `"disabled"` at [effort](build-with-claude-effort.md) `high` or below; combining it with effort `xhigh` or `max` returns a 400 error. This restriction is enforced on each request.*
Models marked `Always on` cannot turn thinking off. Models marked `On` default to thinking but accept `thinking: {type: "disabled"}`.
Earlier Claude 4 models (Claude Opus 4.1, Claude Sonnet 4, and Claude Opus 4) support extended thinking only. See [Model deprecations](../../20-Models/about-claude-model-deprecations.md) for their availability. Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, and Claude Mythos 5 are not available under [zero data retention](../Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements) unless expressly authorized by Anthropic.
## A 400 error says `"thinking.type.enabled"` is not supported
The request fails with a 400 error whose message reads:
``` block
"thinking.type.enabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.
```
This happens because the model you requested has removed extended thinking (see the [per-model configuration table](#rejected-configurations)).
Switch the request to `thinking: {type: "adaptive"}` and steer thinking depth with `effort` instead of `budget_tokens`. [Migrating to adaptive thinking](build-with-claude-extended-thinking.md#migrating-to-adaptive-thinking) walks through the conversion.
## A 400 error says `"thinking.type.disabled"` is not supported
The request fails with a 400 error. On Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Opus 5.5, and Claude Mythos 5, the message reads:
``` block
"thinking.type.disabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.
```
On Claude Mythos Preview, the only one of these models that accepts extended thinking, the message reads:
``` block
"thinking.type.disabled" is not supported for this model. Thinking defaults to adaptive mode when not specified; use "thinking.type.enabled" with "budget_tokens" for extended thinking.
```
This happens because thinking is always on for all of these models (see the [per-model configuration table](#rejected-configurations)).
Omit the `thinking` parameter; these models think without any configuration. If your goal was to keep thinking text out of responses, use `display: "omitted"` instead of disabling thinking; see [Controlling thinking display](build-with-claude-thinking.md#controlling-thinking-display).
A 400 error on `"disabled"` can also occur on Claude Opus 5, which accepts `thinking: {type: "disabled"}` only at [effort](build-with-claude-effort.md) `high` or below: combining it with effort `xhigh` or `max` is rejected. Lower the effort level, or leave thinking on.
## A 400 error says adaptive thinking is not supported
The request fails with a 400 error whose message reads:
``` block
adaptive thinking is not supported on this model
```
This happens because the model supports only extended thinking (see the [per-model configuration table](#rejected-configurations)).
Use `thinking: {type: "enabled", budget_tokens: N}` instead; see [Extended thinking](build-with-claude-extended-thinking.md) for the configuration.
## A 400 error says thinking blocks cannot be modified
A request that returns tool results fails with a 400 `invalid_request_error` whose message contains:
``` block
`thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified
```
In multi-turn and tool-use conversations you send previous assistant messages, including their `thinking` and `redacted_thinking` blocks, back to the API, and the API verifies they arrive unmodified. This error happens when the assistant message you send back differs from the one the API returned, most often because your code filters content blocks by type and drops `redacted_thinking` blocks, or rebuilds the assistant message instead of echoing it.
Echo the assistant turn back verbatim, thinking blocks included. See [Preserving thinking blocks](build-with-claude-thinking.md#preserving-thinking-blocks) for the rules, and the worked round trip in [Thinking in tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md#two-turn-tool-use-round-trip) for correct code in every SDK.
## A 400 error says a thinking block signature is invalid
A request to Claude Fable 5.1 or Claude Opus 5.5 that replays earlier thinking blocks fails with a 400 `invalid_request_error` whose message reads:
``` block
messages.{i}.content.{j}: Invalid `signature` in `thinking` block. The block is bound to a different conversation. Remove the block, or set `thinking.block_binding.prefix_mismatch_behavior` to "drop_block".
```
If the request didn't send the `thinking-binding-controls-2026-08-01` beta header, the message adds `` That setting requires the `thinking-binding-controls-2026-08-01` value in the `anthropic-beta` header. ``
The message usually ends with a sentence naming what changed: the `system` prompt, the `tools` list, the first message or block that differs, content that is missing or new, or an earlier thinking block that is missing or out of order. That sentence is for people and logs. Its wording can change, so don't match on it in code.
If the message stops after `` Invalid `signature` in `thinking` block ``, the signature itself didn't verify: it was truncated, altered, or sent back empty, and `prefix_mismatch_behavior` doesn't apply. Edited thinking text returns a different error. See [A 400 error says thinking blocks cannot be modified](#error-thinking-blocks-modified).
On Claude Fable 5.1 and Claude Opus 5.5, the API accepts a replayed thinking block only while the `system` prompt, `tools`, and messages that preceded it are unchanged. See [Keeping the prefix unchanged](build-with-claude-preserved-thinking.md#prefix-check). The error means something earlier in the conversation changed between requests: an edited, reordered, or removed turn, a per-turn reminder that was injected and later removed, a rebuilt `system` prompt or `tools` array, or client-side compaction that kept recent turns and their thinking verbatim. The check is enforced for new accounts created on or after August 31, 2026, and for any request that sets `thinking.block_binding.prefix_mismatch_behavior`. Server-side [compaction](build-with-claude-compaction.md) and [context editing](build-with-claude-context-editing.md) never trigger it.
To fix it, keep the history append-only: pass earlier turns back exactly as sent and received, add instructions with a [mid-conversation system message](build-with-claude-mid-conversation-system-messages.md) instead of editing `system` or `tools`, and let server-side [context editing](build-with-claude-context-editing.md) or [compaction](build-with-claude-compaction.md) do any trimming. Retrying the same request body doesn't clear the error. To continue this request without the invalidated reasoning, send the `thinking-binding-controls-2026-08-01` beta header and set `thinking.block_binding.prefix_mismatch_behavior` to `"drop_block"`. Alternatively, strip every `thinking` and `redacted_thinking` block from the history (at minimum the named block and every one after it, in that turn and all later turns), leave each turn's other blocks in place, and retry once.
A block from a model the target model can't read never produces this error: the API drops it and, under the beta header, reports it in `input_transformations`.
## The thinking field is empty in the response
The response contains `thinking` blocks, but their `thinking` field is an empty string and only the `signature` field is populated.
This happens because `display` defaults to `"omitted"` on newer models, which returns thinking blocks without their text.
Set `display: "summarized"` in your thinking configuration to receive the summarized thinking text. See [Controlling thinking display](build-with-claude-thinking.md#controlling-thinking-display) for the defaults per model. If you only want the short status lines some models write between tool calls, and not the reasoning, set `display: "updates"` (beta) instead. See [Progress updates between tool calls](build-with-claude-thinking.md#progress-updates).
A block whose `thinking` field is empty is still complete: the `signature` holds the reasoning. Send it back with the turn like any other. See [Send assistant turns back exactly as returned](build-with-claude-preserved-thinking.md#append-assistant-turns-exactly-as-returned).
## No thinking block appears on some turns
Some responses contain no `thinking` block at all, even though thinking is configured.
This is normal in adaptive mode: Claude skips thinking on requests it judges simple enough to answer directly.
If you want thinking more often or more deeply, raise `effort` or steer with prompting; see [Steering how often Claude thinks](build-with-claude-thinking-steering-and-cost.md#tuning-thinking-behavior).
## Tool calls or XML tags appear in the text output
A response occasionally writes a tool call into its text instead of emitting a `tool_use` block, or includes `<thinking>` or other internal XML tags in its visible text. A leaked tool call never runs, and in agentic loops the leaked text stays in the conversation history, so later turns are affected as well.
This happens on Claude Opus 5 when thinking is disabled, most commonly on tool-heavy workloads such as search. System-prompt rules instructing the model not to think or not to reason increase the tag leakage.
Re-enable thinking (the default) and use lower `effort` levels to control token cost instead. If your integration must keep thinking disabled, apply the prompting mitigations in [Running with thinking disabled](../../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-opus-5.md#running-with-thinking-disabled).
## The response stops with `stop_reason: "max_tokens"`
The response ends with `stop_reason: "max_tokens"`, often with a truncated or missing text block.
This happens because thinking tokens count toward `max_tokens`, so a long thinking pass can consume the budget before the text response completes.
Raise `max_tokens` to leave room for both thinking and text, or lower `effort` so Claude spends less on thinking; see [Cost control](build-with-claude-thinking-steering-and-cost.md#cost-control) and [Thinking and the context window](build-with-claude-thinking.md#thinking-and-the-context-window).
## Cache hits drop after changing thinking settings
`cache_read_input_tokens` falls to zero on requests that previously hit the cache.
This happens because the thinking configuration and the effort level (or its default) are part of the cached prompt prefix, so changing any of them starts a new prefix: switching thinking modes, changing the effort value, and changing `budget_tokens` all invalidate message cache breakpoints, and can invalidate tool and system-prompt breakpoints too, depending on where the model renders the configuration.
Keep the thinking configuration and effort level constant across requests that share a conversation; setting a parameter explicitly to its default is equivalent to omitting it and does not invalidate. See [Thinking and prompt caching](build-with-claude-thinking.md#thinking-and-prompt-caching).
## Setting effort does not change thinking
You change `effort` but thinking frequency or depth stays the same.
This happens because effort is the primary thinking lever only in adaptive mode. On extended-thinking-only models, thinking depth is set by `budget_tokens` instead.
Adjust `budget_tokens` on those models, or check which mode your model runs in; see [Thinking and effort](build-with-claude-thinking.md#thinking-and-effort). On Claude Opus 4.5, the one extended-thinking-only model that supports effort, effort composes with the budget; see [Budget rules and tuning](build-with-claude-extended-thinking.md#budget-rules-and-tuning).
## Next steps
[Thinking](build-with-claude-thinking.md)
The overview: what thinking is, how to configure it, and how it interacts with tools, caching, and streaming.
[Errors](../Endpoints/errors.md)
The full error reference, including the thinking configuration 400s with their exact server messages.
[Migrating to adaptive thinking](build-with-claude-extended-thinking.md#migrating-to-adaptive-thinking)
Convert `budget_tokens` requests to adaptive thinking with effort.
---
## Thinking - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/thinking
Path: 04-API-Reference/Guides/build-with-claude-thinking.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fthinking)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
[Overview](build-with-claude-thinking.md)[Steering and cost control](build-with-claude-thinking-steering-and-cost.md)[Tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md)[Preserved thinking](build-with-claude-preserved-thinking.md)[Troubleshooting](build-with-claude-thinking-troubleshooting.md)[Extended thinking (legacy)](build-with-claude-extended-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Thinking
# Thinking
Copy page
Understand how Claude's thinking works: turn it on, read thinking output, steer thinking depth with effort, and use thinking with tools, caching, and streaming.
Copy page
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
A model that answers in a single pass has to get everything right on the first try: no scratch work, no checking, no changing course halfway through. For a proof, a tricky bug, or a long agentic task, the first approach is often not the best one.
Thinking removes that constraint. When thinking is active, Claude works through the problem in its own words before answering: it restates what is being asked, tries approaches, checks intermediate results, and abandons paths that do not hold up. That reasoning arrives in `thinking` content blocks ahead of the response, and Claude draws on it to produce the final answer. This is why thinking improves performance on complex tasks like math, coding, analysis, and long-running agentic work, where the quality of the answer depends on intermediate work that would otherwise be compressed into the response itself or skipped.
Thinking has a cost: the tokens Claude spends reasoning are billed as output tokens, even when the thinking text isn't returned to you, and they count toward `max_tokens` alongside the response text. This page covers how thinking behaves across the API surface: turning it on, reading its output, and managing its interactions with tools, streaming, caching, and the context window.
## How thinking works
Whether Claude thinks on a given request, and how deeply, depends on your thinking configuration and the complexity of the request.
Here is what thinking looks like in a response: one or more `thinking` content blocks arrive before the `text` blocks. The thinking block is still generated content, like the `text` block that follows it, but it is separated from the canonical response. Each thinking block also carries a `signature` field, an encrypted copy of the full reasoning that you pass back unchanged in multi-turn and tool-use conversations (see [Thinking encryption](#thinking-encryption)):
```python
{
"content": [
{
"type": "thinking",
"thinking": "Let me break this down. The question has two parts, so I'll start with the simpler one and use its result to constrain the second...",
"signature": "WaUjzkypQ2mUEVM36O2Txu...."
},
{
"type": "text",
"text": "Based on my analysis..."
}
]
}
```
You don't always see this text, and what you see is never the raw chain of thought: the text in a thinking block is a [summary of Claude's reasoning](#summarized-thinking). The `display` field on the thinking configuration controls whether that summary is returned at all: `"summarized"` returns it, while `"omitted"`, the default on many models, returns thinking blocks with an empty `thinking` field. Either way the block is billed the same and passed back the same in multi-turn conversations. See [Controlling thinking display](#controlling-thinking-display) for per-model defaults and details.
If Claude uses tools, thinking can also appear between tool calls. See [Thinking with tool use](#thinking-with-tool-use). For the full response format, see the [Messages API reference](../Endpoints/messages-create.md).
## Configuring thinking
On most models, thinking is on by default or one parameter away. Which configuration each model accepts, and what it defaults to, is listed in the [per-model configuration table](build-with-claude-thinking-troubleshooting.md#supported-models) on the Troubleshooting page.
On Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5, Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, and Claude Mythos Preview, thinking is already on and needs no configuration. `display` defaults to `"omitted"` on these models, so the thinking text is hidden until you opt in. Opt in with `thinking: {"type": "adaptive", "display": "summarized"}`, which is exactly the following request with the [model string](../../20-Models/about-claude-models-overview.md) swapped.
On Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, and Claude Sonnet 4.6, thinking is off until you set `thinking: {type: "adaptive"}`, which lets Claude decide when and how deeply to think based on the request. The following examples do that, set `display: "summarized"` so the thinking text is visible, and use a roomy `max_tokens`:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=16000,
thinking={"type": "adaptive", "display": "summarized"},
messages=[
{
"role": "user",
"content": "What is the greatest common divisor of 1071 and 462?",
}
],
)
for block in response.content:
match block.type:
case "thinking":
print(f"\nThinking: {block.thinking}")
case "text":
print(f"\nResponse: {block.text}")
```
Running the example prints the summarized thinking, then the answer:
Output
``` block
Thinking: Use Euclidean algorithm.
1071 = 2*462 + 147
462 = 3*147 + 21
147 = 7*21 + 0
GCD = 21
Response: ## Finding GCD of 1071 and 462
I'll use the **Euclidean algorithm**, repeatedly dividing and taking remainders...
```
Thinking tokens count toward `max_tokens`, so set it high enough to leave room for both the thinking and the response text. See [Cost control](build-with-claude-thinking-steering-and-cost.md#cost-control) on the steering page and [Thinking and the context window](#thinking-and-the-context-window).
### Turning thinking off
On Claude Sonnet 5, where thinking is on by default, you can turn it off:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=4096,
thinking={"type": "disabled"},
messages=[{"role": "user", "content": "Summarize this article in one sentence."}],
)
```
Claude Opus 5 also has thinking on by default and accepts `thinking: {type: "disabled"}` at [effort](build-with-claude-effort.md) `high` or below. At `xhigh` or `max` effort, thinking cannot be turned off: requests that combine `thinking: {type: "disabled"}` with those effort levels return a 400 error. This restriction is enforced on each request. With thinking disabled, Claude Opus 5 can occasionally emit tool calls as plain text or include internal XML tags in its visible output. See [Running with thinking disabled](../../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-opus-5.md#running-with-thinking-disabled) for prompting mitigations.
Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, Claude Opus 5.5, and Claude Mythos Preview reject `thinking: {type: "disabled"}`. Thinking can't be turned off on these models.
If your model supports only extended thinking (see the [per-model configuration table](build-with-claude-thinking-troubleshooting.md#supported-models)), configure it with `type: "enabled"` and a `budget_tokens` value instead. The [Extended thinking](build-with-claude-extended-thinking.md) page covers that configuration. And if any thinking configuration comes back with a 400 error, [Troubleshooting thinking](build-with-claude-thinking-troubleshooting.md) matches each error message to its fix.
## Reading thinking output
### Controlling thinking display
The `display` field on the thinking configuration controls how thinking content is returned in API responses. `display` works in both modes: set it alongside `type: "adaptive"` or `type: "enabled"`. It accepts these values:
- `"summarized"`: thinking blocks contain [summarized thinking](#summarized-thinking) text, a readable summary of Claude's reasoning. This is the default on Claude Opus 4.6, Claude Sonnet 4.6, and earlier models.
- `"omitted"`: thinking blocks are returned with an empty `thinking` field. The `signature` field still carries the encrypted full thinking for multi-turn continuity (see [Thinking encryption](#thinking-encryption)). This is the default on Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5, Claude Opus 4.8, Claude Opus 4.7, and [Claude Mythos Preview](../../22-Safety-Policy/glasswing.md).
- `"updates"` (beta): reasoning blocks are returned with an empty `thinking` field, as with `"omitted"`, and the short [progress updates](#progress-updates) some models write between tool calls come back as readable text. Requires the beta header `thinking-display-updates-2026-08-18`.
Set `display: "omitted"` when your application doesn't surface thinking content to users. The primary benefit is faster time-to-first-text-token when streaming: the server skips streaming thinking tokens entirely and delivers only the signature, so the final text response begins streaming sooner.
With `display: "omitted"`, the response contains `thinking` blocks with an empty `thinking` field:
Output
```python
{
"content": [
{
"type": "thinking",
"thinking": "",
"signature": "EosnCkYICxIMMb3LzNrMu..."
},
{
"type": "text",
"text": "The answer is 12,231."
}
]
}
```
Keep the following in mind when working with omitted thinking:
- You're still charged for the full thinking tokens. Omitting reduces latency, not cost.
- If you pass thinking blocks back in multi-turn conversations, pass them unchanged. The server decrypts the `signature` to reconstruct the original thinking for prompt construction (see [Preserving thinking blocks](#preserving-thinking-blocks)). Any text you place in the `thinking` field of a round-tripped omitted block is ignored.
- `display` is invalid with `thinking.type: "disabled"` (there is nothing to display).
- When using `thinking.type: "adaptive"` and the model skips thinking for a simple request, no thinking block is produced regardless of `display`.
- When streaming with `display: "omitted"`, no thinking text is streamed. Each thinking block streams a `thinking_delta` with an empty `thinking` string, then its `signature_delta`. With `display: "updates"`, only [progress-update blocks](#progress-updates) stream `thinking_delta` events that carry text. See [Streaming thinking](#streaming-thinking) for the event sequence.
The `signature` field is identical whichever `display` value you set. Switching `display` values between turns in a conversation is supported.
In the Ruby SDK, plain hashes take `display:` as the examples show. The typed `ThinkingConfigAdaptive` class names the parameter `display_` (trailing underscore, to avoid shadowing Ruby's `Kernel#display`). Either way, the wire field is still `display`.
### Summarized thinking
When `display` is `"summarized"`, the thinking text you receive is a summary of Claude's full thinking process rather than the raw chain of thought. Summarized thinking provides the full intelligence benefits of thinking while preventing misuse. No `display` setting returns the raw chain of thought.
Keep the following in mind when working with summarized thinking:
- You're charged for the full thinking tokens generated by the original request, not the summary tokens. The billed output token count does not match the count of tokens you see in the response.
- On Claude Opus 4.6, Claude Sonnet 4.6, and earlier models, the first few lines of thinking output are more verbose, providing detailed reasoning that's particularly helpful for prompt engineering purposes. [Claude Mythos Preview](../../22-Safety-Policy/glasswing.md) summarizes from the first token, so its thinking blocks do not show this verbose preamble.
- Summarization preserves the key ideas of Claude's thinking process with minimal added latency, so summaries can stream as they arrive.
- Summarization is processed by a different model from the one you target in your requests. The thinking model does not see the summarized output.
- As Anthropic seeks to improve the thinking feature, summarization behavior is subject to change.
In rare cases where you need access to full thinking output, [contact Anthropic sales](mailto:sales@anthropic.com).
To see the model's reasoning, read the `thinking` blocks rather than prompting for reasoning in the response text. On Claude Fable 5.1, Claude Opus 5.5, and Claude Fable 5, a request that attempts to elicit the model's internal reasoning as part of the response text can be refused with `stop_details.category: "reasoning_extraction"`. See [Refusal categories](build-with-claude-refusals-and-fallback.md#refusal-response) for the field reference and handling guidance.
### Streaming thinking
Thinking works with [streaming](build-with-claude-streaming.md). Thinking blocks stream as `thinking_delta` events inside `content_block_delta` events, followed by a single `signature_delta` event just before the block's `content_block_stop`. Text blocks stream afterward as usual.
The following examples stream a response with adaptive thinking, printing thinking and text deltas as they arrive:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=16000,
thinking={"type": "adaptive", "display": "summarized"},
messages=[
{
"role": "user",
"content": "What is the greatest common divisor of 1071 and 462?",
}
],
) as stream:
for event in stream:
match event.type:
case "content_block_start":
print(f"\nStarting {event.content_block.type} block...")
case "content_block_delta":
delta = event.delta
match delta.type:
case "thinking_delta":
print(delta.thinking, end="", flush=True)
case "text_delta":
print(delta.text, end="", flush=True)
```
To reassemble complete thinking blocks with their signatures after streaming, use your SDK's message-accumulation helper, `stream.get_final_message()`, instead of concatenating deltas yourself.
### Full streaming event trace
Output
```python
event: message_start
data: {"type": "message_start", "message": {"id": "msg_01...", "type": "message", "role": "assistant", "content": [], "model": "claude-opus-4-8", "stop_reason": null, "stop_sequence": null}}
event: content_block_start
data: {"type": "content_block_start", "index": 0, "content_block": {"type": "thinking", "thinking": "", "signature": ""}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "I need to find the GCD of 1071 and 462 using the Euclidean algorithm.\n\n1071 = 2 × 462 + 147"}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\n462 = 3 × 147 + 21\n147 = 7 × 21 + 0\n\nSo GCD(1071, 462) = 21"}}
// Additional thinking deltas...
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "signature_delta", "signature": "EqQBCgIYAhIM1gbcDa9GJwZA2b..."}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 0}
event: content_block_start
data: {"type": "content_block_start", "index": 1, "content_block": {"type": "text", "text": ""}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 1, "delta": {"type": "text_delta", "text": "The greatest common divisor of 1071 and 462 is **21**."}}
// Additional text deltas...
event: content_block_stop
data: {"type": "content_block_stop", "index": 1}
event: message_delta
data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence": null}}
event: message_stop
data: {"type": "message_stop"}
```
When `display: "omitted"` is set, the thinking block opens, a `thinking_delta` with an empty `thinking` string arrives, a single `signature_delta` follows, and the block closes. Text streaming begins immediately after:
Output
```python
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":"","signature":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"thinking_delta","thinking":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"signature_delta","signature":"EosnCkYICxIMMb3LzNrMu..."}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"text","text":""}}
```
With `display: "updates"` (beta), reasoning blocks stream as they do under `"omitted"`. Each [progress-update block](#progress-updates) streams its text as `thinking_delta` events before the `tool_use` block it introduces. A pause of several seconds before the progress-update block opens is normal:
Output
```python
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"thinking","thinking":"","signature":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"thinking_delta","thinking":"Confirmed the retry path never refreshes the expired token. Editing auth.py to add the refresh call."}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"signature_delta","signature":"Es8CCkYICxIM..."}}
event: content_block_stop
data: {"type":"content_block_stop","index":1}
event: content_block_start
data: {"type":"content_block_start","index":2,"content_block":{"type":"tool_use","id":"toolu_01D7FLrfh4GYq7yT1ULFeyMV","name":"edit_file","input":{}}}
```
Under `"updates"`, treat a block as a progress update as soon as one of its `thinking_delta` events carries non-empty text.
When using streaming with thinking enabled, you might notice that text sometimes arrives in larger chunks alternating with smaller, token-by-token delivery. This is expected behavior, especially for thinking content.
The streaming system processes content in batches, which can delay and group streaming events into this "chunky" delivery pattern.
For general streaming mechanics, see [Streaming Messages](build-with-claude-streaming.md).
## Thinking and effort
The `thinking` parameter controls whether Claude thinks in [thinking blocks](build-with-claude-thinking.md) before answering; the `effort` parameter controls how much work Claude puts into the whole response, which in adaptive mode includes how often and how deeply it thinks. Don't pass `adaptive` as an `effort` value: `adaptive` is a thinking mode, not an effort level.
To learn what each effort level does to thinking behavior, see the [per-level thinking behavior table](build-with-claude-thinking-steering-and-cost.md#effort-levels) on the [Steering thinking](build-with-claude-thinking-steering-and-cost.md) page. The [Effort](build-with-claude-effort.md) page documents the parameter itself, including which levels each model supports. On Claude Opus 4.5, the only extended-thinking-only model that supports effort, effort composes with `budget_tokens`. See [Budget rules and tuning](build-with-claude-extended-thinking.md#budget-rules-and-tuning).
With the two controls separated this way, pick the one that matches your goal:
- **Lower cost or latency on a thinking-enabled workload:** lower `effort` first. It scales the whole response down, thinking included.
- **Claude is thinking too rarely or too shallowly:** raise `effort`, or see [Steering how often Claude thinks](build-with-claude-thinking-steering-and-cost.md#tuning-thinking-behavior) on the steering page.
- **You need thinking fully off:** use `thinking: {type: "disabled"}` on models that allow it (see the [per-model configuration table](build-with-claude-thinking-troubleshooting.md#supported-models)).
- **You need a hard ceiling on spend:** use `max_tokens`. Effort is soft guidance. `max_tokens` is a strict limit.
## Thinking with tool use
Thinking works alongside [tool use](../Agents-Tools/agents-and-tools-tool-use-overview.md), letting Claude reason through tool selection and process tool results. Two constraints apply:
1. **Tool choice limitation (manual mode):** tool use with manual extended thinking (`thinking: {type: "enabled"}`) only supports `tool_choice: {"type": "auto"}` (the default) or `tool_choice: {"type": "none"}`. Using `tool_choice: {"type": "any"}` or `tool_choice: {"type": "tool", "name": "..."}` results in an error because these options force tool use, which is incompatible with manual extended thinking. Adaptive thinking, including on models where thinking is on by default, supports forced tool use, except on Claude Opus 5.5, Claude Fable 5.1, and Claude Mythos 5.1 (see [Response prefill and forced tool use](#limits-and-feature-compatibility)).
2. **Preserving thinking blocks:** when you return tool results, you must pass the thinking blocks from the assistant message back to the API, complete and unmodified. See [Preserving thinking blocks](#preserving-thinking-blocks).
**A tool-use loop is one assistant turn.** From the model's perspective, an assistant turn doesn't complete until Claude finishes its full response, which may include multiple tool calls and results. This whole sequence is a single assistant turn:
``` block
User: "What's the weather in Paris?"
Assistant: [thinking] + [tool_use: get_weather]
User: [tool_result: "20°C, sunny"]
Assistant: [text: "The weather in Paris is 20°C and sunny"]
```
The entire turn runs in a single thinking mode: you can't toggle thinking in the middle of a turn, including during the tool-use loop. In extended (manual) mode, the API additionally enforces that the final assistant turn of a thinking-enabled request begins with a thinking block. Adaptive mode relaxes this: no assistant turn needs to start with one.
**Mid-turn conflicts degrade gracefully.** If you toggle thinking mid-turn (for example, between sending a tool call and returning its result), the API doesn't error. Instead, it silently disables thinking for that request. To preserve model quality, the API may strip thinking blocks that would create an invalid turn structure, or disable thinking when the conversation history is incompatible with thinking being enabled. To confirm whether thinking was active, check for the presence of `thinking` blocks in the response.
**Toggle between turns, not within them.** Plan your thinking strategy at the start of each turn. Complete the assistant turn, then change the thinking configuration for the next one:
``` block
User: "What's the weather?"
Assistant: [tool_use] (thinking disabled)
User: [tool_result]
Assistant: [text: "It's sunny"]
User: "What about tomorrow?"
Assistant: [thinking] + [text: "..."] (thinking enabled - new turn)
```
Toggling thinking modes also invalidates prompt caching. See [Thinking and prompt caching](#thinking-and-prompt-caching).
### Preserving thinking blocks
When Claude invokes a tool, it pauses construction of its response to await external information. When you return the tool result, Claude continues building that same response, so its earlier reasoning must still be present. Pass every `thinking` block back to the API complete and unmodified, alongside the `tool_use` block it accompanied. This matters for two reasons:
1. **Reasoning continuity:** the thinking blocks capture the step-by-step reasoning that led to the tool requests. Including them lets Claude continue reasoning from where it left off.
2. **Context maintenance:** tool results appear as user messages in the API structure, but they're part of one continuous reasoning flow. Preserving thinking blocks maintains that flow across API calls.
In short:
- **Required:** within a tool-use turn, pass thinking blocks back.
- **Recommended:** across turns, pass everything back.
- **Allowed:** outside tool use, omit prior turns' thinking.
You don't need to prune old thinking yourself. Pass all thinking blocks back in multi-turn conversations, and the API automatically filters them, keeps the blocks needed to preserve the model's reasoning, and bills input tokens only for the blocks actually shown to Claude. Which prior-turn blocks are kept is per-model. See [Thinking block preservation by model](#thinking-block-preservation-by-model). To override the default, use the [`clear_thinking_20251015` context-editing strategy](build-with-claude-context-editing.md#thinking-block-clearing).
Within the latest assistant message, the sequence of consecutive `thinking` blocks must match what the model generated in the original request: you can't rearrange, edit, or partially drop them. This includes [`redacted_thinking` blocks](#redacted-thinking-blocks).
Modified thinking blocks are rejected with a 400 error. See [A 400 error says thinking blocks cannot be modified](build-with-claude-thinking-troubleshooting.md#error-thinking-blocks-modified) for the exact message, the common causes, and the fix. The one exception: text placed in the empty `thinking` field of an [omitted](#controlling-thinking-display) block is ignored rather than rejected.
For a complete two-turn walkthrough with code in every SDK, see [Thinking in tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md#two-turn-tool-use-round-trip). It defines a tool, receives a thinking-plus-tool-use response, and echoes the assistant turn back with the tool result.
### Interleaved thinking
Interleaved thinking lets Claude think between tool calls, reasoning about each tool result before acting on it. With interleaved thinking, Claude can:
- Reason about the results of a tool call before deciding what to do next
- Chain multiple tool calls with reasoning steps in between
- Make more nuanced decisions based on intermediate results
Consecutive tool calls do not require interleaved thinking. Claude can chain tool calls with or without interleaved thinking. Interleaving changes where thinking blocks appear between tool calls, not whether tool calls can chain.
With adaptive thinking, interleaved thinking is automatic on every model that supports adaptive thinking. No beta header is needed. On Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, Claude Mythos Preview, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, and Claude Opus 4.7, reasoning between tool calls always appears in thinking blocks. Claude Haiku 4.5 does not support interleaved thinking. On models using manual extended thinking, interleaving requires a beta header and changes how the thinking budget is counted. [Interleaved thinking in manual mode](build-with-claude-extended-thinking.md#interleaved-thinking) covers the per-model rules and platform-specific header behavior.
With interleaved thinking, the thinking allocation can span the entire assistant turn rather than a single response. Interleaved thinking is only supported for [tools used through the Messages API](../Agents-Tools/agents-and-tools-tool-use-overview.md).
For a worked comparison showing what interleaved thinking changes in a two-tool workflow, see [How interleaved thinking changes the flow](build-with-claude-thinking-tool-workflows.md#how-interleaved-thinking-changes-the-flow).
### Progress updates between tool calls
On Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, and Claude Fable 5, the model can write a progress update between tool calls. A progress update is a sentence or two on what the model just found and what it's about to do next, written for the person watching the agent rather than as reasoning. Each one comes back as its own `thinking` block with its own `signature`, separate from any reasoning block at the same point. It sits immediately before the `tool_use` or `server_tool_use` block it introduces. At most one progress update precedes each tool call, and the model can skip any of them. Progress updates aren't [interleaved thinking](#interleaved-thinking): they appear whether or not reasoning blocks appear between tool calls, and a response can contain both.
What a progress-update block contains depends on [`display`](#controlling-thinking-display):
| `display` | Reasoning blocks | Progress-update blocks |
|-------------------------------------------|------------------------|----------------------------------------------------------|
| `"omitted"` (the default on these models) | Empty `thinking` field | Empty `thinking` field |
| `"updates"` (beta) | Empty `thinking` field | Summary text |
| `"summarized"` | Summary text | Summary text, not distinguishable from a reasoning block |
Use `display: "updates"` for an agent interface that keeps reasoning hidden and shows the user a status line at each step. Under it, any `thinking` block with non-empty text is a progress update, so render those and nothing else. It's in beta and requires the beta header `thinking-display-updates-2026-08-18` (on Amazon Bedrock, Google Cloud, and Microsoft Foundry, pass the beta value as described in [Beta headers](../Endpoints/beta-headers.md)). Without it, the value is rejected with the same 400 `invalid_request_error` as an unknown `display` value.
```python
{
"model": "claude-fable-5-1",
"max_tokens": 16000,
"thinking": { "type": "adaptive", "display": "updates" },
"tools": [
{
"name": "edit_file",
"description": "Replace the contents of a file in the repository.",
"input_schema": {
"type": "object",
"properties": {
"path": { "type": "string" },
"content": { "type": "string" }
},
"required": ["path", "content"]
}
}
],
"messages": [
{
"role": "user",
"content": "The login test fails after an hour of uptime. Find out why and fix it."
}
]
}
```
Under `"updates"`, the start of the response that follows a `tool_result` looks like this. The first block is reasoning and stays empty, as it would under `"omitted"`. The second carries text, so it's a progress update. Under `"summarized"` both blocks carry text, and under `"omitted"` both are empty.
Output
```python
{
"content": [
{
"type": "thinking",
"thinking": "",
"signature": "EqMBCkYICxIM..."
},
{
"type": "thinking",
"thinking": "Confirmed the retry path never refreshes the expired token. Editing auth.py to add the refresh call.",
"signature": "Es8CCkYICxIM..."
},
{
"type": "tool_use",
"id": "toolu_01D7FLrfh4GYq7yT1ULFeyMV",
"name": "edit_file",
"input": { "path": "auth.py", "content": "..." }
}
]
}
```
Keep the following in mind when working with progress updates:
- Pass progress-update blocks back unchanged with the rest of the assistant turn, like any other `thinking` block.
- The text you receive is a summary of the progress update, normally a sentence or two. Don't rely on its length. The progress update counts toward `usage.output_tokens` at its full length, not the summary's.
- A progress-update block can come back with an empty `thinking` field under any `display` value. Render nothing for an empty block. Under `"updates"` it looks the same as an empty reasoning block and needs no separate handling.
- When a response stops on `max_tokens`, `model_context_window_exceeded`, or `stop_sequence` soon after a tool call or tool result, its last block can be a progress-update block standing in for the work the model hadn't finished. Under `"updates"` and `"summarized"` its text is exactly `This part of the response was interrupted before it finished.` and you can show it like any other update. Under `"omitted"` it's empty. To continue, pass the assistant turn back unchanged and append a new `user` message (with a `tool_result` for each `tool_use` block in that turn).
- When [streaming](#streaming-thinking), expect a pause of several seconds before a progress-update block opens. See the `"updates"` trace in [Streaming thinking](#streaming-thinking).
- These models write fewer progress updates at higher [effort](build-with-claude-effort.md) and in long tool chains. If your interface depends on them, see [Ask for user-facing progress updates](../../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-fable-5-1.md#ask-for-user-facing-progress-updates) or, for Claude Opus 5.5, [User-facing progress updates](../../10-Prompting-Guides/build-with-claude-prompt-engineering-prompting-claude-opus-5-5.md#user-facing-progress-updates).
### Thinking block preservation by model
Whether thinking blocks from previous assistant turns stay in context by default depends on the model:
- **Keep all prior turns:** Claude Opus 4.5 and later Opus models, Claude Sonnet 4.6 and later Sonnet models, Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, and Claude Mythos Preview.
- **Keep the last turn only:** earlier Opus and Sonnet models, and all Haiku models through Claude Haiku 4.5. When you pass older thinking blocks back, the API strips them automatically. You don't need to remove them yourself.
Preservation brings two benefits:
- **Cache optimization:** preserved thinking blocks enable cache hits during tool use, as they are passed back with tool results and cached incrementally across the assistant turn, resulting in token savings in multistep workflows.
- **No intelligence impact:** preserving thinking blocks has no negative effect on model performance.
The tradeoff is context usage: long conversations consume more context space on keep-all models, because retained thinking blocks count as input like any other conversation history (see [Thinking and the context window](#thinking-and-the-context-window)). The behavior is automatic in both regimes. No code changes or beta headers are required, and you should keep passing complete, unmodified thinking blocks back as described in [Preserving thinking blocks](#preserving-thinking-blocks). To override the default in either direction, use [thinking block clearing](build-with-claude-context-editing.md#thinking-block-clearing).
**Switching models mid-conversation.** Keep passing thinking blocks back unchanged when you switch models, for example after a [classifier refusal fallback](build-with-claude-refusals-and-fallback.md). A thinking block is readable only by the model that produced it and certain other models, and the API ignores or drops the blocks the target model can't read. On Claude Fable 5.1 and Claude Mythos 5.1 the direction matters: they read every earlier model's thinking blocks and no earlier model reads theirs, so switching up to them keeps the conversation's reasoning and switching down drops it (see [how dropped blocks are billed and reported](build-with-claude-preserved-thinking.md#switching-models)). Claude Opus 5.5 reads Claude Opus 5's thinking blocks and those of earlier Opus, Sonnet, and Haiku models, but not those of the Claude Fable and Claude Mythos models; on the Claude API, Claude Fable 5.1 and Claude Mythos 5.1 read Claude Opus 5.5's blocks. A switch from Claude Opus 5.5 up to Claude Fable 5.1 on the Claude API keeps the earlier turns' reasoning; a switch from Claude Fable 5.1 to Claude Opus 5.5 drops it. Strip prior `thinking` and `redacted_thinking` blocks yourself only to save input tokens on models that ignore rather than drop them, and never when redeeming a [fallback credit](build-with-claude-fallback-credit.md), which requires the body unchanged.
## Preserved thinking
[Preserved thinking](build-with-claude-preserved-thinking.md) decides whether the model can use a thinking block that you send back from an earlier turn. Starting with Claude Fable 5.1, the API checks the `signature` of every `thinking` or `redacted_thinking` block in a request for two things:
- **The model that produced it.** Each model reads its own thinking blocks and those of a fixed set of other models. Claude Fable 5.1 reads blocks from Claude Opus 5 and, on the Claude API, from Claude Opus 5.5; neither Claude Opus 5 nor Claude Opus 5.5 reads blocks from Claude Fable 5.1. The API drops a block the current model can't read, without an error and without billing it. See [Switching models mid-conversation](build-with-claude-preserved-thinking.md#switching-models).
- **Everything sent before it.** A block stays valid only while the top-level `system` prompt, the `tools`, and the messages before it are unchanged. If any of them changes, that block and every later thinking block are invalid, and the API rejects the request with a 400 error or drops the invalid blocks, whichever you choose. See [Keeping the prefix unchanged](build-with-claude-preserved-thinking.md#prefix-check).
The model check applies to every account. The API enforces the prefix check by default for accounts created on or after August 31, 2026, 00:00 UTC. On older accounts it enforces the check only on requests that set `thinking.block_binding.prefix_mismatch_behavior`. Make your integration append-only regardless of your account's age, so the same code works on every account, including newer accounts enforced by default.
To keep thinking valid, send every assistant turn back exactly as you received it and add new messages only at the end of `messages`. If your code builds the `messages` array itself, the Preserved thinking page covers:
- [What counts as an edit](build-with-claude-preserved-thinking.md#what-counts-as-an-edit), and [how to check whether your code makes one](build-with-claude-preserved-thinking.md#how-to-tell-whether-your-integration-is-impacted).
- [The API feature that replaces each common edit](build-with-claude-preserved-thinking.md#replace-prefix-edits): mid-conversation system messages for new instructions and per-turn reminders, `tool_addition` and `tool_removal` blocks for tool changes, per-message `output_config` for effort changes, and server-side compaction and context editing for trimming.
- [Client-side compaction](build-with-claude-preserved-thinking.md#custom-compaction-on-the-client): which patterns keep thinking valid and which don't.
- [The `thinking-binding-controls-2026-08-01` beta header](build-with-claude-preserved-thinking.md#preserved-thinking-controls). It adds a `block_binding.prefix_mismatch_behavior` field (`"error"` or `"drop_block"`) to the thinking configuration and an `input_transformations` array to every response. The array lists each thinking block that the API dropped, or that failed the prefix check and was let through.
## Thinking and prompt caching
[Prompt caching](build-with-claude-prompt-caching.md) interacts with thinking in a few specific ways. The following rules apply in both thinking modes.
**Configuration changes invalidate caching.** The thinking configuration and the resolved [`effort`](build-with-claude-effort.md) level are rendered into the prompt itself, so changing any of them starts a new cache prefix. Switching between `adaptive`, `enabled`, and `disabled`, changing `budget_tokens`, and changing the effort value all invalidate cache breakpoints: message-level breakpoints always miss, and tool and system-prompt breakpoints can miss too, depending on where the model renders the configuration. Treat any thinking or top-level effort change as starting the cache over. On models that support [per-message effort](build-with-claude-effort.md#change-effort-mid-conversation-beta), an effort change carried in a `role: "system"` message inside `messages` leaves the cached prefix intact. Consecutive requests that keep the same configuration preserve the cache, and setting a parameter explicitly to its default value is equivalent to omitting it. A thinking block the API drops under either [preserved-thinking condition](#preserved-thinking) changes the cached prefix from that block's position onward. Blocks passed back unchanged keep the cache intact. A worked demonstration with usage output is on the [Steering thinking](build-with-claude-thinking-steering-and-cost.md#prompt-caching) page.
**Thinking blocks are cached with tool results.** During a tool-use loop, caching occurs when you make a follow-up request that includes tool results. At that point the previous conversation history, including its thinking blocks, can be cached, and those cached thinking blocks count as input tokens in your usage metrics when read from the cache. This occurs automatically, even without explicit `cache_control` markers, and behaves the same for regular and interleaved thinking. The tradeoff: thinking blocks you never see again in responses still contribute to input token usage when read from cache.
**Whether prior blocks are in context at all is per-model.** The [preservation default](#thinking-block-preservation-by-model) governs this. On keep-all models, previous turns' thinking blocks stay cached and in context. On last-turn-only models, once you send a user message that isn't a tool result, all previous thinking blocks are stripped from context. On those models, a conversation like this:
``` block
User: ["What's the weather in Paris?"],
Assistant: [thinking_block_1] + [tool_use block 1],
User: [tool_result_1, cache=True],
Assistant: [thinking_block_2] + [text block 2],
User: [Text response, cache=True]
```
is processed as if the thinking blocks were never there:
``` block
User: ["What's the weather in Paris?"],
Assistant: [tool_use block 1],
User: [tool_result_1, cache=True],
Assistant: [text block 2],
User: [Text response, cache=True]
```
On keep-all models, the same request keeps `thinking_block_1` and `thinking_block_2` in context and in the cache.
**Degradation strips thinking from the cacheable history.** If thinking becomes disabled mid-turn and you pass thinking content in the current tool-use turn, the thinking content is stripped and thinking remains disabled for that request (see [graceful degradation](#thinking-with-tool-use)). [Interleaved thinking](#interleaved-thinking) amplifies cache invalidation effects, because thinking blocks can occur between multiple tool calls.
Thinking-heavy tasks often take longer than the default 5-minute cache lifetime to complete. Consider the [1-hour cache duration](build-with-claude-prompt-caching.md#1-hour-cache-duration) to maintain cache hits across longer thinking sessions and multistep workflows.
## Thinking and the context window
`max_tokens`, which includes all thinking Claude generates in the current turn, is enforced as a strict limit. On Claude 4.5 models and newer, if input tokens plus `max_tokens` exceeds the context window size, the API accepts the request. If generation then reaches the context window limit, it stops with `stop_reason: "model_context_window_exceeded"` instead of returning an error. On earlier models, the API returns a validation error instead. See [Handling stop reasons](build-with-claude-handling-stop-reasons.md).
How thinking counts against the window depends on when it was generated:
- **Current-turn thinking** always counts toward `max_tokens`, is billed as output tokens, and occupies context window space for the turn that generated it.
- **Prior-turn thinking** depends on the [preservation default](#thinking-block-preservation-by-model). On [models that keep all prior turns](#thinking-block-preservation-by-model), previous thinking blocks remain in context, count toward the window, and are billed as input tokens like the rest of the conversation history. On models that keep only the last turn, the API strips older thinking blocks automatically when you pass them back, so they don't consume window space or input tokens.
In practice:
- On keep-all models, budget your context window as if thinking were ordinary conversation history, because it is. Long agentic sessions accumulate thinking in context. Use [thinking block clearing](build-with-claude-context-editing.md#thinking-block-clearing) if you need to reclaim space.
- On last-turn-only models, thinking is a per-turn cost only: each turn's thinking counts against that turn's `max_tokens` and then drops out of the window.
The following diagrams illustrate the last-turn-only (stripping) regime. The first shows a multi-turn conversation: each turn's thinking block is generated in the output but not carried into later turns' input.
The second shows the same regime with tool use: thinking stays in context alongside its tool result for the duration of the assistant turn, then drops out on the next user turn.
Use the [token counting API](build-with-claude-token-counting.md) to get accurate counts for your specific use case, especially for multi-turn conversations that include thinking.
## Thinking encryption
Full thinking content is encrypted and returned in the `signature` field on each thinking block. The API uses the signature to verify that thinking blocks were generated by Claude when you pass them back.
Keep the following in mind when working with signatures:
- It is only strictly necessary to send back thinking blocks when [using tools with thinking](#thinking-with-tool-use). Otherwise you can omit thinking blocks from previous turns. If you do pass them back, whether the API keeps or strips them depends on the model (see [Thinking block preservation by model](#thinking-block-preservation-by-model)). Use [context editing](build-with-claude-context-editing.md) to configure this.
- When sending back thinking blocks, pass everything back exactly as you received it, for consistency and to avoid potential issues.
- When [streaming responses](#streaming-thinking), the signature arrives as a `signature_delta` inside a `content_block_delta` event just before the `content_block_stop` event.
- `signature` values are significantly longer in Claude 4 and later models than in previous models.
- The `signature` field is opaque: don't interpret or parse it.
- `signature` values are compatible across platforms (the Claude API, [Amazon Bedrock](build-with-claude-claude-in-amazon-bedrock.md), and [Google Cloud](build-with-claude-claude-on-vertex-ai.md)). Values generated on one platform work on another.
## Redacted thinking blocks
In addition to regular `thinking` blocks, the API may return `redacted_thinking` blocks when portions of Claude's reasoning are safety-redacted. A `redacted_thinking` block contains encrypted thinking content in a `data` field, with no readable text:
```python
{
"type": "redacted_thinking",
"data": "..."
}
```
The `data` field is opaque and encrypted. Like the `signature` field on regular thinking blocks, pass `redacted_thinking` blocks back to the API unchanged when continuing a multi-turn conversation with [tools](#thinking-with-tool-use).
If your code filters content blocks by type (for example, `block.type == "thinking"`) when round-tripping responses with tool use, also include `redacted_thinking` blocks. Filtering on `block.type == "thinking"` alone silently drops `redacted_thinking` blocks and breaks the multi-turn protocol described in [Preserving thinking blocks](#preserving-thinking-blocks).
`redacted_thinking` blocks are a distinct content block type returned when thinking is safety-redacted. This is separate from the [`display: "omitted"`](#controlling-thinking-display) option, which returns regular `thinking` blocks with an empty `thinking` field.
## Limits and feature compatibility
### Sampling parameters
On Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, Claude Mythos Preview, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, and Claude Sonnet 5, non-default `temperature`, `top_p`, or `top_k` values return a 400 error on every request, regardless of whether thinking is used. On older models, the restriction applies only while thinking is on: `temperature` and `top_k` are incompatible with thinking, and `top_p` is allowed at values between 0.95 and 1.
### Response prefill and forced tool use
You can't prefill the assistant response while thinking is on. Forced tool use (`tool_choice: {"type": "any"}` or `{"type": "tool", ...}`) is incompatible with manual extended thinking but works with adaptive thinking. The exceptions are Claude Opus 5.5, Claude Fable 5.1, and Claude Mythos 5.1, which reject forced tool use on every request with a 400 error. On those models, use `tool_choice: {"type": "auto"}` with [strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md) or [structured outputs](build-with-claude-structured-outputs.md) instead. See [Thinking with tool use](#thinking-with-tool-use).
### Output limits
Each model accepts `max_tokens` up to the ceiling listed here. On the [Message Batches API](build-with-claude-batch-processing.md#extended-output-beta), the `output-300k-2026-03-24` [beta header](../Endpoints/beta-headers.md) raises that ceiling for the models with a batches ceiling listed.
| Model | Max output tokens | Batches beta ceiling |
|-----------------------|-------------------|----------------------|
| Claude Fable 5.1 | 128K | — |
| Claude Mythos 5.1 | 128K | — |
| Claude Fable 5 | 128K | — |
| Claude Mythos 5 | 128K | — |
| Claude Mythos Preview | 128K | Not available |
| Claude Opus 5.5 | 128K | 300K |
| Claude Opus 5 | 128K | 300K |
| Claude Opus 4.8 | 128K | 300K |
| Claude Opus 4.7 | 128K | 300K |
| Claude Opus 4.6 | 128K | 300K |
| Claude Opus 4.5 | 64K | Not available |
| Claude Sonnet 5 | 128K | 300K |
| Claude Sonnet 4.6 | 128K | 300K |
| Claude Sonnet 4.5 | 64K | Not available |
| Claude Haiku 4.5 | 64K | Not available |
See the [models overview](../../20-Models/about-claude-models-overview.md) for limits on legacy models.
### Long requests
The SDKs require streaming when `max_tokens` is greater than 21,333, to avoid HTTP timeouts on long-running requests. This is a client-side validation, not an API restriction. If you don't need to process events incrementally, use `.stream()` with `.get_final_message()` to get the complete `Message` object without assembling it from individual events yourself. See [Streaming Messages](build-with-claude-streaming.md#get-the-final-message-without-handling-events). Expect longer response times when thinking is active, because generating thinking blocks adds processing time. For workloads that push thinking above roughly 32k tokens per request, use [batch processing](build-with-claude-batch-processing.md) to avoid networking issues: such requests can run long enough to hit system timeouts and open connection limits.
## Next steps
[Steering thinking](build-with-claude-thinking-steering-and-cost.md)
Steer how often and how deeply Claude thinks with effort levels, system prompt guidance, and per-message steering, and understand thinking's cost and pricing.
[Thinking in tool and multi-turn workflows](build-with-claude-thinking-tool-workflows.md)
Walk through a complete two-turn tool-use round trip that preserves thinking blocks correctly, and see how interleaved thinking changes the flow.
[Preserved thinking](build-with-claude-preserved-thinking.md)
Find out whether your Messages API integration edits conversation history, and replace each edit with the API feature that keeps earlier thinking blocks valid.
[Troubleshooting thinking](build-with-claude-thinking-troubleshooting.md)
Diagnose and fix the most common thinking failures: configuration 400 errors, empty or missing thinking blocks, max_tokens stops, and cache misses.
[Effort](build-with-claude-effort.md)
Control how many tokens Claude uses when responding with the effort parameter, trading off between response thoroughness and token efficiency.
---
## Token counting - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/token-counting
Path: 04-API-Reference/Guides/build-with-claude-token-counting.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Ftoken-counting)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Context management
# Token counting
Copy page
Count the tokens in a message before you send it to Claude. Use token counts to manage rate limits and costs, make model routing decisions, and fit prompts to a target length.
Copy page
Token counting
[ZDR](../Other/manage-claude-api-and-data-retention.md)
Eligible
excludes [Covered Models](../Other/manage-claude-api-and-data-retention.md#model-specific-data-retention-requirements)
Token counting lets you determine the number of tokens in a message before you send it to Claude. This helps you make informed decisions about your prompts and usage. With token counting, you can:
- Proactively manage rate limits and costs
- Make smart model routing decisions
- Optimize prompts to a specific length
------------------------------------------------------------------------
## How to count message tokens
The [token counting](../Endpoints/platform-claude-com-messages-count-tokens.md) endpoint accepts the same structured list of inputs for creating a message, including support for system prompts, [tools](../Agents-Tools/agents-and-tools-tool-use-overview.md), [images](build-with-claude-vision.md), and [PDFs](build-with-claude-pdf-support.md). The response contains the total number of input tokens.
This endpoint returns an `invalid_request_error` for a few inputs that the Messages API accepts: [server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md) such as web search, web fetch, code execution, and tool search (every server tool except the [advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)), the [MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md), and `image` or `document` blocks with a `url` or `file` source. Send images and PDFs as base64 to count them. For requests that use server tools or MCP servers, the Messages API response reports the tokens used in its `usage` object.
The token count is an **estimate**. In some cases, the actual number of input tokens used when creating a message might differ by a small amount.
Token counts may include tokens added automatically by Anthropic for system optimizations. **You are not billed for system-added tokens**. Billing reflects only your content.
### Supported models
All [active models](../../20-Models/about-claude-models-overview.md) support token counting.
Claude 4.7 and later models and Claude Mythos Preview use a newer tokenizer. The same input text produces approximately 30 percent more tokens than on earlier models. The exact increase depends on the content and workload shape. Recount prompts against the model you plan to use rather than reusing counts measured against earlier models.
### Count tokens in basic messages
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.count_tokens(
model="claude-opus-5-5",
system="You are a scientist",
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(response.json())
```
Output
```python
{ "input_tokens": 14 }
```
### Count tokens in messages with tools
Token counting supports client tools and the [advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md). Requests that include other [server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md) return an error. For the advisor tool, the count covers the executor's first sampling call only.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.count_tokens(
model="claude-opus-5-5",
tools=[
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
},
}
],
messages=[{"role": "user", "content": "What's the weather like in San Francisco?"}],
)
print(response.json())
```
Output
```python
{ "input_tokens": 403 }
```
### Count tokens in messages with images
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import base64
import httpx2
image_url = "https://platform.claude.com/docs/images/vision-example.jpg"
image_media_type = "image/jpeg"
image_data = base64.standard_b64encode(httpx2.get(image_url).content).decode("utf-8")
client = anthropic.Anthropic()
response = client.messages.count_tokens(
model="claude-opus-5-5",
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": image_media_type,
"data": image_data,
},
},
{"type": "text", "text": "Describe this image"},
],
}
],
)
print(response.json())
```
Output
```python
{ "input_tokens": 1028 }
```
An embedded image block that sets [`"oversized_image": "error"`](build-with-claude-vision-coordinates.md#oversized-image-error) is rejected at count time exactly as the Messages API would reject it.
### Count tokens in messages with thinking
See [Thinking and the context window](build-with-claude-thinking.md#thinking-and-the-context-window) for more details.
- Thinking blocks from **previous** assistant turns count toward your input tokens on models that [keep all prior turns](build-with-claude-thinking.md#thinking-block-preservation-by-model); on models that keep only the last turn, the API strips them and they do **not** count
- **Current** assistant turn thinking **does** count toward your input tokens
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
response = client.messages.count_tokens(
model="claude-opus-5-5",
thinking={"type": "adaptive"},
messages=[
{
"role": "user",
"content": "Are there an infinite number of prime numbers such that n mod 4 == 3?",
},
{
"role": "assistant",
"content": [
{
"type": "thinking",
"thinking": "This is a nice number theory question. Let's think about it step by step...",
"signature": "EuYBCkQYAiJAgCs1le6/Pol5Z4/JMomVOouGrWdhYNsH3ukzUECbB6iWrSQtsQuRHJID6lWV...",
},
{
"type": "text",
"text": "Yes, there are infinitely many prime numbers p such that p mod 4 = 3...",
},
],
},
{"role": "user", "content": "Can you write a formal proof?"},
],
)
print(response.json())
```
Output
```python
{ "input_tokens": 88 }
```
### Count tokens in messages with PDFs
Token counting supports base64-encoded PDFs with the same [PDF requirements](build-with-claude-pdf-support.md#check-pdf-requirements) as the Messages API. This endpoint doesn't support `url` or `file` document sources.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import base64
import anthropic
client = anthropic.Anthropic()
with open("/path/to/document.pdf", "rb") as pdf_file:
pdf_base64 = base64.standard_b64encode(pdf_file.read()).decode("utf-8")
response = client.messages.count_tokens(
model="claude-opus-5-5",
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": pdf_base64,
},
},
{"type": "text", "text": "Please summarize this document."},
],
}
],
)
print(response.json())
```
Output
```python
{ "input_tokens": 2188 }
```
------------------------------------------------------------------------
## Token counts on Claude Fable and Claude Mythos models
Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, and Claude Mythos 5 share the tokenizer introduced with Claude Opus 4.7. A prompt counts the same on all four, and roughly 30 percent higher than on models before Claude Opus 4.7 (the exact increase depends on the content). The token counting endpoint counts under the tokenizer of the `model` you pass. To measure the difference for your workload, count the same request twice, once with your current model and once with the model you plan to move to, and compare the two `input_tokens` values.
**Billing and migration:** Usage and billing on these models reflect this tokenizer's counts. When migrating from a model before Claude Opus 4.7, don't reuse token counts measured on the older model to estimate costs or context window fit. Count your prompts with the `model` ID you plan to use (for example, `"claude-fable-5-1"`).
------------------------------------------------------------------------
## Pricing and rate limits
Token counting is **free to use** but subject to requests per minute rate limits based on your [usage tier](../Endpoints/rate-limits.md#rate-limits). If you need higher limits, use **Request rate limit increase** on the [Rate limits](../Other/usage-limits.md) page.
| Usage tier | Requests per minute (RPM) |
|------------|---------------------------|
| Start | 5,000 |
| Build | 10,000 |
| Scale | 20,000 |
Token counting and message creation have separate and independent rate limits. Usage of one does not count against the limits of the other.
------------------------------------------------------------------------
## FAQ
### Does token counting use prompt caching?
No, token counting provides an estimate without using caching logic. Although you may provide `cache_control` blocks in your token counting request, prompt caching only occurs during actual message creation.
------------------------------------------------------------------------
## Next steps
[Count message tokens](../Endpoints/platform-claude-com-messages-count-tokens.md)
Read the full API reference for the token counting endpoint.
[Context windows](build-with-claude-context-windows.md)
Use token counts to keep prompts within a model's context window.
[Rate limits](../Endpoints/rate-limits.md)
Check token counts before you send a request to stay within your usage tier.
[Prompt caching](build-with-claude-prompt-caching.md)
Reduce cost and latency on repeated prompts by caching prompt prefixes.
## Compatibility
Supported platforms
- Claude API
- Claude Platform on AWS
- Amazon Bedrock
- Google Cloud
- Microsoft Foundry
---
## Usage and Cost API - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/usage-cost-api
Path: 04-API-Reference/Guides/build-with-claude-usage-cost-api.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fmanage-claude%2Fusage-cost-api)
SearchCtrlK
Organization
[Admin API](../Other/manage-claude-admin-api.md)[User management](../Other/manage-claude-user-management.md)[Workspaces](../Other/manage-claude-workspaces.md)
Authentication
[Overview](../Other/manage-claude-authentication.md)[Create an Admin API key](../Other/manage-claude-admin-api-keys.md)[App Attest](../Other/manage-claude-app-attest.md)[Workload Identity Federation](../Other/manage-claude-workload-identity-federation.md)[Manage WIF via API](../Other/manage-claude-wif-admin-api.md)[WIF reference](../Other/manage-claude-wif-reference.md)
Identity providers
Monitoring
[Usage and Cost API](../Other/manage-claude-usage-cost-api.md)[Rate Limits API](../Other/manage-claude-rate-limits-api.md)[Analytics APIs](../Other/manage-claude-analytics-api.md)[Claude Code Analytics API](../Other/manage-claude-claude-code-analytics-api.md)[Spend Limits API](../Other/manage-claude-spend-limits-api.md)
Data & compliance
[Data residency](build-with-claude-data-residency.md)[API and data retention](../Other/manage-claude-api-and-data-retention.md)[Access Transparency](../Other/manage-claude-access-transparency.md)
[Encryption keys](../Other/manage-claude-cmek.md)
[Inference hooks](../Other/manage-claude-inference-hooks.md)
Compliance API
[Overview](../Other/manage-claude-compliance-api.md)[Set up the Compliance API](../Other/manage-claude-compliance-api-access.md)[Activity Feed](../Other/manage-claude-compliance-activity-feed.md)[Chats, files, and projects](../Other/manage-claude-compliance-content-data.md)[Session transcripts](../Other/manage-claude-compliance-sessions.md)[Organizations, users, roles, groups, and settings](../Other/manage-claude-compliance-org-data.md)[Design your integration](../Other/manage-claude-compliance-integration-patterns.md)[Errors](../Other/manage-claude-compliance-errors.md)[FAQ](../Other/manage-claude-compliance-faq.md)
[Console](../Other/usage-limits.md)
[Admin](../Other/manage-claude-admin-api.md)Monitoring
# Usage and Cost API
Copy page
Programmatically access your organization's API usage and cost data with the Usage & Cost Admin API.
Copy page
**The Admin API is unavailable for individual accounts.** To collaborate with teammates and add members, set up your organization in **Console → Settings → Organization**.
The Usage & Cost Admin API provides programmatic and granular access to historical API usage and cost data for your organization. This data is similar to the information available in the [Usage](../Other/usage-limits.md) and [Cost](../Other/usage-limits.md) pages of the Claude Console.
This API enables you to better monitor, analyze, and optimize your Claude implementations:
- **Accurate usage tracking:** Get precise token counts and usage patterns instead of relying solely on response token counting
- **Cost reconciliation:** Match internal records with Anthropic billing for finance and accounting teams
- **Product performance and improvement:** Monitor product performance while measuring if changes to the system have improved it, or set up alerting
- **[Rate limit](../Endpoints/rate-limits.md) optimization:** Optimize features like [prompt caching](build-with-claude-prompt-caching.md) or specific prompts to make the most of your allocated capacity.
- **Advanced analysis:** Perform deeper data analysis than what's available in Console
**Admin API credentials required.** These endpoints are part of the Admin API. You can access them using an [Admin API key](../Other/manage-claude-admin-api-keys.md), an OAuth token with the `org:admin` scope, or a personal or service account key that isn't scoped to a workspace; workspace API keys don't work. See [Authentication](../Other/manage-claude-admin-api.md#authentication) for details.
Claude Enterprise organizations use an Analytics API key with a different API instead; see [Which API do you need?](#which-api-do-you-need).
**Claude Platform on AWS:** The programmatic Usage and Cost API endpoints are not currently available. View usage and cost data on the **Usage** and **Cost** pages in the Claude Console instead.
## Which API do you need?
Anthropic provides cost and usage reporting through two APIs, depending on which Claude product your organization manages:
| Your organization | API | Key type |
|----------------------------------|----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|
| Claude Console (Claude Platform) | The Usage and Cost Admin API described on this page | Admin API key (`sk-ant-admin01-...`) or another [Admin API credential](../Other/manage-claude-admin-api.md#authentication) |
| Claude Enterprise (claude.ai) | The [Claude Enterprise Analytics API](../Admin/http-beta-organization-analytics.md) cost and usage endpoints | Analytics API key |
Claude Enterprise parent organizations do not appear in Claude Console and carry no Admin API keys, so for them the Analytics API key is the only path to this data. See [Analytics APIs](../Other/manage-claude-analytics-api.md) for how to create each key type and which plans the Claude Enterprise cost data applies to.
## Partner solutions
Leading observability platforms offer ready-to-use integrations for monitoring your Claude API usage and cost, without writing custom code. These integrations provide dashboards, alerting, and analytics to help you manage your API usage effectively.
[CloudZero](https://docs.cloudzero.com/docs/connections-anthropic)
Cloud intelligence platform for tracking and forecasting costs
[Datadog](https://docs.datadoghq.com/integrations/anthropic/)
LLM Observability with automatic tracing and monitoring
[Grafana Cloud](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/integrations/integration-reference/integration-anthropic/)
Agentless integration for easy LLM observability with out-of-the-box dashboards and alerts
[Harness](https://developer.harness.io/docs/cloud-cost-management/provider-integrations/ai-providers/anthropic/)
FinOps platform for cloud and AI cost management
[Honeycomb](https://docs.honeycomb.io/integrations/anthropic-usage-monitoring/)
Advanced querying and visualization through OpenTelemetry
[Vantage](https://docs.vantage.sh/connecting_anthropic)
FinOps platform for LLM cost & usage observability
## Quick start
Get your organization's daily usage for the last 7 days:
cURL
```python
curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2025-01-08T00:00:00Z&\
ending_at=2025-01-15T00:00:00Z&\
bucket_width=1d" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
**Set a User-Agent header for integrations**
If you're building an integration, set your User-Agent header to help Anthropic understand usage patterns:
``` block
User-Agent: YourApp/1.0.0 (https://yourapp.com)
```
## Usage API
Track token consumption across your organization with detailed breakdowns by model, workspace, and service tier with the `/v1/organizations/usage_report/messages` endpoint.
### Key concepts
- **Time buckets:** Aggregate usage data in fixed intervals (`1m`, `1h`, or `1d`)
- **Token tracking:** Measure uncached input, cached input, cache creation, and output tokens
- **Filtering & grouping:** Filter by API key, workspace, model, service tier, context window, [data residency](build-with-claude-data-residency.md), or speed (beta), and group results by these dimensions
- **Server tool usage:** Track usage of server-side tools such as web search
For complete parameter details and response schemas, see the [Usage API reference](https://platform.claude.com/docs/en/api/admin-api/usage-cost/get-messages-usage-report).
### Basic examples
#### Daily usage by model
cURL
```python
curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2025-01-01T00:00:00Z&\
ending_at=2025-01-08T00:00:00Z&\
group_by[]=model&\
bucket_width=1d" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
#### Hourly usage with filtering
cURL
```python
curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2025-01-15T00:00:00Z&\
ending_at=2025-01-15T23:59:59Z&\
models[]=claude-opus-5-5&\
service_tiers[]=batch&\
context_window[]=0-200k&\
bucket_width=1h" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
#### Filter usage by API keys and workspaces
cURL
```python
curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2025-01-01T00:00:00Z&\
ending_at=2025-01-08T00:00:00Z&\
api_key_ids[]=apikey_01Rj2N8SVvo6BePZj99NhmiT&\
api_key_ids[]=apikey_01ABC123DEF456GHI789JKL&\
workspace_ids[]=wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ&\
workspace_ids[]=wrkspc_01XYZ789ABC123DEF456MNO&\
bucket_width=1d" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
To retrieve your organization's API key IDs, use the [List API Keys](https://platform.claude.com/docs/en/api/admin-api/apikeys/list-api-keys) endpoint.
To retrieve your organization's workspace IDs, use the [List Workspaces](https://platform.claude.com/docs/en/api/admin-api/workspaces/list-workspaces) endpoint, or find your organization's workspace IDs in the Claude Console.
#### Data residency
Track your [data residency controls](build-with-claude-data-residency.md) by grouping and filtering usage with the `inference_geo` dimension. This is useful for verifying geographic routing across your organization.
cURL
```python
curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2026-02-01T00:00:00Z&\
ending_at=2026-02-08T00:00:00Z&\
group_by[]=inference_geo&\
group_by[]=model&\
bucket_width=1d" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
You can also filter to a specific geo. Valid values are `global`, `us`, and `not_available`:
cURL
```python
curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2026-02-01T00:00:00Z&\
ending_at=2026-02-08T00:00:00Z&\
inference_geos[]=us&\
group_by[]=model&\
bucket_width=1d" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
Models released before February 2026 (prior to Claude Opus 4.6 and Claude Sonnet 4.6) don't support the `inference_geo` request parameter, so their usage reports return `"not_available"` for this dimension. You can use `not_available` as a filter value in `inference_geos[]` to target those models.
#### Fast mode (research preview)
Track [fast mode](build-with-claude-fast-mode.md) usage by grouping and filtering with the `speed` dimension. This is useful for monitoring standard versus fast mode usage.
cURL
```python
curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2026-02-01T00:00:00Z&\
ending_at=2026-02-08T00:00:00Z&\
group_by[]=speed&\
group_by[]=model&\
bucket_width=1d" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: fast-mode-2026-02-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
You can also filter to a specific speed. Valid values are `standard` and `fast`:
cURL
```python
curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2026-02-01T00:00:00Z&\
ending_at=2026-02-08T00:00:00Z&\
speeds[]=fast&\
group_by[]=model&\
bucket_width=1d" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: fast-mode-2026-02-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
Both the `speeds[]` filter and the `speed` group_by value require the `fast-mode-2026-02-01` beta header.
### Time granularity limits
| Granularity | Default limit | Maximum limit | Use case |
|-------------|---------------|---------------|------------------------|
| `1m` | 60 buckets | 1,440 buckets | Real-time monitoring |
| `1h` | 24 buckets | 168 buckets | Daily patterns |
| `1d` | 7 buckets | 31 buckets | Weekly/monthly reports |
## Cost API
Retrieve service-level cost breakdowns in USD with the `/v1/organizations/cost_report` endpoint.
### Key concepts
- **Currency:** All costs in USD, reported as decimal strings in lowest units (cents)
- **Cost types:** Track token usage, web search, and code execution costs
- **Grouping:** Group costs by workspace or description for detailed breakdowns. When grouping by `description`, responses include parsed fields such as `model` and `inference_geo`
- **Time buckets:** Daily granularity only (`1d`)
For complete parameter details and response schemas, see the [Cost API reference](https://platform.claude.com/docs/en/api/admin-api/usage-cost/get-cost-report).
Priority Tier costs use a different billing model and are not included in the cost endpoint. Track Priority Tier usage through the usage endpoint instead.
### Basic example
cURL
```python
curl "https://api.anthropic.com/v1/organizations/cost_report?\
starting_at=2025-01-01T00:00:00Z&\
ending_at=2025-01-31T00:00:00Z&\
group_by[]=workspace_id&\
group_by[]=description" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
## Pagination
Both endpoints support pagination for large datasets:
1. Make your initial request.
2. If `has_more` is `true`, use the `next_page` value in your next request.
3. Continue until `has_more` is `false`.
cURL
```python
# First request
curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2025-01-01T00:00:00Z&\
ending_at=2025-01-31T00:00:00Z&\
limit=7" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
# Response includes: "has_more": true, "next_page": "page_xyz..."
# Next request with pagination
curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2025-01-01T00:00:00Z&\
ending_at=2025-01-31T00:00:00Z&\
limit=7&\
page=page_xyz..." \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_ADMIN_KEY"
```
## Common use cases
Explore detailed implementations in [Claude Cookbook](https://platform.claude.com/cookbook):
- **Daily usage reports:** Track token consumption trends
- **Cost attribution:** Allocate expenses by workspace for chargebacks
- **Cache efficiency:** Measure and optimize prompt caching
- **Budget monitoring:** Set up alerts for spending thresholds
- **CSV export:** Generate reports for finance teams
## Frequently asked questions
### How fresh is the data?
Usage and cost data typically appears within 5 minutes of API request completion, though delays may occasionally be longer.
### What's the recommended polling frequency?
The API supports polling once per minute for sustained use. For short bursts (for example, downloading paginated data), more frequent polling is acceptable. Cache results for dashboards that need frequent updates.
### How do I track code execution usage?
Code execution costs appear in the cost endpoint grouped under `Code Execution Usage` in the description field. Code execution is not included in the usage endpoint.
### How do I track Priority Tier usage?
Filter or group by `service_tier` in the usage endpoint and look for the `priority` value. Priority Tier costs are not available in the cost endpoint.
### What happens with playground usage?
API usage from playground in the Claude Console (and from the legacy Workbench before it) is not associated with an API key, so `api_key_id` will be `null` even when grouping by that dimension.
### How is the default workspace represented?
Usage and costs attributed to the default workspace have a `null` value for `workspace_id`.
### How do I get per-user cost breakdowns for Claude Code?
Use the [Claude Code Analytics API](../Other/manage-claude-claude-code-analytics-api.md), which provides per-user estimated costs and productivity metrics without the performance limitations of breaking down costs by many API keys. For general API usage with many keys, use the [Usage API](#usage-api) to track token consumption as a cost proxy.
## See also
Use the Usage and Cost APIs to deliver a better experience for your users, manage costs, and preserve your rate limit. Learn more about some of these other features:
- [Admin API](../Other/manage-claude-admin-api.md)
- [Admin API reference](../Admin/admin.md)
- [Analytics APIs](../Other/manage-claude-analytics-api.md) - Which analytics API and key type your organization needs
- [Pricing](../../17-Billing-Plans/about-claude-pricing.md)
- [Prompt caching](build-with-claude-prompt-caching.md) - Optimize costs with caching
- [Batch processing](build-with-claude-batch-processing.md) - 50% discount on batch requests
- [Rate limits](../Endpoints/rate-limits.md) - Understand usage tiers
- [Rate Limits API](../Other/manage-claude-rate-limits-api.md) - Read your configured rate limits
- [Data residency](build-with-claude-data-residency.md) - Control inference geography
---
## Coordinates and bounding boxes - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/vision-coordinates
Path: 04-API-Reference/Guides/build-with-claude-vision-coordinates.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fvision-coordinates)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
[Overview](build-with-claude-vision.md)[Coordinates and bounding boxes](build-with-claude-vision-coordinates.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Images and vision
# Coordinates and bounding boxes
Copy page
How Claude resizes images, and how to work with the pixel coordinates it returns for bounding boxes, points, and UI elements.
Copy page
Claude can locate and label regions of an image (for example, returning bounding boxes for tables, form fields, chart elements, or UI components). This guide covers how Claude resizes images before processing them and how to work with the pixel coordinates it returns, so that boxes and points line up with your original image.
You'll need this for OCR pipelines, form extraction, chart parsing, UI element location, and any task where you act on a specific region of an image. For sending images, supported formats, and per-model resolution limits, see [Vision](build-with-claude-vision.md).
**Claude works best with absolute pixel coordinates.** Ask for them explicitly in your prompt. For example: *"Return the bounding box of each table as `[x1, y1, x2, y2]` (top-left and bottom-right corners) in pixel coordinates."* Claude does not work well when you ask for normalized coordinates, for example: *"Return bounding box coordinates between `0` and `1000`."* Always ask for pixel coordinates and normalize in your own code if you need to. To get coordinates as machine-readable JSON instead of prose, define a schema with [structured outputs](build-with-claude-structured-outputs.md), for example an object with an `[x1, y1, x2, y2]` array per detected element.
Coordinates follow the standard image convention: the origin `(0, 0)` is the top-left corner of the image, with x increasing to the right and y increasing downward. The coordinates Claude returns are pixel positions in the image Claude sees: your image after Claude resizes it to fit the model's native resolution (see [How Claude resizes and pads images](#how-claude-resizes-and-pads-images)). To get coordinates you can use directly, either pre-resize your image so the coordinates map one-to-one onto the image you have (see [Resize your image before uploading](#resize-your-image-before-uploading)), or rescale the coordinates Claude returns (see [Rescale coordinates when you cannot pre-resize](#rescale-coordinates-when-you-cannot-pre-resize)).
Claude's spatial reasoning has limits (see [Limitations](build-with-claude-vision.md#limitations)). Coordinate accuracy is best when you state the expected coordinate format in your prompt and spot-check results visually before processing at scale. Small elements lose precision when an image is downscaled: for fine targets, crop the region of interest and send the crop (offset returned coordinates by the crop origin), or use a high-resolution-tier model. For [PDF support](build-with-claude-pdf-support.md), pages are rasterized to images server-side at dimensions you don't control, so the returned coordinates can't be reliably mapped back onto the page. To work with coordinates on PDF content, rasterize the pages to images yourself and use the pre-resize approach.
## How Claude resizes and pads images
Claude finds the largest aspect-preserving size that satisfies both of the model's image limits:
1. **Edge limit:** neither side exceeds the maximum edge length (1568 px on the standard tier, 2576 px on the high-resolution tier).
2. **Visual token limit:** the image's token cost `⌈width / 28⌉ × ⌈height / 28⌉` does not exceed the model's visual token budget (1568 tokens on the standard tier, 4784 on the high-resolution tier).
See [Resolution and token cost](build-with-claude-vision.md#evaluate-image-size) for which models are in which tier.
For nearly all photos and screenshots, the visual token limit is what determines the final size. The edge limit takes over only for elongated images such as panoramas or tall phone screenshots. Compute the size with the [reference implementation](#resize-your-image-before-uploading) rather than scaling to the edge length by hand: a 1920×1080 screenshot resizes to 1456×819, not 1568×882, and assuming the edge limit puts every coordinate noticeably off target.
The token limit can also trigger a resize when neither side exceeds the edge limit. Overlooking this is the most common cause of misaligned coordinates. For example, an A4 page scanned at 130 DPI is 1075×1520 pixels: both sides are under 1568 px, but it costs `39 × 55 = 2145` visual tokens, so Claude resizes it to 924×1307.
This example assumes a model on the standard resolution tier. A high-resolution-tier model doesn't resize the same scan: 2145 tokens is within its 4784-token budget, so the coordinates it returns map directly onto the 1075×1520 original. Model tiers are listed in [Resolution and token cost](build-with-claude-vision.md#evaluate-image-size).
Claude then pads every image, resized or not, up to the next multiple of 28 pixels on the bottom and right edges (924×1307 becomes 924×1316 in the example). The padding contains no content: Claude perceives the padded image, but the page content only ever occupies the un-padded resized region. **Always normalize or rescale by the resized dimensions, not the padded dimensions**; dividing by the padded dimensions scales every coordinate by a small amount.
## Resize your image before uploading
The most reliable approach is to resize your image yourself before uploading, so the image you have is exactly the image Claude sees and the coordinates Claude returns need no conversion.
First check which resolution tier your model is on (see [Resolution and token cost](build-with-claude-vision.md#evaluate-image-size)) and pass the matching edge and token limits. The following reference implementation computes the exact size Claude resizes an image to:
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import math
def count_image_tokens(width: int, height: int) -> int:
"""Visual tokens consumed by an image: one token per 28x28 pixel patch."""
return math.ceil(width / 28) * math.ceil(height / 28)
def resized_size(
width: int,
height: int,
max_edge: int = 1568,
max_tokens: int = 1568,
) -> tuple[int, int]:
"""The size Claude resizes an image to before padding.
Defaults are for the standard resolution tier. For high-resolution-tier
models, use max_edge=2576 and max_tokens=4784. Returns (width, height).
Images that already fit within the limits are returned unchanged.
"""
def fits(w: int, h: int) -> bool:
return (
math.ceil(w / 28) * 28 <= max_edge
and math.ceil(h / 28) * 28 <= max_edge
and count_image_tokens(w, h) <= max_tokens
)
if fits(width, height):
return (width, height)
if height > width:
resized_h, resized_w = resized_size(height, width, max_edge, max_tokens)
return (resized_w, resized_h)
# Binary search along the long edge for the largest aspect-preserving
# size that fits.
aspect_ratio = width / height
lo, hi = 1, width # lo always fits; hi never fits
while lo + 1 < hi:
mid = (lo + hi) // 2
if fits(mid, max(round(mid / aspect_ratio), 1)):
lo = mid
else:
hi = mid
return (lo, max(round(lo / aspect_ratio), 1))
# The A4 example from "How Claude resizes and pads images":
print(resized_size(1075, 1520)) # (924, 1307)
# To apply the resize, use your image library, for example Pillow:
# image.resize(resized_size(*image.size))
```
1. Resize the image to the dimensions returned by the resize helper. If the image already fits within the model's limits, the helper returns its dimensions unchanged and no resize is needed.
2. [Send the resized image](build-with-claude-vision.md#send-images-to-claude) to the API. Don't pad it yourself. Claude handles padding, and padding doesn't shift the coordinate origin.
3. In your prompt, ask explicitly for pixel coordinates. For example: *"Return the click point for the Submit button as `[x, y]` in pixel coordinates."*
4. Use the returned coordinates directly against the image you sent. If you need normalized coordinates, divide by the dimensions of the image you sent, not by the original image's dimensions and not by the padded dimensions.
The [Token counting](build-with-claude-token-counting.md) endpoint estimates an image's token cost from its dimensions without fully processing it, so a successful count doesn't mean the image is within the Messages API's [request limits](build-with-claude-vision.md#request-limits). An image can count successfully and still be rejected when you send it.
## Turn resizing into an error with `transformations`
Pre-resizing only protects your coordinates while your pipeline keeps producing the right sizes. A new image source or a switch to a model on a different resolution tier can quietly reintroduce server-side resizing. To turn that silent drift into a visible error, set the optional `transformations` field on an image content block in a [Messages](../Endpoints/messages.md) request:
```python
{
"type": "image",
"source": { "type": "base64", "media_type": "image/png", "data": "..." },
"transformations": { "oversized_image": "error" }
}
```
A request whose marked image (any block that sets `"oversized_image": "error"`) would be resized is rejected with a 400 `invalid_request_error` naming the image's dimensions and the largest dimensions that fit. Whether an image triggers the rejection depends on the [limits of every model the request names](#how-claude-resizes-and-pads-images): the 1920×1080 example below is rejected by a standard-tier model but fits within the high-resolution tier:
``` block
messages.0.content.0: image dimensions 1920x1080 exceed the maximum image size of a model named on this request and would be downsized to 1456x819; scale the image to at most 1456x819 or set the image's oversized_image setting to "downsize"
```
Rescale to the reported target and resend: the target is the largest size, at your image's aspect ratio, that every model named on the request accepts. How marked images interact with the [server-side fallback beta](build-with-claude-refusals-and-fallback.md#server-side-fallback) is described with that feature; in every mode, a marked image is never served resized.
The setting is per image. `"oversized_image": "downsize"` (the default when the field is omitted) keeps automatic resizing as described on this page. Each image block is checked only against its own setting, so one request can mix images whose dimensions are load-bearing (a screenshot you'll click on) with images where resizing is harmless (a logo). What the setting does and does not change:
- Padding ([which never discards content](#how-claude-resizes-and-pads-images)), format conversion, and orientation correction proceed as usual.
- The hard limits (8000 px on the longest side, and the stricter per-image limit on [many-image requests](build-with-claude-vision.md#request-limits)) are separate rejections; this setting never lets an image past them.
- Images supplied by URL or file ID are checked once their bytes have been fetched; those rejections carry the same message without the leading position, so they don't identify which image failed; only embedded base64 images are named by position in the error.
- [PDF pages](build-with-claude-pdf-support.md) are rasterized server-side at dimensions you don't control; the `document` block does not accept the field (an image block nested inside a document's content accepts it like any other).
- A marked image whose dimensions cannot be determined is rejected rather than passed through: that rejection reports that the image's source dimensions could not be determined, not the resize message quoted above. No image that sets `"error"` reaches the model resized.
The [Token counting](build-with-claude-token-counting.md) endpoint honors `transformations` too, rejecting an embedded image exactly as the Messages API would, so you can check whether an embedded image fits without being resized, before running inference. Counting rejects images supplied by URL or file ID rather than fetching them, so a marked image from those sources is checked only at Messages time.
## Rescale coordinates when you cannot pre-resize
If you cannot pre-resize (for example, when the image comes from an upstream system you can't modify), use the resize helper from [Resize your image before uploading](#resize-your-image-before-uploading) to recover the dimensions Claude saw, then map the coordinates Claude returns into normalized coordinates or back onto your original image. Unless an image [opts into an error instead](#oversized-image-error), Claude resizes oversized images rather than rejecting them, up to the API's [request limits](build-with-claude-vision.md#request-limits). Beyond those limits the request fails with a validation error instead. Pass the tier limits that match the model you called: the wrong tier's limits recover the wrong resized dimensions and silently shift every coordinate. This approach requires knowing the pixel dimensions of the image you uploaded, so it does not apply to PDF uploads.
Screenshots and zoom images that you return to the [computer use](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md#handle-coordinate-scaling-for-higher-resolutions) and [browser use](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md#targets-and-coordinates) toolsets are an exception to automatic resizing. The API rejects a `tool_result` image that exceeds the model's limits with a validation error instead of resizing it. Resize those images in your application before returning them, then scale the coordinates Claude returns back to your screen's dimensions.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
# This helper calls resized_size from the resize example on this page.
def to_relative_coordinates(
x: float,
y: float,
original_width: int,
original_height: int,
max_edge: int = 1568,
max_tokens: int = 1568,
) -> tuple[float, float]:
"""Map a pixel coordinate returned by Claude to relative coordinates in [0, 1].
Pass the dimensions of the image you uploaded. For high-resolution-tier
models, use max_edge=2576 and max_tokens=4784.
"""
resized_w, resized_h = resized_size(
original_width, original_height, max_edge, max_tokens
)
return (x / resized_w, y / resized_h)
# A table corner Claude returns at (462, 653.5) on the resized A4 page maps
# back onto the 1075x1520 original like this:
rel_x, rel_y = to_relative_coordinates(462, 653.5, 1075, 1520)
print((rel_x * 1075, rel_y * 1520)) # (537.5, 760.0)
```
Padding is applied only to the bottom and right edges, so the origin doesn't shift and a per-axis linear rescale is sufficient. Clamp returned coordinates to the resized dimensions before rescaling, so a point slightly outside the image can't map outside your original.
The relative coordinates multiply against whatever surface you act on: the original image, a full-resolution scan, or a screen. When you act on a screen and screenshot pixels differ from logical coordinates (HiDPI displays), also divide by the display scale factor. The [Computer use tool's scaling guidance](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md#handle-coordinate-scaling-for-higher-resolutions) covers that pattern.
## Next steps
[Agent Skills](../Agents-Tools/agents-and-tools-agent-skills-overview.md)
Agent Skills are modular capabilities that extend Claude's functionality. Each Skill packages instructions, metadata, and optional resources (scripts, templates) that Claude uses automatically when relevant.
[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)
Give Claude screenshot, mouse, and keyboard control of a desktop environment with the computer use tool.
[PDF support](build-with-claude-pdf-support.md)
Process PDFs with Claude. Extract text, analyze charts, and understand visual content from your documents.
[Token counting](build-with-claude-token-counting.md)
Count the tokens in a message before you send it to Claude. Use token counts to manage rate limits and costs, make model routing decisions, and fit prompts to a target length.
---
## Vision - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/vision
Path: 04-API-Reference/Guides/build-with-claude-vision.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fvision)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
[Overview](build-with-claude-vision.md)[Coordinates and bounding boxes](build-with-claude-vision-coordinates.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Images and vision
# Vision
Copy page
Claude's vision capabilities allow it to understand and analyze images, opening up exciting possibilities for multimodal interaction.
Copy page
This guide describes how to send images to Claude, the limits and costs that apply, and where to find guidance for [coordinate-based workflows](build-with-claude-vision-coordinates.md).
------------------------------------------------------------------------
## Send images to Claude
Use Claude's vision capabilities through:
- [claude.ai](https://claude.ai/). Upload an image like you would a file, or drag and drop an image directly into the chat window.
- [Playground](../Other/usage-limits.md) in the Claude Console. Add images directly to any User message block.
- API request. See the following examples.
On the API, provide images to Claude as `image` content blocks using one of three source types:
1. A base64-encoded image embedded in the request body
2. A URL reference to an image hosted online
3. A `file_id` returned by the [Files API](build-with-claude-files.md) (upload once, reference many times)
On Amazon Bedrock and Google Cloud, only base64-encoded sources are currently available.
Just as [placing long documents before your query](../../10-Prompting-Guides/build-with-claude-prompt-engineering-claude-prompting-best-practices.md#long-context-prompting) improves results in text prompts, Claude works best when images come before text. Images placed after text or interpolated with text still perform well, but if your use case allows it, prefer an image-then-text structure.
### Base64-encoded image example
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
image1_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"
image1_media_type = "image/png"
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": image1_media_type,
"data": image1_data,
},
},
{"type": "text", "text": "Describe this image."},
],
}
],
)
print(message)
```
### URL-based image example
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "url",
"url": "https://platform.claude.com/docs/images/vision-example.jpg",
},
},
{"type": "text", "text": "Describe this image."},
],
}
],
)
print(message)
```
### Files API image example
For images you'll use repeatedly or when you want to avoid encoding overhead, use the [Files API](build-with-claude-files.md). Upload the image once, then reference the returned `file_id` in subsequent messages instead of resending base64 data.
In multi-turn conversations and agentic workflows, each request resends the full conversation history. If images are base64-encoded, the full image bytes are included in the payload on every turn, which can significantly increase request size and latency as the conversation grows. Uploading images to the Files API and referencing them by `file_id` keeps request payloads small regardless of how many images accumulate in the conversation history.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
client = anthropic.Anthropic()
# Upload the image file
with open("vision-example.jpg", "rb") as f:
file_upload = client.files.upload(file=("vision-example.jpg", f, "image/jpeg"))
# Use the uploaded file in a message
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {"type": "file", "file_id": file_upload.id},
},
{"type": "text", "text": "Describe this image."},
],
}
],
)
print(message.content)
```
See [Messages API examples](../Endpoints/messages-create.md) for more example code and parameter details.
### Multiple images
You can include multiple images in a single request, and Claude analyzes them jointly. This is useful for comparing images, asking about differences, or working with a sequence such as pages of a document. When sending several images, introduce each one with a short text label (`Image 1:`, `Image 2:`, and so on) so you can refer to them by name in your prompt and in follow-up turns.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
image1_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"
image2_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYPgPAAEDAQAIicLsAAAAAElFTkSuQmCC"
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Image 1:"},
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image1_data,
},
},
{"type": "text", "text": "Image 2:"},
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image2_data,
},
},
{"type": "text", "text": "How are these images different?"},
],
}
],
)
print(message)
```
In a multi-turn conversation, add new images in later `user` turns the same way. Claude has access to every image from earlier turns, so follow-up questions such as "Are these similar to the first two?" work without including the earlier images again in the new turn's content.
------------------------------------------------------------------------
## Image limits and costs
### Request limits
The maximum number of images per message or request is:
- 20 per message on [claude.ai](https://claude.ai/).
- 100 per request on the API, for models with a 200k-token context window.
- 600 per request on the API, for all other models.
The maximum dimensions per image are 8000x8000 px.
If a single API request contains more than 20 images, a stricter per-image dimension limit applies to every image in that request. All `image` blocks in the request count toward this threshold, including images from earlier conversation turns that you resend and images nested inside `tool_result` content (for example, screenshots returned to the computer use tool). On Amazon Bedrock and Google Cloud, document blocks such as PDFs also count toward this threshold. Images exceeding the stricter limit are rejected with an `invalid_request_error` whose message references "many-image requests" and states the current limit in pixels. To stay under the limit on all platforms, either resize each image so that neither dimension exceeds 2000 px, or keep the request to 20 or fewer image and document blocks.
The maximum size per image is:
- 10 MB (base64-encoded) when using the Claude API directly.
- 5 MB (base64-encoded) on Amazon Bedrock and Google Cloud.
- 10 MB on [claude.ai](https://claude.ai/).
Although the API supports up to 600 images per request, [request size limits](../Endpoints/overview.md#request-size-limits) (32 MB for standard endpoints; lower on some partner-operated platforms, for example, Amazon Bedrock and Google Cloud) can be reached first. For many images, consider uploading with the [Files API](#files-api-image-example) and referencing by `file_id` to keep request payloads small.
Even when using the Files API, requests with many large images can fail before reaching the 600-image count. Reduce image dimensions or file sizes (for example, by downsampling) before uploading (see [Resolution and token cost](#evaluate-image-size)).
### Supported formats
Claude supports JPEG, PNG, GIF, and WebP images (`image/jpeg`, `image/png`, `image/gif`, `image/webp`). Animations are unsupported, and only the first frame is used.
### Resolution and token cost
Claude views images in patches instead of pixels. Each patch is a 28×28-pixel block of the image, referred to as a visual token. An image, therefore, costs `⌈width / 28⌉ × ⌈height / 28⌉` visual tokens.
Each model has a maximum native image resolution, expressed as a long-edge limit and a visual-token limit. Images larger than either limit are downscaled before processing; see [How Claude resizes and pads images](build-with-claude-vision-coordinates.md#how-claude-resizes-and-pads-images) for the exact rule. The exception is screenshots and zoom images that you return to the [computer use](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md#handle-coordinate-scaling-for-higher-resolutions) and [browser use](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md#targets-and-coordinates) toolsets: the API rejects a `tool_result` image that exceeds the model's limits with a validation error instead of downscaling it, so resize those images in your application before returning them. To have any other oversized image rejected with an error instead of downscaled, set the image block's [`transformations` field](build-with-claude-vision-coordinates.md#oversized-image-error).
| Resolution tier | Models | Max long edge | Max visual tokens |
|-----------------|-----------------------------|---------------|-------------------|
| High-resolution | Claude 4.7 and later models | 2576 px | 4784 |
| Standard | All other models | 1568 px | 1568 |
High-resolution support is automatic on the listed models and requires no beta header or client-side opt-in.
The following table shows the downsized resolution and visual-token cost for several image sizes on each tier:
| Image size | Standard tier: downsized to | Standard tier: tokens | High-resolution tier: downsized to | High-resolution tier: tokens |
|--------------------------------|-----------------------------|-----------------------|------------------------------------|------------------------------|
| 200x200 px (0.04 megapixels) | Not resized | 64 | Not resized | 64 |
| 1000x1000 px (1 megapixel) | Not resized | 1296 | Not resized | 1296 |
| 1092x1092 px (1.19 megapixels) | Not resized | 1521 | Not resized | 1521 |
| 1920x1080 px (2.07 megapixels) | 1456x819 px | 1560 | Not resized | 2691 |
| 2000x1500 px (3 megapixels) | 1269x952 px | 1564 | Not resized | 3888 |
| 3840x2160 px (8.29 megapixels) | 1456x819 px | 1560 | 2576x1449 px | 4784 |
When an image is downsized, Claude scales it to the largest size that fits the tier's limits while preserving its aspect ratio. This caps the token cost. For the precise rule and a reference implementation, see [How Claude resizes and pads images](build-with-claude-vision-coordinates.md#how-claude-resizes-and-pads-images).
To estimate cost, multiply the token count by the [per-token price of the model](../../17-Billing-Plans/pricing.md) you're using. For example, at Claude Haiku 4.5's \$1 USD per million input tokens (standard tier), the 1000×1000 image costs about \$1.30 USD per thousand images. At Claude Opus 5's \$5 USD per million (high-resolution tier), the same image costs about \$6.48 USD per thousand and the 4K image about \$23.92 USD per thousand.
High-resolution images can use up to roughly three times more visual tokens than the same image on a standard-tier model. If you don't need the additional fidelity that high resolution provides for computer use, screenshot understanding, and dense documents, downsample images before sending to control token costs. To minimize latency and to simplify [coordinate-based workflows](build-with-claude-vision-coordinates.md), prefer resizing images before uploading them.
### Image quality guidance
When providing images to Claude, keep the following in mind for best results:
- **Image clarity:** Ensure images are clear and not too blurry or pixelated.
- **Text:** If the image contains important text, make sure it's legible and not too small. Avoid cropping out key visual context solely to enlarge the text.
- **Resizing:** Take into account that your image might be resized if it is too large (see [Resolution and token cost](#evaluate-image-size)); this might, for example, make text less legible. Consider pre-resizing your images, cropping them, or both. To have an oversized image rejected with an error instead of resized (important for [coordinate workflows](build-with-claude-vision-coordinates.md)), mark the image block with [`"oversized_image": "error"`](build-with-claude-vision-coordinates.md#oversized-image-error).
- **Image compression:** Compressing images before sending them, using a lossy format such as JPEG or WebP (lossy mode), can reduce latency by reducing the size of requests. However, this can introduce artifacts that are detrimental to model performance, especially when multiple compression passes are applied. For example, heavy JPEG compression can make text difficult to read. Confirm your compression settings are appropriate for the task by inspecting the actual images sent to the API.
------------------------------------------------------------------------
## Coordinates and bounding boxes
For bounding boxes, points, and pixel coordinates, see [Coordinates and bounding boxes](build-with-claude-vision-coordinates.md). Claude returns absolute pixel coordinates relative to the image it sees after resizing; that guide covers how Claude resizes and pads images and how to pre-resize or rescale so coordinates line up with your original image.
------------------------------------------------------------------------
## Limitations
Although Claude's image understanding capabilities are cutting-edge, there are some limitations to be aware of:
- **People identification:** Claude [cannot be used](https://www.anthropic.com/legal/aup) to name people in images and refuses to do so.
- **Accuracy:** Claude might hallucinate or make mistakes when interpreting low-quality, rotated, or very small images under 200 pixels.
- **Spatial reasoning:** Claude's coordinate and localization outputs are approximate. Follow the guidance in [Coordinates and bounding boxes](build-with-claude-vision-coordinates.md) and verify outputs before relying on them.
- **Counting:** Claude can give approximate counts of objects in an image but might not always be precisely accurate, especially with large numbers of small objects.
- **AI-generated images:** Claude cannot determine whether an image is AI-generated and might be incorrect if asked. Do not rely on it to detect fake or synthetic images.
- **Inappropriate content:** Claude does not process inappropriate or explicit images that violate the [Acceptable Use Policy](https://www.anthropic.com/legal/aup).
- **Healthcare applications:** Although Claude can analyze general medical images, it is not designed to interpret complex diagnostic scans such as CTs or MRIs. Claude's outputs should not be considered a substitute for professional medical advice or diagnosis.
Always carefully review and verify Claude's image interpretations, especially for high-stakes use cases. Do not use Claude for tasks requiring perfect precision or sensitive image analysis without human oversight.
------------------------------------------------------------------------
## FAQ
### What image file types does Claude support?
JPEG, PNG, GIF, and WebP. See [Supported formats](#supported-formats).
### Can Claude read image URLs?
Yes. Use the `url` source type instead of `base64` in the `image` content block. See the [URL-based image example](#url-based-image-example).
### Is there a limit to the image file size I can upload?
Yes. See [Request limits](#request-limits) for per-image and overall request size limits across the Claude API, Amazon Bedrock, Google Cloud, and claude.ai.
### How many images can I include in one request?
Up to 600 per API request (100 for models with a 200k-token context window) and 20 per turn on claude.ai. See [Request limits](#request-limits) for details and the lower per-image dimension limit that applies above 20 images.
### Does Claude read image metadata?
No, Claude does not parse or receive any metadata from images passed to it.
### Can I delete images I've uploaded?
No. Image uploads are ephemeral and not stored beyond the duration of the API request. Uploaded images are automatically deleted after they have been processed.
### Where can I find details on data privacy for image uploads?
Refer to the Anthropic privacy policy page for information on how uploaded images and other data are handled. Anthropic does not use uploaded images to train models.
### What if Claude's image interpretation seems wrong?
If Claude's image interpretation seems incorrect:
1. Ensure the image is clear, high-quality, and correctly oriented.
2. Try prompt engineering techniques to improve results.
3. If the issue persists, flag the output in claude.ai (thumbs up/down) or contact the [support team](https://support.claude.com/).
Your feedback helps improve Claude!
### Can Claude generate or edit images?
No, Claude is an image understanding model only. It can interpret and analyze images, but it cannot generate, produce, edit, manipulate, or create images.
------------------------------------------------------------------------
## Next steps
[Multimodal cookbook](https://platform.claude.com/cookbook/multimodal-getting-started-with-vision)
Get tips and best-practice techniques for tasks such as interpreting charts and extracting content from forms.
[API reference](../Endpoints/messages-create.md)
See the Messages API documentation, including example API calls involving images.
---
## Using the Messages API - Claude Platform Docs
Source: https://platform.claude.com/docs/en/build-with-claude/working-with-messages
Path: 04-API-Reference/Guides/build-with-claude-working-with-messages.md
- [Managed Agents](../Other/managed-agents-overview.md)
- [Admin](../Other/manage-claude-admin-api.md)
- Resources
- [Best practices](../About/about-claude-use-case-guides-overview.md)
- [Models & pricing](../../20-Models/about-claude-models-overview.md)
- [CLI, SDKs, and libraries](../Other/cli-sdks-libraries-overview.md)
- [Claude API skill](../Agents-Tools/agents-and-tools-agent-skills-claude-api-skill.md)
- [Release notes](../../20-Models/release-notes-overview.md)
[API reference](../Endpoints/overview.md)
[Console](../Other/usage-limits.md)[Log in](https://platform.claude.com/login?returnTo=%2Fdocs%2Fen%2Fbuild-with-claude%2Fworking-with-messages)
SearchCtrlK
First steps
[Intro to Claude](../../01-Getting-Started/intro.md)[Get your API key](../Other/get-api-key.md)[Quickstart](../../01-Getting-Started/get-started.md)[Authentication](../Other/manage-claude-authentication.md)
Building with Claude
[Features overview](build-with-claude-overview.md)[Using the Messages API](build-with-claude-working-with-messages.md)[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)[Refusals and fallback](build-with-claude-refusals-and-fallback.md)[Fallback credit](build-with-claude-fallback-credit.md)
Model capabilities
[Effort](build-with-claude-effort.md)[Task budgets (beta)](build-with-claude-task-budgets.md)[Fast mode (research preview)](build-with-claude-fast-mode.md)[Structured outputs](build-with-claude-structured-outputs.md)[Citations](build-with-claude-citations.md)[Streaming Messages](build-with-claude-streaming.md)[Batch processing](build-with-claude-batch-processing.md)[Search results](build-with-claude-search-results.md)[Streaming refusals](../Test-Evaluate/test-and-evaluate-strengthen-guardrails-handle-streaming-refusals.md)[Multilingual support](build-with-claude-multilingual-support.md)[Embeddings](build-with-claude-embeddings.md)
[Thinking](build-with-claude-thinking.md)
Tools
[Overview](../Agents-Tools/agents-and-tools-tool-use-overview.md)[How tool use works](../Agents-Tools/agents-and-tools-tool-use-how-tool-use-works.md)[Tutorial: Build a tool-using agent](../Agents-Tools/agents-and-tools-tool-use-build-a-tool-using-agent.md)[Define tools](../Agents-Tools/agents-and-tools-tool-use-implement-tool-use.md)[Handle tool calls](../Agents-Tools/agents-and-tools-tool-use-handle-tool-calls.md)[Parallel tool use](../Agents-Tools/agents-and-tools-tool-use-parallel-tool-use.md)[Tool Runner (SDK)](../Agents-Tools/agents-and-tools-tool-use-tool-runner.md)[Strict tool use](../Agents-Tools/agents-and-tools-tool-use-strict-tool-use.md)[Server tools](../Agents-Tools/agents-and-tools-tool-use-server-tools.md)[Web search tool](../Agents-Tools/agents-and-tools-tool-use-web-search-tool.md)[Web fetch tool](../Agents-Tools/agents-and-tools-tool-use-web-fetch-tool.md)[Code execution tool](../Agents-Tools/agents-and-tools-tool-use-code-execution-tool.md)[Advisor tool](../Agents-Tools/agents-and-tools-tool-use-advisor-tool.md)[Tool search tool](../Agents-Tools/agents-and-tools-tool-use-tool-search-tool.md)[Memory tool](../Agents-Tools/agents-and-tools-tool-use-memory-tool.md)[Bash tool](../Agents-Tools/agents-and-tools-tool-use-bash-tool.md)[Text editor tool](../Agents-Tools/agents-and-tools-tool-use-text-editor-tool.md)[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)[Troubleshooting](../Agents-Tools/agents-and-tools-tool-use-troubleshooting-tool-use.md)
Tool infrastructure
[Tool reference](../Agents-Tools/agents-and-tools-tool-use-tool-reference.md)[Manage tool context](../Agents-Tools/agents-and-tools-tool-use-manage-tool-context.md)[Tool combinations](../Agents-Tools/agents-and-tools-tool-use-tool-combinations.md)[Tool use with prompt caching](../Agents-Tools/agents-and-tools-tool-use-tool-use-with-prompt-caching.md)[Programmatic tool calling](../Agents-Tools/agents-and-tools-tool-use-programmatic-tool-calling.md)[Fine-grained tool streaming](../Agents-Tools/agents-and-tools-tool-use-fine-grained-tool-streaming.md)
Context management
[Context windows](build-with-claude-context-windows.md)[Context editing](build-with-claude-context-editing.md)[Prompt caching](build-with-claude-prompt-caching.md)[Mid-conversation system messages and tool changes](build-with-claude-mid-conversation-system-messages.md)[Build an orchestration mode](build-with-claude-mid-conversation-effort-example.md)[Cache diagnostics](build-with-claude-cache-diagnostics.md)[Token counting](build-with-claude-token-counting.md)
[Compaction](build-with-claude-compaction.md)
Working with files
[Files API](build-with-claude-files.md)[PDF support](build-with-claude-pdf-support.md)
[Images and vision](build-with-claude-vision.md)
Skills
[Overview](../Agents-Tools/agents-and-tools-agent-skills-overview.md)[Quickstart](../Agents-Tools/agents-and-tools-agent-skills-quickstart.md)[Best practices](../Agents-Tools/agents-and-tools-agent-skills-best-practices.md)[Skills for enterprise](../Agents-Tools/agents-and-tools-agent-skills-enterprise.md)[Skills in the API](build-with-claude-skills-guide.md)
MCP
[Remote MCP servers](../Agents-Tools/agents-and-tools-remote-mcp-servers.md)[MCP connector](../Agents-Tools/agents-and-tools-mcp-connector.md)
[MCP tunnels](../Agents-Tools/agents-and-tools-mcp-tunnels-overview.md)
Claude on cloud platforms
[Amazon Bedrock (Opus 4.7 and later)](build-with-claude-claude-in-amazon-bedrock.md)[Amazon Bedrock (Opus 4.6 and earlier)](build-with-claude-claude-on-amazon-bedrock-legacy.md)[Claude Platform on AWS](build-with-claude-claude-platform-on-aws.md)[Google Cloud](build-with-claude-claude-on-vertex-ai.md)[Microsoft Foundry](build-with-claude-claude-in-microsoft-foundry.md)
[Console](../Other/usage-limits.md)
[Messages](../../01-Getting-Started/intro.md)Building with Claude
# Using the Messages API
Copy page
Practical patterns and examples for using the Messages API effectively
Copy page
Anthropic offers two ways to build with Claude, each suited to different use cases:
| | Messages API | Claude Managed Agents |
|----------------|---------------------------------------------|---------------------------------------------------------------------------|
| **What it is** | Direct model prompting access | Pre-built, configurable agent harness that runs in managed infrastructure |
| **Best for** | Custom agent loops and fine-grained control | Long-running tasks and asynchronous work |
This guide covers common patterns for working with the Messages API, including basic requests, multi-turn conversations, prefill techniques, and vision capabilities. For complete API specifications, see the [Messages API reference](../Endpoints/messages-create.md). For the managed agent harness instead, see the [Claude Managed Agents overview](../Other/managed-agents-overview.md).
To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](../Other/manage-claude-api-and-data-retention.md).
## Basic request and response
The `temperature`, `top_p`, and `top_k` sampling parameters are not supported on Claude 4.7 and later models and Claude Mythos Preview. Setting them to a non-default value returns a 400 error. Omit them from request payloads and use prompting to guide the model's behavior instead. See the [migration guide](../../20-Models/models-opus-5-5-migration-guide.md#opus-46-breaking-changes).
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
message = anthropic.Anthropic().messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(message)
```
Output
```python
{
"id": "msg_01XFDUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Hello!"
}
],
"model": "claude-opus-5-5",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 12,
"output_tokens": 6
}
}
```
Refusal responses (`stop_reason: "refusal"`) also include a `stop_details` object identifying the policy category that triggered the refusal, on every model. See [Handling stop reasons](build-with-claude-refusals-and-fallback.md#refusal-response) for the field reference and example handling code.
## Multiple conversational turns
The Messages API is stateless, which means that you always send the full conversational history to the API. You can use this pattern to build up a conversation over time. Earlier conversational turns don't necessarily need to actually originate from Claude. You can use synthetic `assistant` messages.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
message = anthropic.Anthropic().messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello, Claude"},
{"role": "assistant", "content": "Hello!"},
{"role": "user", "content": "Can you describe LLMs to me?"},
],
)
print(message)
```
Output
```python
{
"id": "msg_018gCsTGsXkYJVqYPxTgDHBU",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Sure, I'd be happy to provide..."
}
],
"model": "claude-opus-5-5",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 30,
"output_tokens": 309
}
}
```
### System role in messages
On Claude Fable 5.1, [Claude Mythos 5.1](../../22-Safety-Policy/glasswing.md), Claude Fable 5, [Claude Mythos 5](../../22-Safety-Policy/glasswing.md), Claude Opus 5.5, Claude Opus 4.8, and Claude Opus 5, you can include messages with `"role": "system"` after a user turn (subject to [placement rules](build-with-claude-mid-conversation-system-messages.md#limitations)) to add a new system instruction partway through a conversation. A `system` message cannot be the first entry in `messages`. Use the top-level `system` field for instructions that apply from the start.
A mid-conversation system message has the same authority as the top-level `system` field, but because it is appended to the end of the message history, it does not invalidate any cached prefix that came before it. Use the top-level `system` field for instructions that should apply from the very first turn, and a mid-conversation system message for instructions that only become relevant later.
See [Mid-conversation system messages](build-with-claude-mid-conversation-system-messages.md) for the complete guide, including how to combine it with [prompt caching](build-with-claude-prompt-caching.md).
## Prefilling Claude's response
You can pre-fill part of Claude's response in the last position of the input messages list. Use this technique to shape Claude's response. The following example uses `"max_tokens": 1` to get a single multiple choice answer from Claude.
Prefilling is not supported on Claude 4.6 and later models and [Claude Mythos Preview](../../22-Safety-Policy/glasswing.md). Requests using prefill with these models return a 400 error. Use [structured outputs](build-with-claude-structured-outputs.md) on models that support it, or system prompt instructions, instead. See the [migration guide](../../20-Models/about-claude-models-migration-guide.md) for migration patterns.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
message = anthropic.Anthropic().messages.create(
model="claude-sonnet-4-5",
max_tokens=1,
messages=[
{
"role": "user",
"content": "What is latin for Ant? (A) Apoidea, (B) Rhopalocera, (C) Formicidae",
},
{"role": "assistant", "content": "The answer is ("},
],
)
print(message)
```
Output
```python
{
"id": "msg_01Q8Faay6S7QPTvEUUQARt7h",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "C"
}
],
"model": "claude-sonnet-4-5",
"stop_reason": "max_tokens",
"stop_sequence": null,
"usage": {
"input_tokens": 42,
"output_tokens": 1
}
}
```
## Vision
Claude can read both text and images in requests. You can supply images using the `base64`, `url`, or `file` source types. The `file` source type references an image uploaded through the [Files API](build-with-claude-files.md). Supported media types are `image/jpeg`, `image/png`, `image/gif`, and `image/webp`. See the [vision guide](build-with-claude-vision.md) for more details.
cURL
CLI
Python
TypeScript
C#
Go
Java
PHP
Ruby
```python
import base64
import httpx2
# Option 1: Base64-encoded image
image_url = "https://platform.claude.com/docs/images/vision-example.jpg"
image_media_type = "image/jpeg"
image_data = base64.standard_b64encode(httpx2.get(image_url).content).decode("utf-8")
message = anthropic.Anthropic().messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": image_media_type,
"data": image_data,
},
},
{"type": "text", "text": "What is in the above image?"},
],
}
],
)
print(message)
# Option 2: URL-referenced image
message_from_url = anthropic.Anthropic().messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "url",
"url": "https://platform.claude.com/docs/images/vision-example.jpg",
},
},
{"type": "text", "text": "What is in the above image?"},
],
}
],
)
print(message_from_url)
```
Output
```python
{
"id": "msg_011CdKmWtV3oFx1C5yUbf5CY",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "This image is a beautiful minimalist/flat-design illustration of a sunset landscape. Here's what it contains:\n\n**Sky & Sun:**\n- A warm gradient sky transitioning from golden-yellow at the top to deep orange toward the horizon\n- A large pale yellow sun positioned in the upper-right area\n\n**Birds:**\n- Three small silhouetted birds flying in the upper-left portion of the sky, depicted as simple \"M\" or \"v\" shapes\n\n**Mountains:**\n- Multiple layered mountain peaks in purple and maroon tones\n- The mountains overlap to create depth, with varying shades of dusty purple and deep burgundy\n\n**Water:**\n- A dark purple body of water at the bottom of the image\n- A reflection of the sun shown as horizontal cream/peach colored lines in the center-bottom area\n\nThe overall style is clean, geometric, and uses a warm sunset color palette (oranges, yellows, purples, and maroons), giving it a peaceful, serene aesthetic typical of modern vector/flat design artwork."
}
],
"model": "claude-opus-5-5",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 1030,
"output_tokens": 350
}
}
```
## Next steps
[Stop reasons and fallback](build-with-claude-handling-stop-reasons.md)
Handle each `stop_reason` value and decide what to do when a response ends.
[Tool use with Claude](../Agents-Tools/agents-and-tools-tool-use-overview.md)
Give Claude tools to call external services and APIs from within the Messages API.
[Computer use tool](../Agents-Tools/agents-and-tools-tool-use-computer-use-tool.md)
Control desktop computer environments with the Messages API.
[Browser use tool](../Agents-Tools/agents-and-tools-tool-use-browser-use-tool.md)
Let Claude navigate, read, and interact with webpages in a browser you run.
[Structured outputs](build-with-claude-structured-outputs.md)
Get guaranteed, schema-validated JSON output from Claude.
[Task budgets](build-with-claude-task-budgets.md)
Set an advisory token budget across a full agentic loop with `output_config.task_budget`.