Follow Discord
Sweep 22 Oct 2026 · 21:04Z Build v2.1.309 528 read Stable v2.1.308 Latest v2.1.309 Next v2.1.309 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One capture · api

One read of Claude Developer Platformapi-20261023T000722Z

139 pages moved out of 812 read.

Pages moved 139 significant first
Pages read 812 in this capture
Captured 00:07 UTC
Corpus hash b5a82bae26cf index-hash

What this read moved

26-50 of 139, page 2 of 6

This capture is too large to show at once. Changes 26-50 of 139 are below, significant first; the rest are on the following screens.

api/service-tiers Changed · +9 / -9 lines

from line 81
8181 messages:
8282 - role: user
8383 content: Hello, Claude!
84 service_tier: auto # Automatically use Priority Tier when available, fallback to standard
84 service_tier: auto # Automatically use Priority Tier when available, fall back to standard
8585 YAML
8686 ```
8787 
from line 92
9292 model="claude-opus-4-8",
9393 max_tokens=1024,
9494 messages=[{"role": "user", "content": "Hello, Claude!"}],
95 service_tier="auto", # Automatically use Priority Tier when available, fallback to standard
95 service_tier="auto", # Automatically use Priority Tier when available, fall back to standard
9696 )
9797 print(message.usage.service_tier)
9898 ```
from line 104
104104 model: "claude-opus-4-8",
105105 max_tokens: 1024,
106106 messages: [{ role: "user", content: "Hello, Claude!" }],
107 service_tier: "auto" // Automatically use Priority Tier when available, fallback to standard
107 service_tier: "auto" // Automatically use Priority Tier when available, fall back to standard
108108 });
109109 console.log(message.usage.service_tier);
110110 ```
from line 117
117117 Model = Model.ClaudeOpus4_8,
118118 MaxTokens = 1024,
119119 Messages = [new UserMessageParam { Content = "Hello, Claude!" }],
120 ServiceTier = ServiceTier.Auto, // Automatically use Priority Tier when available, fallback to standard
120 ServiceTier = ServiceTier.Auto, // Automatically use Priority Tier when available, fall back to standard
121121 });
122122 Console.WriteLine(message.Usage.ServiceTier);
123123 ```
from line 131
131131 Messages: []anthropic.MessageParam{
132132 anthropic.NewUserMessage(anthropic.NewTextBlock("Hello, Claude!")),
133133 },
134 // Automatically use Priority Tier when available, fallback to standard
134 // Automatically use Priority Tier when available, fall back to standard
135135 ServiceTier: anthropic.MessageNewParamsServiceTierAuto,
136136 })
137137 if err != nil {
from line 147
147147 .model(Model.CLAUDE_OPUS_4_8)
148148 .maxTokens(1024L)
149149 .addUserMessage("Hello, Claude!")
150 // Automatically use Priority Tier when available, fallback to standard
150 // Automatically use Priority Tier when available, fall back to standard
151151 .serviceTier(MessageCreateParams.ServiceTier.AUTO)
152152 .build();
153153 
from line 159
159159 $client = new Client();
160160 
161161 $message = $client->messages->create(
162 model: 'claude-opus-4-8',
162 model: Model::CLAUDE_OPUS_4_8,
163163 maxTokens: 1024,
164164 messages: [['role' => 'user', 'content' => 'Hello, Claude!']],
165 serviceTier: 'auto', // Automatically use Priority Tier when available, fallback to standard
165 serviceTier: 'auto', // Automatically use Priority Tier when available, fall back to standard
166166 );
167167 echo $message->usage->serviceTier;
168168 ```
from line 174
174174 model: Anthropic::Model::CLAUDE_OPUS_4_8,
175175 max_tokens: 1024,
176176 messages: [{ role: "user", content: "Hello, Claude!" }],
177 service_tier: :auto # Automatically use Priority Tier when available, fallback to standard
177 service_tier: :auto # Automatically use Priority Tier when available, fall back to standard
178178 )
179179 puts(message.usage.service_tier)
180180 ```

build-with-claude/batch-processing Changed · +150 / -149 lines

from line 317
317317 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
318318 
319319 BatchCreateParams params = BatchCreateParams.builder()
320 .addRequest(
321 BatchCreateParams.Request.builder()
322 .customId("my-first-request")
323 .params(
324 BatchCreateParams.Request.Params.builder()
325 .model(Model.CLAUDE_OPUS_5_5)
326 .maxTokens(1024)
327 .addUserMessage("Hello, world")
328 .build()
329 )
330 .build()
331 )
332 .addRequest(
333 BatchCreateParams.Request.builder()
334 .customId("my-second-request")
335 .params(
336 BatchCreateParams.Request.Params.builder()
337 .model(Model.CLAUDE_OPUS_5_5)
338 .maxTokens(1024)
339 .addUserMessage("Hi again, friend")
340 .build()
341 )
342 .build()
343 )
344 .build();
320 .addRequest(
321 BatchCreateParams.Request.builder()
322 .customId("my-first-request")
323 .params(
324 BatchCreateParams.Request.Params.builder()
325 .model(Model.CLAUDE_OPUS_5_5)
326 .maxTokens(1024)
327 .addUserMessage("Hello, world")
328 .build()
329 )
330 .build()
331 )
332 .addRequest(
333 BatchCreateParams.Request.builder()
334 .customId("my-second-request")
335 .params(
336 BatchCreateParams.Request.Params.builder()
337 .model(Model.CLAUDE_OPUS_5_5)
338 .maxTokens(1024)
339 .addUserMessage("Hi again, friend")
340 .build()
341 )
342 .build()
343 )
344 .build();
345345 
346346 MessageBatch messageBatch = client.messages().batches().create(params);
347347 
from line 459
459459 
460460 ```bash CLI
461461 # Check the status; repeat until processing_status is "ended"
462 ant messages:batches retrieve \
463 --message-batch-id "$MESSAGE_BATCH_ID"
462 ant messages:batches retrieve --message-batch-id "$MESSAGE_BATCH_ID"
464463 ```
465464 
466465 ```python Python
from line 559
560559 
561560 ```php PHP
562561 $client = new Client();
563 $messageBatchId = getenv("MESSAGE_BATCH_ID");
562 $messageBatchId = getenv('MESSAGE_BATCH_ID');
564563 
565564 $messageBatch = null;
566565 while (true) {
from line 566
567566 $messageBatch = $client->messages->batches->retrieve(
568567 messageBatchID: $messageBatchId,
569568 );
570 if ($messageBatch->processingStatus === "ended") {
569 if ($messageBatch->processingStatus === 'ended') {
571570 break;
572571 }
573572 
from line 669
670669 
671670 // Automatically fetches more pages as needed
672671 for (MessageBatch messageBatch : client
673 .messages()
674 .batches()
675 .list(BatchListParams.builder().limit(20).build())
676 .autoPager()) {
677 System.out.println(messageBatch);
672 .messages()
673 .batches()
674 .list(BatchListParams.builder()
675 .limit(20)
676 .build())
677 .autoPager()) {
678 System.out.println(messageBatch);
678679 }
679680 ```
680681 
from line 715
714715 
715716<CodeGroup>
716717 ```bash cURL
717 # Streams the batch's .jsonl results, one result per line.
718 # Streams the batch's .jsonl results, one result on each line.
718719 # For per-result handling (retries, validation errors), use the Claude SDK.
719720 curl "https://api.anthropic.com/v1/messages/batches/msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d/results" \
720721 -H "anthropic-version: 2023-06-01" \
from line 723
722723 ```
723724 
724725 ```bash CLI
725 # Prints one result per line, for example `{"custom_id":"test-1","result":{"type":"succeeded",…}}`.
726 # For per-result handling (retries, validation errors), use the SDK
726 # Prints one result on each line, for example `{"custom_id":"test-1","result":{"type":"succeeded",…}}`.
727 # For per-result handling (retries, validation errors), use the Claude SDK
727728 # examples in the other tabs.
728729 ant messages:batches results \
729730 --message-batch-id msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d \
from line 836
835836 import com.anthropic.models.messages.batches.BatchResultsParams;
836837 import com.anthropic.models.messages.batches.MessageBatchIndividualResponse;
837838 // ...
838 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
839 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
839840 
840 // Stream results file in memory-efficient chunks, processing one at a time
841 try (
842 StreamResponse<MessageBatchIndividualResponse> streamResponse = client
843 .messages()
844 .batches()
845 .resultsStreaming(
846 BatchResultsParams.builder()
847 .messageBatchId("msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d")
848 .build()
849 )
850 ) {
851 streamResponse
852 .stream()
853 .forEach(result -> {
854 switch (result.result().type().value()) {
855 case SUCCEEDED -> System.out.println("Success! " + result.customId());
856 case ERRORED -> {
857 if (result.result().asErrored().error().error().isInvalidRequestError()) {
858 // Request body must be fixed before re-sending request
859 System.out.println("Validation error: " + result.customId());
860 } else {
861 // Request can be retried directly
862 System.out.println("Server error: " + result.customId());
863 }
864 }
865 case EXPIRED -> System.out.println("Request expired: " + result.customId());
866 }
867 });
868 }
841 // Stream results file in memory-efficient chunks, processing one at a time
842 try (
843 StreamResponse<MessageBatchIndividualResponse> streamResponse = client
844 .messages()
845 .batches()
846 .resultsStreaming(
847 BatchResultsParams.builder()
848 .messageBatchId("msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d")
849 .build()
850 )
851 ) {
852 streamResponse
853 .stream()
854 .forEach(result -> {
855 switch (result.result().type().value()) {
856 case SUCCEEDED -> System.out.println("Success! " + result.customId());
857 case ERRORED -> {
858 if (result.result().asErrored().error().error().isInvalidRequestError()) {
859 // Request body must be fixed before re-sending request
860 System.out.println("Validation error: " + result.customId());
861 } else {
862 // Request can be retried directly
863 System.out.println("Server error: " + result.customId());
864 }
865 }
866 case EXPIRED -> System.out.println("Request expired: " + result.customId());
867 }
868 });
869 }
869870 ```
870871 
871872 ```php PHP
from line 882
881882 echo "Success! {$result->customID}\n";
882883 break;
883884 case $result->result instanceof MessageBatchErroredResult:
884 if ($result->result->error->error->type === "invalid_request_error") {
885 if ($result->result->error->error->type === 'invalid_request_error') {
885886 echo "Validation error: {$result->customID}\n";
886887 } else {
887888 echo "Server error: {$result->customID}\n";
from line 988
987988 ```java Java
988989 import com.anthropic.models.messages.batches.*;
989990 // ...
990 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
991 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
991992 
992 MessageBatch messageBatch = client
993 .messages()
994 .batches()
995 .cancel("msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d");
996 System.out.println(messageBatch);
993 MessageBatch messageBatch = client
994 .messages()
995 .batches()
996 .cancel("msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d");
997 System.out.println(messageBatch);
997998 ```
998999 
9991000 ```php PHP
from line 1376
13751376 // ...
13761377 import com.anthropic.models.messages.batches.*;
13771378 // ...
1378 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
1379 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
13791380 
1380 BatchCreateParams createParams = BatchCreateParams.builder()
1381 .addRequest(
1382 BatchCreateParams.Request.builder()
1383 .customId("my-first-request")
1384 .params(
1385 BatchCreateParams.Request.Params.builder()
1386 .model(Model.CLAUDE_OPUS_5_5)
1387 .maxTokens(1024)
1388 .systemOfTextBlockParams(
1389 List.of(
1390 TextBlockParam.builder()
1391 .text(
1392 "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
1381 BatchCreateParams createParams = BatchCreateParams.builder()
1382 .addRequest(
1383 BatchCreateParams.Request.builder()
1384 .customId("my-first-request")
1385 .params(
1386 BatchCreateParams.Request.Params.builder()
1387 .model(Model.CLAUDE_OPUS_5_5)
1388 .maxTokens(1024)
1389 .systemOfTextBlockParams(
1390 List.of(
1391 TextBlockParam.builder()
1392 .text(
1393 "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
1394 )
1395 .build(),
1396 TextBlockParam.builder()
1397 .text("<the entire contents of Pride and Prejudice>")
1398 .cacheControl(CacheControlEphemeral.builder().build())
1399 .build()
1400 )
1401 )
1402 .addUserMessage("Analyze the major themes in Pride and Prejudice.")
1403 .build()
13931404 )
1394 .build(),
1395 TextBlockParam.builder()
1396 .text("<the entire contents of Pride and Prejudice>")
1397 .cacheControl(CacheControlEphemeral.builder().build())
13981405 .build()
1399 )
1400 )
1401 .addUserMessage("Analyze the major themes in Pride and Prejudice.")
1402 .build()
1403 )
1404 .build()
1405 )
1406 .addRequest(
1407 BatchCreateParams.Request.builder()
1408 .customId("my-second-request")
1409 .params(
1410 BatchCreateParams.Request.Params.builder()
1411 .model(Model.CLAUDE_OPUS_5_5)
1412 .maxTokens(1024)
1413 .systemOfTextBlockParams(
1414 List.of(
1415 TextBlockParam.builder()
1416 .text(
1417 "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
1406 )
1407 .addRequest(
1408 BatchCreateParams.Request.builder()
1409 .customId("my-second-request")
1410 .params(
1411 BatchCreateParams.Request.Params.builder()
1412 .model(Model.CLAUDE_OPUS_5_5)
1413 .maxTokens(1024)
1414 .systemOfTextBlockParams(
1415 List.of(
1416 TextBlockParam.builder()
1417 .text(
1418 "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
1419 )
1420 .build(),
1421 TextBlockParam.builder()
1422 .text("<the entire contents of Pride and Prejudice>")
1423 .cacheControl(CacheControlEphemeral.builder().build())
1424 .build()
1425 )
1426 )
1427 .addUserMessage("Write a summary of Pride and Prejudice.")
1428 .build()
14181429 )
1419 .build(),
1420 TextBlockParam.builder()
1421 .text("<the entire contents of Pride and Prejudice>")
1422 .cacheControl(CacheControlEphemeral.builder().build())
14231430 .build()
1424 )
1425 )
1426 .addUserMessage("Write a summary of Pride and Prejudice.")
1427 .build()
1428 )
1429 .build()
1430 )
1431 .build();
1431 )
1432 .build();
14321433 
1433 MessageBatch messageBatch = client.messages().batches().create(createParams);
1434 MessageBatch messageBatch = client.messages().batches().create(createParams);
14341435 ```
14351436 
14361437 ```php PHP
from line 1543
15421543 
15431544All [server tools](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools) (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.
15441545 
1545Because 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 complete; 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](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#the-server-side-loop-and-pause-turn).
1546Because there is no open connection to maintain, the batch loop can run **more iterations in a 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 complete; 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](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#the-server-side-loop-and-pause-turn).
15461547 
15471548The batch worker additionally throttles `web_search` for each 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.
15481549 
from line 1716
17151716 import com.anthropic.models.beta.messages.batches.*;
17161717 
17171718 void main() {
1718 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
1719 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
17191720 
1720 BatchCreateParams params = BatchCreateParams.builder()
1721 .addBeta("output-300k-2026-03-24")
1722 .addRequest(
1723 BatchCreateParams.Request.builder()
1724 .customId("long-form-request")
1725 .params(
1726 BatchCreateParams.Request.Params.builder()
1727 .model(Model.CLAUDE_OPUS_5_5)
1728 .maxTokens(300_000L)
1729 .addUserMessage("Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices.")
1730 .build()
1721 BatchCreateParams params = BatchCreateParams.builder()
1722 .addBeta("output-300k-2026-03-24")
1723 .addRequest(
1724 BatchCreateParams.Request.builder()
1725 .customId("long-form-request")
1726 .params(
1727 BatchCreateParams.Request.Params.builder()
1728 .model(Model.CLAUDE_OPUS_5_5)
1729 .maxTokens(300_000L)
1730 .addUserMessage("Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices.")
1731 .build()
1732 )
1733 .build()
17311734 )
1732 .build()
1733 )
1734 .build();
1735 .build();
17351736 
1736 BetaMessageBatch messageBatch = client.beta().messages().batches().create(params);
1737 BetaMessageBatch messageBatch = client.beta().messages().batches().create(params);
17371738 
1738 IO.println(messageBatch);
1739 IO.println(messageBatch);
17391740 }
17401741 ```
17411742 

build-with-claude/citations Changed · +46 / -18 lines

from line 11
1111 Claude API: ga
1212 Claude Platform on AWS: ga
1313 Amazon Bedrock: ga
14 Google Cloud: ga
14 Claude Models on Google Cloud (Google managed): ga
1515 Microsoft Foundry: ga
1616---
1717 
from line 217
217217 .source(source)
218218 .title("My Document")
219219 .context("This is a trustworthy document.")
220 .citations(CitationsConfigParam.builder().enabled(true).build())
220 .citations(CitationsConfigParam.builder()
221 .enabled(true)
222 .build())
221223 .build();
222224 
223225 TextBlockParam textBlockParam = TextBlockParam.builder()
from line 268
266268 ],
267269 ],
268270 ],
269 model: 'claude-opus-5-5',
271 model: Model::CLAUDE_OPUS_5_5,
270272 );
271273 
272274 echo json_encode($response, JSON_PRETTY_PRINT);
from line 598
596598 + " ... ".repeat(1000); // Minimum cacheable length
597599 
598600 DocumentBlockParam documentParam = DocumentBlockParam.builder()
599 .source(PlainTextSource.builder().data(longDocument).build())
600 .citations(CitationsConfigParam.builder().enabled(true).build())
601 .source(PlainTextSource.builder()
602 .data(longDocument)
603 .build())
604 .citations(CitationsConfigParam.builder()
605 .enabled(true)
606 .build())
601607 .cacheControl(CacheControlEphemeral.builder().build()) // Cache the document content
602608 .build();
603609 
from line 657
651657 ],
652658 ],
653659 ],
654 model: 'claude-opus-5-5',
660 model: Model::CLAUDE_OPUS_5_5,
655661 );
656662 
657663 echo json_encode($response, JSON_PRETTY_PRINT);
from line 913
907913 .fileSource(fileId)
908914 .title("Document Title")
909915 .context("Context about the document that will not be cited from")
910 .citations(CitationsConfigParam.builder().enabled(true).build())
916 .citations(CitationsConfigParam.builder()
917 .enabled(true)
918 .build())
911919 .build()),
912920 ContentBlockParam.ofText(TextBlockParam.builder()
913921 .text("Summarize this document.")
from line 1201
11931201 String pdfBase64 = Base64.getEncoder().encodeToString(pdfBytes);
11941202 
11951203 DocumentBlockParam documentParam = DocumentBlockParam.builder()
1196 .source(Base64PdfSource.builder().data(pdfBase64).build())
1204 .source(Base64PdfSource.builder()
1205 .data(pdfBase64)
1206 .build())
11971207 .title("Document Title")
11981208 .context("Context about the document that will not be cited from")
1199 .citations(CitationsConfigParam.builder().enabled(true).build())
1209 .citations(CitationsConfigParam.builder()
1210 .enabled(true)
1211 .build())
12001212 .build();
12011213 
12021214 MessageCreateParams params = MessageCreateParams.builder()
from line 1217
12051217 .addUserMessageOfContentBlockParams(
12061218 List.of(
12071219 ContentBlockParam.ofDocument(documentParam),
1208 ContentBlockParam.ofText(TextBlockParam.builder().text("Summarize this document.").build())
1220 ContentBlockParam.ofText(TextBlockParam.builder()
1221 .text("Summarize this document.")
1222 .build())
12091223 )
12101224 )
12111225 .build();
from line 1487
14731487 .build())
14741488 .title("Document Title")
14751489 .context("Context about the document that will not be cited from")
1476 .citations(CitationsConfigParam.builder().enabled(true).build())
1490 .citations(CitationsConfigParam.builder()
1491 .enabled(true)
1492 .build())
14771493 .build();
14781494 
14791495 MessageCreateParams params = MessageCreateParams.builder()
from line 1498
14821498 .addUserMessageOfContentBlockParams(
14831499 List.of(
14841500 ContentBlockParam.ofDocument(documentParam),
1485 ContentBlockParam.ofText(TextBlockParam.builder().text("Summarize this document.").build())
1501 ContentBlockParam.ofText(TextBlockParam.builder()
1502 .text("Summarize this document.")
1503 .build())
14861504 )
14871505 )
14881506 .build();
from line 1741
17231741 .fileSource(fileId)
17241742 .title("Document Title")
17251743 .context("Context about the document that will not be cited from")
1726 .citations(CitationsConfigParam.builder().enabled(true).build())
1744 .citations(CitationsConfigParam.builder()
1745 .enabled(true)
1746 .build())
17271747 .build()),
17281748 ContentBlockParam.ofText(TextBlockParam.builder()
17291749 .text("Summarize this document.")
from line 2032
20122032 .source(ContentBlockSource.builder()
20132033 .contentOfBlockSource(
20142034 List.of(
2015 ContentBlockSourceContent.ofText(TextBlockParam.builder().text("First chunk").build()),
2016 ContentBlockSourceContent.ofText(TextBlockParam.builder().text("Second chunk").build())
2035 ContentBlockSourceContent.ofText(TextBlockParam.builder()
2036 .text("First chunk")
2037 .build()),
2038 ContentBlockSourceContent.ofText(TextBlockParam.builder()
2039 .text("Second chunk")
2040 .build())
20172041 )
20182042 )
20192043 .build())
20202044 .title("Document Title")
20212045 .context("Context about the document that will not be cited from")
2022 .citations(CitationsConfigParam.builder().enabled(true).build())
2046 .citations(CitationsConfigParam.builder()
2047 .enabled(true)
2048 .build())
20232049 .build();
20242050 
20252051 MessageCreateParams params = MessageCreateParams.builder()
from line 2054
20282054 .addUserMessageOfContentBlockParams(
20292055 List.of(
20302056 ContentBlockParam.ofDocument(documentParam),
2031 ContentBlockParam.ofText(TextBlockParam.builder().text("Summarize this document.").build())
2057 ContentBlockParam.ofText(TextBlockParam.builder()
2058 .text("Summarize this document.")
2059 .build())
20322060 )
20332061 )
20342062 .build();
from line 2094
20662094 ],
20672095 ],
20682096 ],
2069 model: 'claude-opus-5-5',
2097 model: Model::CLAUDE_OPUS_5_5,
20702098 );
20712099 
20722100 echo json_encode($response, JSON_PRETTY_PRINT);

build-with-claude/claude-in-amazon-bedrock Changed · +4 / -4 lines

from line 150
150150 ```bash
151151 curl https://bedrock-mantle.us-east-1.api.aws/anthropic/v1/messages \
152152 --aws-sigv4 "aws:amz:us-east-1:bedrock-mantle" \
153 --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
153 -u "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
154154 -H "x-amz-security-token: $AWS_SESSION_TOKEN" \
155155 -H "content-type: application/json" \
156156 -H "anthropic-version: 2023-06-01" \
from line 282
282282 );
283283 
284284 message.content().stream()
285 .filter(ContentBlock::isText)
286 .findFirst()
287 .ifPresent(block -> IO.println(block.asText().text()));
285 .filter(ContentBlock::isText)
286 .findFirst()
287 .ifPresent(block -> IO.println(block.asText().text()));
288288 }
289289 ```
290290 </Tab>

build-with-claude/claude-models-on-google-cloud/anthropic-managed New page · 847 lines, new page

## Set up your account ### Troubleshooting account setup ## Manage access ### IAM roles ### Using the Claude Console ### Workspaces ## Before making API calls ### Find your workspace ID ### Install an SDK ## Making requests ### API model IDs ## Project, location, and workspace resolution ## Authentication ### Credential precedence ## Feature support ### Claude Managed Agents ### Features not supported ### Context window ## Billing, rate limits, and logging ### Rate limits ### Billing ### Data retention ### Monitoring and logging #### Request IDs ## Moving from an existing Anthropic organization ## Migrating from Claude Models on Google Cloud (Google managed) ## Next steps

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Claude Models on Google Cloud (Anthropic managed)
url: https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed
description: Claude Models on Google Cloud (Anthropic managed) is the Claude API, run by Anthropic and reached through your Google Cloud project.
---

Google Cloud handles access and billing for Claude Models on Google Cloud (Anthropic managed). To compare the two Google Cloud offerings, or to check which one you use, see [Claude Models on Google Cloud](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/overview).

## Set up your account

To set up your account for Claude Models on Google Cloud (Anthropic managed), you need the following:

* Permission to purchase in Google Cloud Marketplace on your billing account
* Permission to enable services on the project
* An [IAM role that lets you open the Claude Console](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#using-the-claude-console), which you need for step 4

These steps create a new Anthropic organization for your Google Cloud project. It's separate from any Anthropic organization your company already has. That includes a Claude Enterprise organization. To move from an existing organization, see [Moving from an existing Anthropic organization](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#moving-from-an-existing-anthropic-organization).

If you have an existing discount, contact your Anthropic or Google Cloud account representative before you start these steps. Discounts can't be applied to past usage.

<Steps>
  <Step title="Subscribe in Marketplace">
    1. Open [Google Cloud Marketplace](https://console.cloud.google.com/marketplace) and find the **Claude Models on Google Cloud (Anthropic managed)** listing.
    2. Click **Subscribe** and complete the purchase flow.
    3. Return to the listing and click **Manage on Console**. This opens the Claude page in the Google Cloud console.

    To return to the Claude page later, select your project in the Google Cloud console. Then go to **Agent Platform > Models > Claude Platform** and select **Anthropic managed**.
  </Step>

  <Step title="Enable the services">
    Enable two services on every project that calls Claude Models on Google Cloud (Anthropic managed):

    * `claude.googleapis.com` serves the API for Claude Models on Google Cloud (Anthropic managed). This service also defines the IAM permissions. Calls fail without it.
    * `anthropic-managed-claude.cloudpartnerservices.goog` is the Marketplace service that attributes the project's usage to your subscription.

    ```bash CLI
    gcloud services enable claude.googleapis.com \
      anthropic-managed-claude.cloudpartnerservices.goog \
      --project=my-project-id
    ```

    Replace `my-project-id` with your project ID.

    You can also enable both from the Claude page or from **APIs & Services**. Enabling is a one-time step for each project. To check that both services are enabled, run `gcloud services list --enabled --project=my-project-id` and look for both names.
  </Step>

  <Step title="Set up your Anthropic organization">
    1. On the Claude page, click **Activate**.
    2. In the Anthropic setup flow, enter a contact email address.
    3. Open the setup link sent to that address.
    4. Fill in the organization's name, entity type, country, and intended use.
    5. Accept Anthropic's Commercial Terms of Service and Usage Policy.

    The contact address is used only for setup and service notices. For how people open the Claude Console after setup, see [Using the Claude Console](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#using-the-claude-console).
  </Step>

  <Step title="Open the Claude Console">
    When your Anthropic organization is active, the button on the Claude page changes to **Open Claude Console**. Click it. Google Cloud checks your IAM access. Then it redirects your browser to `platform.claude.com`. You're signed in to the new organization.

    While you're in the Claude Console, [find your workspace ID](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#find-your-workspace-id) and copy it. Everyone who calls Claude Models on Google Cloud (Anthropic managed) needs it. Pass it on to your developers.
  </Step>
</Steps>

To add another project, repeat these steps in that project, starting from step 2.

### Troubleshooting account setup

If you run into one of the following problems while you set up Claude Models on Google Cloud (Anthropic managed), apply its fix:

* **`gcloud services enable` can't find `anthropic-managed-claude.cloudpartnerservices.goog`:** Run the command as the account that completed the Marketplace purchase, or contact your Anthropic account representative.
* **A permission error on your first API call:** Check that `claude.googleapis.com` is enabled on the project you're calling. Check that the caller has `roles/claude.user` or `roles/claude.admin` on that project. For what each role allows, see [IAM roles](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#iam-roles). A new grant or a newly enabled service can take a moment to apply.
* **"Signed in as a different account" after following the setup link:** Click **Log out and continue**. Then use the email address you entered in step 3.
* **The button says "Finish Setup" instead of "Open Claude Console":** Your Anthropic organization exists, but its setup isn't complete. An administrator has to finish the organization details form.
* **The Usage page shows no data after your first API call:** Usage data can take a few minutes to appear in the Claude Console.

## Manage access

### IAM roles

Claude Models on Google Cloud (Anthropic managed) has three predefined IAM roles. Grant roles on the project.

| Role                  | Display name  | What it allows                                                                                                                                                                                                                          |
| --------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `roles/claude.viewer` | Claude Viewer | Every `get` and `list` permission on workspace resources<br />This role is read-only.                                                                                                                                                   |
| `roles/claude.user`   | Claude User   | Everything `roles/claude.viewer` allows, plus creating and changing workspace resources<br />This includes sending messages and counting tokens. It also includes managing batches, files, skills, and Claude Managed Agents resources. |
| `roles/claude.admin`  | Claude Admin  | Everything `roles/claude.user` allows, plus the permissions checked on your Anthropic organization<br />Organization-level routes act on your Anthropic organization as a whole, not on one workspace.                                  |

For example, the following command lets a service account call Claude Models on Google Cloud (Anthropic managed):

```bash CLI
gcloud projects add-iam-policy-binding my-project-id \
  --member="serviceAccount:[email protected]" \
  --role="roles/claude.user"
```

For permissions, predefined roles, and audit log types, see [IAM permissions for Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/api/claude-models-on-google-cloud-anthropic-managed-iam-permissions).

Enabling `claude.googleapis.com` creates a service agent for the project. Don't remove its role grants. Removing them stops Claude Models on Google Cloud (Anthropic managed) from working in the project.

### Using the Claude Console

With Claude Models on Google Cloud (Anthropic managed), you can't use an email address to sign in to your Anthropic organization. Instead, click **Open Claude Console** on the [Claude page](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#set-up-your-account) in the Google Cloud console. Google Cloud IAM controls who can open the Claude Console. Of the three predefined [IAM roles](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#iam-roles), only `roles/claude.admin` on the project lets you open the Claude Console.

### Workspaces

In Claude Models on Google Cloud (Anthropic managed), setup creates your Anthropic organization with one workspace, the Default Workspace. To create more workspaces, [open the Claude Console](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#using-the-claude-console) and go to **Settings > Workspaces**. On the same page, you can rename or archive any workspace except the Default Workspace. Each workspace has its own [workspace ID](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#find-your-workspace-id). Files, skills, batches, Claude Managed Agents sessions, and other workspace resources belong to the workspace whose ID you [set for the request](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#project-location-and-workspace-resolution).

You grant [IAM roles](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#iam-roles) on the project, so a role applies to every workspace in that project. When teams need separate access, give each team its own Google Cloud project. Each project has its own Anthropic organization, so repeat the [setup steps](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#set-up-your-account) in each project, starting from step 2.

## Before making API calls

To call Claude Models on Google Cloud (Anthropic managed), you need the following:

1. A Google Cloud project with an active subscription and an Anthropic organization whose setup is complete. See [Set up your account](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#set-up-your-account).
2. The [gcloud CLI](https://cloud.google.com/sdk/docs/install) installed, for local development.
3. The `roles/claude.user` role, granted on the project to the identity that makes the calls.
4. Application Default Credentials for that identity. See [Authentication](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#authentication).
5. Your project ID and your [workspace ID](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#find-your-workspace-id).

To grant the role to your own account for local development, run the following command. You need permission to change the project's IAM policy.

```bash CLI
gcloud projects add-iam-policy-binding my-project-id \
  --member="user:[email protected]" \
  --role="roles/claude.user"
```

Replace `my-project-id` with your project ID. Replace `[email protected]` with your Google account's email address. To see the project gcloud is using, run `gcloud config get-value project`. For service accounts and the other roles, see [IAM roles](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#iam-roles).

### Find your workspace ID

To find your workspace ID for Claude Models on Google Cloud (Anthropic managed), [open the Claude Console](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#using-the-claude-console) and go to **Settings > Workspaces**. The ID starts with `wrkspc_`. If you can't open the Claude Console, ask someone who can open it to send you the ID.

Set the project and workspace as environment variables so that the SDK client and the [`ant` CLI](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/quickstart) pick them up:

```bash CLI
export ANTHROPIC_GOOGLE_CLOUD_PROJECT="my-project-id"
export ANTHROPIC_GOOGLE_CLOUD_WORKSPACE_ID="wrkspc_01AbCdEf23GhIj"
```

### Install an SDK

The [SDK client](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) for Claude Models on Google Cloud (Anthropic managed) is `AnthropicGoogleCloud` (csharp: `AnthropicGoogleCloudClient`; go: `googlecloud.NewClient`; java: `GoogleCloudBackend`; php: `Anthropic\GoogleCloud\Client`; ruby: `Anthropic::GoogleCloudClient`). The client resolves your Google credentials. It also builds the base URL from your project, location, and workspace ID.

<Note>
  The SDK client for Claude Models on Google Cloud (Anthropic managed) is in beta.
</Note>

Install the package that provides the client:

<Tabs>
  <Tab title="Python">
    ```bash
    pip install -U "anthropic[google_cloud]"
    ```
  </Tab>

  <Tab title="TypeScript">
    ```bash
    npm install @anthropic-ai/google-cloud-sdk
    ```
  </Tab>

  <Tab title="C#">
    ```bash
    dotnet add package Anthropic.GoogleCloud
    ```
  </Tab>

  <Tab title="Go">
    ```bash
    go get github.com/anthropics/anthropic-sdk-go/v2
    ```
  </Tab>

  <Tab title="Java">
    ```kotlin Gradle
    implementation("com.anthropic:anthropic-java:3.1.0")
    implementation("com.anthropic:anthropic-java-google-cloud:3.1.0")
    ```

    ```xml Maven
    <dependency>
      <groupId>com.anthropic</groupId>
      <artifactId>anthropic-java</artifactId>
      <version>3.1.0</version>
    </dependency>
    <dependency>
      <groupId>com.anthropic</groupId>
      <artifactId>anthropic-java-google-cloud</artifactId>
      <version>3.1.0</version>
    </dependency>
    ```
  </Tab>

  <Tab title="PHP">
    ```bash
    composer require anthropic-ai/sdk google/auth
    ```
  </Tab>

  <Tab title="Ruby">
    ```bash
    gem install anthropic googleauth
    ```
  </Tab>
</Tabs>

To use the `ant` CLI instead, [install or update the CLI](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/quickstart#installation) to the latest version. A version without support for Claude Models on Google Cloud (Anthropic managed) ignores the `ANTHROPIC_GOOGLE_CLOUD_*` variables. It then does one of the following:

* Sends the request to the Claude API with any other credential you've set up
* Fails with an authentication error

## Making requests

Claude Models on Google Cloud (Anthropic managed) serves Claude API endpoints under a base URL that names your project, a location, and your workspace:

```text wrap
https://claude.googleapis.com/v1/projects/{project}/locations/global/workspaces/{workspace}/invoke
```

The [organization-level routes](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#iam-roles), whose paths start with `/v1/organizations/`, use a base URL without the workspace:

```text wrap
https://claude.googleapis.com/v1/projects/{project}/locations/global/claudeOrganization/invoke
```

If you don't [set the base URL](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#project-location-and-workspace-resolution), the SDK client chooses between these two for each request.

Append the Claude API path to the base URL. For example, the [Messages API](https://platform.claude.com/docs/en/api/messages/create) is at `.../invoke/v1/messages`. Three things differ from a Claude API request:

* **Base URL:** The project-scoped URLs shown earlier, in place of `https://api.anthropic.com`.
* **Authentication:** An `Authorization: Bearer` header with a Google access token. Don't send an `x-api-key` header.
* **Workspace:** The workspace ID is part of the URL. Don't send an `anthropic-workspace-id` header.

Everything else is the same as on the Claude API, including the following:

* The `anthropic-version` and `anthropic-beta` headers
* The request body
* Streaming
* The response

Code samples elsewhere in this documentation create the Claude API client and read an API key. To run one with Claude Models on Google Cloud (Anthropic managed), replace its import and client constructor with the ones in the following examples. For a cURL sample, apply the three differences listed earlier.

Before running these examples, complete the steps in [Before making API calls](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#before-making-api-calls).

<CodeGroup>
  ```bash cURL
  curl "https://claude.googleapis.com/v1/projects/$ANTHROPIC_GOOGLE_CLOUD_PROJECT/locations/global/workspaces/$ANTHROPIC_GOOGLE_CLOUD_WORKSPACE_ID/invoke/v1/messages" \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "content-type: application/json" \
    -H "anthropic-version: 2023-06-01" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [
        {"role": "user", "content": "Hello, Claude"}
      ]
    }'
  ```

  ```bash CLI
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --message '{role: user, content: "Hello, Claude"}'
  ```

  ```python Python
  from anthropic import AnthropicGoogleCloud

  client = AnthropicGoogleCloud()

  message = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      messages=[{"role": "user", "content": "Hello, Claude"}],
  )
  print(message)
  ```

  ```typescript TypeScript
  import { AnthropicGoogleCloud } from "@anthropic-ai/google-cloud-sdk";

  const client = new AnthropicGoogleCloud();

  const message = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello, Claude" }]
  });
  console.log(message);
  ```

  ```csharp C#
  using Anthropic.GoogleCloud;
  using Anthropic.Models.Messages;

  var client = new AnthropicGoogleCloudClient();

Cut at 300 lines. The page has the rest.

build-with-claude/claude-models-on-google-cloud/google-managed New page · 763 lines, new page

## Before making API calls ### Install an SDK ## Making requests ### API model IDs ## Global, multi-region, and regional endpoints ## Feature support ### Features not supported ### Context window ## Billing, rate limits, and logging ### Rate limits ### Billing ### Data retention ### Monitoring and logging ## Migrating from Claude Models on Google Cloud (Anthropic managed) ## Next steps

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Claude Models on Google Cloud (Google managed)
url: https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed
description: Google operates Claude Models on Google Cloud (Google managed) as part of Google Cloud's Agent Platform. You can call Claude with Anthropic's client SDKs.
---

[Claude Models on Google Cloud](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/overview) compares the two Google Cloud offerings. It also shows how to tell which one you use.

## Before making API calls

To use Claude Models on Google Cloud (Google managed), you need:

1. A Google Cloud project that can use Agent Platform. For setup steps, see Google Cloud's [Anthropic Claude models on Agent Platform](https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/partner-models/claude) page.
2. The [gcloud CLI](https://cloud.google.com/sdk/docs/install) installed, for local development.
3. For the identity making the calls, an IAM role that includes the `aiplatform.endpoints.predict` permission, such as Agent Platform User (`roles/aiplatform.user`). For details, see Google Cloud's [Agent Platform partner models](https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/partner-models/use-partner-models) page.
4. Google Cloud credentials for that identity. For the SDK examples, you might need to run `gcloud auth application-default login` to authenticate with Google Cloud. The cURL examples for Claude Models on Google Cloud (Google managed) get their token with `gcloud auth print-access-token`. That command uses the gcloud CLI's own login, not Application Default Credentials. For those examples, run `gcloud auth login` or `gcloud init` first.

### Install an SDK

Anthropic's [client SDKs](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) support Claude Models on Google Cloud (Google managed) through `AnthropicVertex` (csharp: `AnthropicVertexClient`; go: `vertex.WithGoogleAuth`; java: `VertexBackend`; php: `Anthropic\Vertex\Client`; ruby: `Anthropic::VertexClient`). Install the package that provides it:

<Tabs>
  <Tab title="Python">
    ```bash
    pip install -U "anthropic[vertex]"
    ```
  </Tab>

  <Tab title="TypeScript">
    ```bash
    npm install @anthropic-ai/vertex-sdk
    ```
  </Tab>

  <Tab title="C#">
    ```bash
    dotnet add package Anthropic.Vertex
    ```
  </Tab>

  <Tab title="Go">
    ```bash
    go get github.com/anthropics/anthropic-sdk-go/v2
    ```
  </Tab>

  <Tab title="Java">
    <CodeGroup exclude="shell, python, typescript, csharp, go, php, ruby">
      ```groovy Gradle
      implementation("com.anthropic:anthropic-java:3.1.0")
      implementation("com.anthropic:anthropic-java-vertex:3.1.0")
      ```

      ```xml Maven
      <dependency>
          <groupId>com.anthropic</groupId>
          <artifactId>anthropic-java</artifactId>
          <version>3.1.0</version>
      </dependency>
      <dependency>
          <groupId>com.anthropic</groupId>
          <artifactId>anthropic-java-vertex</artifactId>
          <version>3.1.0</version>
      </dependency>
      ```
    </CodeGroup>
  </Tab>

  <Tab title="PHP">
    ```bash
    composer require anthropic-ai/sdk google/auth
    ```
  </Tab>

  <Tab title="Ruby">
    ```bash
    # Gemfile
    gem "anthropic"
    gem "googleauth"
    ```
  </Tab>
</Tabs>

The `ant` CLI doesn't support Claude Models on Google Cloud (Google managed).

## Making requests

Requests to Claude Models on Google Cloud (Google managed) go to an Agent Platform endpoint URL that ends in `:rawPredict`. Streaming requests use `:streamRawPredict` instead.

A request is nearly identical to a [Messages API](https://platform.claude.com/docs/en/api/messages/create) request. It differs in two main ways:

* **Model:** The endpoint URL names the model. In a cURL request, leave `model` out of the body.
* **Version:** In a cURL request, pass `anthropic_version` in the body, not as a header. Set it to `vertex-2023-10-16`, or to [API version `2026-10-21`](https://platform.claude.com/docs/en/api/migration-2026-10-21).

The following examples use the global endpoint. For the other endpoint types, see [Global, multi-region, and regional endpoints](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed#global-multi-region-and-regional-endpoints).

<CodeGroup exclude="shell:CLI">
  ```bash cURL
  curl https://aiplatform.googleapis.com/v1/projects/MY_PROJECT_ID/locations/global/publishers/anthropic/models/claude-opus-5-5:rawPredict \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -d '{
      "anthropic_version": "vertex-2023-10-16",
      "messages": [{"role": "user", "content": "Hey Claude!"}],
      "max_tokens": 100
    }'
  ```

  <CodeGroupItem language="CLI">
    The `ant` CLI doesn't support Claude Models on Google Cloud (Google managed).
  </CodeGroupItem>

  ```python 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)
  ```

  ```typescript TypeScript
  import { AnthropicVertex } from "@anthropic-ai/vertex-sdk";

  const projectId = "MY_PROJECT_ID";
  const region = "global";

  // Goes through the standard `google-auth-library` flow.
  const client = new AnthropicVertex({
    projectId,
    region
  });

  const result = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 100,
    messages: [
      {
        role: "user",
        content: "Hey Claude!"
      }
    ]
  });
  console.log(JSON.stringify(result, null, 2));
  ```

  ```csharp C#
  using Anthropic.Models.Messages;
  using Anthropic.Vertex;

  var projectId = "MY_PROJECT_ID";
  var region = "global";

  var client = new AnthropicVertexClient(new AnthropicVertexCredentials(region, projectId));

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 100,
      Messages = [new UserMessageParam { Content = "Hey Claude!" }]
  };

  var message = await client.Messages.Create(parameters);
  Console.WriteLine(message);
  ```

  ```go Go
  import (
  	"context"
  	"fmt"

  	"github.com/anthropics/anthropic-sdk-go/v2"
  	"github.com/anthropics/anthropic-sdk-go/v2/vertex"
  )
  // ...
  	// Uses default Google Cloud credentials
  	client := anthropic.NewClient(
  		vertex.WithGoogleAuth(context.Background(), "global", "MY_PROJECT_ID"),
  	)

  	message, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 100,
  		Messages: []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock("Hey Claude!")),
  		},
  	})
  	if err != nil {
  		panic(err)
  	}
  	fmt.Printf("%+v\n", message)
  ```

  ```java Java
  import com.anthropic.client.AnthropicClient;
  import com.anthropic.client.okhttp.AnthropicOkHttpClient;
  import com.anthropic.models.messages.Message;
  import com.anthropic.models.messages.MessageCreateParams;
  import com.anthropic.models.messages.Model;
  import com.anthropic.vertex.backends.VertexBackend;
  import com.google.auth.oauth2.GoogleCredentials;

  void main() throws Exception {
      AnthropicClient client = AnthropicOkHttpClient.builder()
          .backend(
              VertexBackend.builder()
                  .googleCredentials(GoogleCredentials.getApplicationDefault())
                  .region("global")
                  .project("MY_PROJECT_ID")
                  .build()
          )
          .build();

      Message message = client
          .messages()
          .create(
              MessageCreateParams.builder()
                  .model(Model.CLAUDE_OPUS_5_5)
                  .maxTokens(100)
                  .addUserMessage("Hey Claude!")
                  .build()
          );

      IO.println(message);
  }
  ```

  ```php PHP
  <?php

  use Anthropic\Messages\TextBlock;
  use Anthropic\Vertex;

  $client = Vertex\Client::fromEnvironment(
      region: 'global',
      projectId: 'MY_PROJECT_ID',
  );

  $message = $client->messages->create(
      maxTokens: 100,
      messages: [
          ['role' => 'user', 'content' => 'Hey Claude!']
      ],
      model: 'claude-opus-5-5',
  );

  foreach ($message->content as $block) {
      if ($block instanceof TextBlock) {
          echo $block->text . PHP_EOL;
      }
  }
  ```

  ```ruby Ruby
  require "anthropic"

  client = Anthropic::VertexClient.new(
    region: "global",
    project_id: "MY_PROJECT_ID"
  )

  message = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 100,
    messages: [{role: "user", content: "Hey Claude!"}]
  )

  puts message.content.find { it.type == :text }.text
  ```
</CodeGroup>

### API model IDs

| Model                                                                                                 | Agent Platform API model ID  |
| :---------------------------------------------------------------------------------------------------- | :--------------------------- |
| Claude Fable 5.1                                                                                      | `claude-fable-5-1`           |
| Claude Mythos 5.1 ([limited availability](https://support.claude.com/en/articles/14604842))           | `claude-mythos-5-1`          |
| Claude Fable 5                                                                                        | `claude-fable-5`             |
| Claude Mythos 5 ([limited availability](https://support.claude.com/en/articles/14604842))             | `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](https://platform.claude.com/docs/en/about-claude/model-deprecations))   | `claude-opus-4-1@20250805`   |
| Claude Opus 4 ([deprecated](https://platform.claude.com/docs/en/about-claude/model-deprecations))     | `claude-opus-4@20250514`     |
| Claude Sonnet 5.5                                                                                     | `claude-sonnet-5-5`          |

Cut at 300 lines. The page has the rest.

build-with-claude/claude-models-on-google-cloud/overview New page · 79 lines, new page

## How the two Google Cloud offerings differ ## What both offerings share ## Moving between the two offerings ## Which offering are you using? ## Next steps

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Claude Models on Google Cloud
url: https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/overview
description: Compare Claude Models on Google Cloud (Anthropic managed) and Claude Models on Google Cloud (Google managed), and find out which one you use.
---

You can use Claude through your Google Cloud project in two ways:

* **[Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed):** Anthropic operates the [Claude API](https://platform.claude.com/docs/en/api/overview).
* **[Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed):** Google operates Claude models as part of Google Cloud's Agent Platform.

## How the two Google Cloud offerings differ

The following table compares Claude Models on Google Cloud (Anthropic managed) with Claude Models on Google Cloud (Google managed).

| Aspect                                           | [Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed)                                                        | [Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed)                                                                                                 |
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **API surface**                                  | Claude API endpoints<br />`/v1/{endpoint}`                                                                                                                                                                        | Agent Platform prediction endpoints                                                                                                                                                                                                                  |
| **Request format**                               | Same as the Claude API<br />`model` in the request body<br />`anthropic-version` header                                                                                                                           | `model` in the URL<br />`anthropic_version` in the request body                                                                                                                                                                                      |
| **Streaming**                                    | `"stream": true` in the request body                                                                                                                                                                              | A separate `:streamRawPredict` endpoint                                                                                                                                                                                                              |
| **Location**                                     | `global`<br />See [Project, location, and workspace resolution](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#project-location-and-workspace-resolution). | A global, multi-region, or regional endpoint<br />See [Global, multi-region, and regional endpoints](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed#global-multi-region-and-regional-endpoints). |
| **Model IDs for models earlier than Claude 4.6** | The Claude API ID<br />Example: `claude-haiku-4-5-20251001`                                                                                                                                                       | The Claude API ID, with `@` in place of the hyphen before the snapshot date<br />Example: `claude-haiku-4-5@20251001`<br />See [Model IDs and versioning](https://platform.claude.com/docs/en/about-claude/models/model-ids-and-versions).           |
| **Services to enable on your project**           | See [Set up your account](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#set-up-your-account).                                                             | The Agent Platform API<br />`aiplatform.googleapis.com`                                                                                                                                                                                              |
| **Anthropic organization**                       | A new Anthropic organization for your project                                                                                                                                                                     | None                                                                                                                                                                                                                                                 |
| **Billing**                                      | Google Cloud Marketplace                                                                                                                                                                                          | Google Cloud, as Agent Platform usage                                                                                                                                                                                                                |
| **Rate limits**                                  | Managed by Anthropic                                                                                                                                                                                              | Managed by Google Cloud                                                                                                                                                                                                                              |

## What both offerings share

* **Credentials:** Both offerings use Google Cloud credentials, including Application Default Credentials. You grant access to each offering separately, through its own IAM roles.

  * [Credentials for Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#authentication)
  * [Credentials for Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed#before-making-api-calls)

* **Billing:** Charges for both offerings appear on your Google Cloud bill.

  * [Billing for Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#billing)
  * [Billing for Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed#billing)

* **Model IDs:** Claude 4.6 and later models use their Claude API IDs on both offerings. See [Model IDs and versioning](https://platform.claude.com/docs/en/about-claude/models/model-ids-and-versions).

* **SDKs:** Anthropic's [client SDKs](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) support both offerings.

## Moving between the two offerings

Follow the steps for whichever offering you're moving to:

* [Steps for moving to Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#migrating-from-google-managed)
* [Steps for moving to Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed#migrating-from-anthropic-managed)

## Which offering are you using?

The following table lists values that identify Claude Models on Google Cloud (Anthropic managed) and Claude Models on Google Cloud (Google managed). Find a value you already have. For example, look for the host in your request URLs or the SDK client in your code. The heading of that value's column is your offering.

| What to check                                               | [Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed)                                                                                                                         | [Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed)                                                                                                                                                                      |
| ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Where your requests go**                                  | `claude.googleapis.com`<br />The URL includes your workspace ID.<br />It ends in a Claude API path, such as `.../invoke/v1/messages`.                                                                                                                                              | One of these Agent Platform hosts:<br />`aiplatform.googleapis.com`<br />`aiplatform.us.rep.googleapis.com`<br />`aiplatform.eu.rep.googleapis.com`<br />`{region}-aiplatform.googleapis.com`<br />The URL path contains `.../publishers/anthropic/models/{model}`.<br />It ends in `:rawPredict` or `:streamRawPredict`. |
| **SDK client in your code**                                 | `AnthropicGoogleCloud` (csharp: `AnthropicGoogleCloudClient`; go: `googlecloud.NewClient`; java: `GoogleCloudBackend`; php: `Anthropic\GoogleCloud\Client`; ruby: `Anthropic::GoogleCloudClient`)<br />In every SDK, the client name contains `GoogleCloud` (all lowercase in Go). | `AnthropicVertex` (csharp: `AnthropicVertexClient`; go: `vertex.WithGoogleAuth`; java: `VertexBackend`; php: `Anthropic\Vertex\Client`; ruby: `Anthropic::VertexClient`)<br />In every SDK, the client name contains `Vertex` (all lowercase in Go).                                                                      |
| **IAM roles that grant access**                             | `roles/claude.admin`<br />`roles/claude.user`<br />`roles/claude.viewer`                                                                                                                                                                                                           | Agent Platform IAM roles                                                                                                                                                                                                                                                                                                  |
| **Management console**                                      | The Claude Console, at `platform.claude.com`<br />You open it from the Google Cloud console.                                                                                                                                                                                       | The Google Cloud console                                                                                                                                                                                                                                                                                                  |
| **Where each offering appears in the Google Cloud console** | The option labeled **Anthropic managed**<br />See [Set up your account](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#set-up-your-account).                                                                                | Claude models in [Model Garden](https://cloud.google.com/model-garden)                                                                                                                                                                                                                                                    |

If you call `api.anthropic.com` with an API key, you use neither offering. To move those calls to Claude Models on Google Cloud (Anthropic managed), see [Moving from an existing Anthropic organization](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#moving-from-an-existing-anthropic-organization).

## Next steps

<CardGroup cols={2}>
  <Card title="Claude Models on Google Cloud (Anthropic managed)" icon="cloud" href="https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed">
    Set up your account and make your first request.
  </Card>

  <Card title="Claude Models on Google Cloud (Google managed)" icon="cloud" href="https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed">
    Install an SDK and make your first request.
  </Card>

  <Card title="IAM permissions for Claude Models on Google Cloud (Anthropic managed)" icon="lock" href="https://platform.claude.com/docs/en/api/claude-models-on-google-cloud-anthropic-managed-iam-permissions">
    Look up permissions, roles, and audit log types.
  </Card>
</CardGroup>

build-with-claude/claude-on-amazon-bedrock-legacy Changed · +56 / -56 lines

from line 311
311311<Tabs>
312312 <Tab title="cURL">
313313 <Note>
314 Calling the `InvokeModel` API with AWS credentials requires SigV4 request signing, which the SDK handles automatically. For a Bedrock endpoint you can call with a self-contained cURL command, see [Making your first request with Claude in Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock#making-your-first-request).
314 Calling the `InvokeModel` API with AWS credentials requires SigV4 request signing, which the SDK examples in the other tabs handle automatically. For a Bedrock endpoint you can call with a self-contained cURL command, see [Making your first request with Claude in Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock#making-your-first-request).
315315 </Note>
316316 </Tab>
317317 
from line 444
444444 
445445 public class BedrockExample {
446446 
447 public static void main(String[] args) {
448 // Uses default AWS credential provider chain
449 AnthropicClient client = AnthropicOkHttpClient.builder()
450 .backend(BedrockBackend.fromEnv())
451 .build();
447 public static void main(String[] args) {
448 // Uses default AWS credential provider chain
449 AnthropicClient client = AnthropicOkHttpClient.builder()
450 .backend(BedrockBackend.fromEnv())
451 .build();
452452 
453 Message message = client
454 .messages()
455 .create(
456 MessageCreateParams.builder()
457 .model("global.anthropic.claude-opus-4-6-v1")
458 .maxTokens(256)
459 .addUserMessage("Hello, world")
460 .build()
461 );
453 Message message = client
454 .messages()
455 .create(
456 MessageCreateParams.builder()
457 .model("global.anthropic.claude-opus-4-6-v1")
458 .maxTokens(256)
459 .addUserMessage("Hello, world")
460 .build()
461 );
462462 
463 System.out.println(message.content());
464 }
463 System.out.println(message.content());
464 }
465465 }
466466 ```
467467 </Tab>
from line 473
473473 use Anthropic\Bedrock;
474474 
475475 $client = Bedrock\Client::withCredentials(
476 accessKeyId: getenv("AWS_ACCESS_KEY_ID"),
477 secretAccessKey: getenv("AWS_SECRET_ACCESS_KEY"),
476 accessKeyId: getenv('AWS_ACCESS_KEY_ID'),
477 secretAccessKey: getenv('AWS_SECRET_ACCESS_KEY'),
478478 region: 'us-west-2',
479 securityToken: getenv("AWS_SESSION_TOKEN"),
479 securityToken: getenv('AWS_SESSION_TOKEN'),
480480 );
481481 
482482 $message = $client->messages->create(
from line 653
653653 
654654 // Option 1: Set AWS_BEARER_TOKEN_BEDROCK environment variable and use fromEnv()
655655 AnthropicClient client = AnthropicOkHttpClient.builder()
656 .backend(BedrockBackend.fromEnv())
657 .build();
656 .backend(BedrockBackend.fromEnv())
657 .build();
658658 
659659 // Option 2: Provide the token programmatically
660660 client = AnthropicOkHttpClient.builder()
661 .backend(BedrockBackend.builder()
662 .apiKey("your-bearer-token")
663 .build())
664 .build();
661 .backend(BedrockBackend.builder()
662 .apiKey("your-bearer-token")
663 .build())
664 .build();
665665 
666666 MessageCreateParams params = MessageCreateParams.builder()
667 .model("us.anthropic.claude-sonnet-4-5-20250929-v1:0")
668 .maxTokens(1024)
669 .addUserMessage("Hello!")
670 .build();
667 .model("us.anthropic.claude-sonnet-4-5-20250929-v1:0")
668 .maxTokens(1024)
669 .addUserMessage("Hello!")
670 .build();
671671 
672672 client.messages().create(params).content().stream()
673 .flatMap(block -> block.text().stream())
674 .forEach(textBlock -> System.out.println(textBlock.text()));
673 .flatMap(block -> block.text().stream())
674 .forEach(textBlock -> System.out.println(textBlock.text()));
675675 ```
676676 </Tab>
677677 
from line 809
809809<Tabs>
810810 <Tab title="cURL">
811811 <Note>
812 Calling the `InvokeModel` API with AWS credentials requires SigV4 request signing, which the SDK handles automatically. For a Bedrock endpoint you can call with a self-contained cURL command, see [Making your first request with Claude in Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock#making-your-first-request).
812 Calling the `InvokeModel` API with AWS credentials requires SigV4 request signing, which the SDK examples in the other tabs handle automatically. For a Bedrock endpoint you can call with a self-contained cURL command, see [Making your first request with Claude in Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock#making-your-first-request).
813813 </Note>
814814 </Tab>
815815 
from line 903
903903 
904904 // Uses default AWS credential provider chain
905905 AnthropicClient client = AnthropicOkHttpClient.builder()
906 .backend(BedrockBackend.fromEnv())
907 .build();
906 .backend(BedrockBackend.fromEnv())
907 .build();
908908 
909909 var message = client
910 .messages()
911 .create(
912 MessageCreateParams.builder()
913 .model("global.anthropic.claude-opus-4-6-v1")
914 .maxTokens(256)
915 .addUserMessage("Hello, world")
916 .build()
917 );
910 .messages()
911 .create(
912 MessageCreateParams.builder()
913 .model("global.anthropic.claude-opus-4-6-v1")
914 .maxTokens(256)
915 .addUserMessage("Hello, world")
916 .build()
917 );
918918 ```
919919 </Tab>
920920 
from line 960
960960<Tabs>
961961 <Tab title="cURL">
962962 <Note>
963 Calling the `InvokeModel` API with AWS credentials requires SigV4 request signing, which the SDK handles automatically. For a Bedrock endpoint you can call with a self-contained cURL command, see [Making your first request with Claude in Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock#making-your-first-request).
963 Calling the `InvokeModel` API with AWS credentials requires SigV4 request signing, which the SDK examples in the other tabs handle automatically. For a Bedrock endpoint you can call with a self-contained cURL command, see [Making your first request with Claude in Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock#making-your-first-request).
964964 </Note>
965965 </Tab>
966966 
from line 1055
10551055 
10561056 // Uses default AWS credential provider chain
10571057 AnthropicClient client = AnthropicOkHttpClient.builder()
1058 .backend(BedrockBackend.fromEnv())
1059 .build();
1058 .backend(BedrockBackend.fromEnv())
1059 .build();
10601060 
10611061 // Using US regional endpoint (CRIS)
10621062 var message = client
1063 .messages()
1064 .create(
1065 MessageCreateParams.builder()
1066 .model("us.anthropic.claude-opus-4-6-v1") // Regional prefix
1067 .maxTokens(256)
1068 .addUserMessage("Hello, world")
1069 .build()
1070 );
1063 .messages()
1064 .create(
1065 MessageCreateParams.builder()
1066 .model("us.anthropic.claude-opus-4-6-v1") // Regional prefix
1067 .maxTokens(256)
1068 .addUserMessage("Hello, world")
1069 .build()
1070 );
10711071 ```
10721072 </Tab>
10731073 

build-with-claude/claude-on-vertex-ai Page removed · 763 lines, page removed

## Before making API calls ### Install an SDK ## Making requests ### API model IDs ## Global, multi-region, and regional endpoints ## Feature support ### Features not supported ### Context window ## Billing, rate limits, and logging ### Rate limits ### Billing ### Data retention ### Monitoring and logging ## Migrating from Claude Models on Google Cloud (Anthropic managed) ## Next steps

The page is gone upstream. What it last said is kept here.

build-with-claude/claude-platform-on-aws Changed · +31 / -28 lines

from line 26
2626| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
2727| **Who operates the stack** | Anthropic | AWS | AWS |
2828| **API surface** | Claude API (`/v1/{endpoint}`) | Messages API at `/anthropic/v1/messages` | Bedrock Converse / InvokeModel |
29| **Feature availability** | Typically same-day as Claude API (see [feature limitations](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#features-not-supported)) | Per Amazon Bedrock release schedule | Per Amazon Bedrock release schedule |
29| **Feature availability** | Typically same-day as Claude API (see [feature limitations](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#features-not-supported)) | Follows the Amazon Bedrock release schedule | Follows the Amazon Bedrock release schedule |
3030| **Agent Skills** | Available | Not available (requires code execution) | Not available |
3131| **Beta features** | Pass through with `anthropic-beta` headers (see [feature limitations](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#features-not-supported)) | The beta features Amazon Bedrock supports, through the `anthropic-beta` header | The beta features Amazon Bedrock supports, through the `anthropic_beta` field of the InvokeModel request body |
3232| **Authentication** | AWS IAM / SigV4 or API key | AWS IAM / SigV4 | AWS IAM / SigV4 or bearer token |
from line 117
117117Once the new organization is running, the differences are concentrated in billing and authentication, which are handled through AWS:
118118 
119119* **Billing** moves to AWS Marketplace: usage is billed in Claude Consumption Units rather than prepaid credits (see [Billing](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#billing)), and you set spend limits on the **Billing** page (see [Spend limits](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#spend-limits)). During the transition, billing stays separate: the existing organization continues to be billed as it is today.
120* **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](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#authentication)). Organization membership is managed through AWS IAM rather than the Claude Console (see [Available pages](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#available-pages)), and the SDK provides a platform-specific client class (see [Install an SDK](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#install-an-sdk)).
120* **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](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#authentication)). Organization membership is managed through AWS IAM rather than the Claude Console (see [Available pages](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#available-pages)), and the Claude SDK provides a platform-specific client class (see [Install an SDK](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#install-an-sdk)).
121121* **Day-to-day API usage** works the way it does on the first-party Claude API, except where noted in the [feature limitations](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#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](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#rate-limits-and-quotas)).
122122 
123123For Claude Enterprise (claude.ai) organizations, which behave differently, see the [offering comparison](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#claude-platform-on-aws-vs-amazon-bedrock).
from line 239
239239 import com.anthropic.client.okhttp.AnthropicOkHttpClient;
240240 
241241 void main() {
242 String token = TokenGenerator.builder().region(Region.US_WEST_2).build().getToken();
242 String token = TokenGenerator.builder()
243 .region(Region.US_WEST_2)
244 .build()
245 .getToken();
243246 
244247 AnthropicClient client = AnthropicOkHttpClient.builder()
245248 .backend(AwsBackend.builder()
from line 392
389392 # Omit the x-amz-security-token header if you use long-term IAM user credentials
390393 curl "https://aws-external-anthropic.us-west-2.api.aws/v1/messages" \
391394 --aws-sigv4 "aws:amz:us-west-2:aws-external-anthropic" \
392 --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
395 -u "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
393396 -H "x-amz-security-token: $AWS_SESSION_TOKEN" \
394397 -H "content-type: application/json" \
395398 -H "anthropic-version: 2023-06-01" \
from line 615
612615 # Omit the x-amz-security-token header if you use long-term IAM user credentials
613616 curl "https://aws-external-anthropic.us-west-2.api.aws/v1/messages" \
614617 --aws-sigv4 "aws:amz:us-west-2:aws-external-anthropic" \
615 --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
618 -u "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
616619 -H "x-amz-security-token: $AWS_SESSION_TOKEN" \
617620 -H "content-type: application/json" \
618621 -H "anthropic-version: 2023-06-01" \
from line 808
8058083. Click **Open Claude Console**. The AWS Console issues a JWT and redirects you to `platform.claude.com`.
8068094. 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.
807810 
808Two 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, request log, rate limit, and workspace information. Contact your Anthropic account representative to assign the Admin or Developer role to a principal.
811Two 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.
809812 
810813### Available pages
811814 
812815The **Through AWS gateway** column indicates whether the page reads and writes data through the AWS gateway (and is therefore governed by [IAM actions for Claude Platform on AWS](https://platform.claude.com/docs/en/api/claude-platform-on-aws-iam-actions)). Pages marked **No** read organization-level metadata directly from Anthropic and bypass IAM action checks.
813816 
814| Page | Available | Through AWS gateway | Notes |
815| --------------------- | ------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
816| **Usage** | Yes | No | View token usage by model, workspace, and dimension. Data can take a few minutes to appear after a request. |
817| **Cost** | Yes | No | View cost breakdowns by model and workspace. AWS Cost Explorer shows the aggregated [Claude Consumption Unit (CCU)](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#billing) line item. |
818| **Rate limits** | Yes | No | View rate limits (read-only). Tier increases go through your Anthropic account representative; see [Rate limits and quotas](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#rate-limits-and-quotas). |
819| **Logs** | Yes | No | View per-request metadata such as time, model, workspace, token counts, and status. Log entries do not include prompts or responses. |
820| **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](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#spend-limits). |
821| **Encryption keys** | Yes | Yes | A section of the [Data retention](https://platform.claude.com/settings/privacy#encryption-keys) page (`platform.claude.com/settings/privacy`) in the Claude Console, shown while **Organization** is selected in the dropdown menu at the top of the page. Register AWS KMS keys there (Admin role), as described in [Set up CMEK on Claude Platform on AWS](https://platform.claude.com/docs/en/manage-claude/cmek-claude-platform-on-aws). To attach a registered key to a workspace, select the workspace from that dropdown menu, then select the key under **Encryption key**. |
822| **Files** | Yes | Yes | View and manage uploaded files. |
823| **Skills** | Yes | Yes | View and manage Agent Skills. |
824| **Batches** | Yes | Yes | View and manage batch processing jobs. |
825| **Agents** | Yes | Yes | View and manage agent definitions. |
826| **Sessions** | Yes | Yes | View agent sessions and event history. |
827| **Environments** | Yes | Yes | View and manage cloud sandbox configurations for sessions. |
828| **Credential vaults** | Yes | Yes | View and manage credential vaults for session authentication. |
829| **Memory stores** | Yes | Yes | View and manage persistent agent memory. |
830| **Webhooks** | Yes | Yes | View and manage webhook endpoints. |
831| **API keys** | No | N/A | Manage API keys in the AWS Console (**Claude Platform on AWS → API keys**). See [API key authentication](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#api-key-authentication). |
832| **Members** | No | N/A | Not applicable. AWS IAM manages access. |
833| **Billing** | Yes (limited) | No | Set an organization monthly spend limit; see [Spend limits](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#spend-limits). AWS Marketplace manages invoicing. View cost breakdowns on the **Cost** page. |
834| **Claude Code** | No | N/A | View Claude Code usage on the **Usage** page. |
817| Page | Available | Through AWS gateway | Notes |
818| --------------------- | ---------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
819| **Usage** | Yes | No | View token usage by model, workspace, and dimension. Data can take a few minutes to appear after a request. |
820| **Cost** | Yes | No | View cost breakdowns by model and workspace. AWS Cost Explorer shows the aggregated [Claude Consumption Unit (CCU)](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#billing) line item. |
821| **Rate limits** | Yes | No | View rate limits (read-only). Tier increases go through your Anthropic account representative; see [Rate limits and quotas](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#rate-limits-and-quotas). |
822| **Logs** | Yes (Admin role) | No | View per-request metadata such as time, model, workspace, token counts, and status. Log entries do not include prompts or responses. |
823| **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](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#spend-limits). |
824| **Encryption keys** | Yes | Yes | A section of the [Data retention](https://platform.claude.com/settings/privacy#encryption-keys) page (`platform.claude.com/settings/privacy`) in the Claude Console, shown while **Organization** is selected in the dropdown menu at the top of the page. Register AWS KMS keys there (Admin role), as described in [Set up CMEK on Claude Platform on AWS](https://platform.claude.com/docs/en/manage-claude/cmek-claude-platform-on-aws). To attach a registered key to a workspace, select the workspace from that dropdown menu, then select the key under **Encryption key**. |
825| **Files** | Yes | Yes | View and manage uploaded files. |
826| **Skills** | Yes | Yes | View and manage Agent Skills. |
827| **Batches** | Yes | Yes | View and manage batch processing jobs. |
828| **Agents** | Yes | Yes | View and manage agent definitions. |
829| **Sessions** | Yes | Yes | View agent sessions and event history. |
830| **Environments** | Yes | Yes | View and manage cloud sandbox configurations for sessions. |
831| **Credential vaults** | Yes | Yes | View and manage credential vaults for session authentication. |
832| **Memory stores** | Yes | Yes | View and manage persistent agent memory. |
833| **Webhooks** | Yes | Yes | View and manage webhook endpoints. |
834| **API keys** | No | N/A | Manage API keys in the AWS Console (**Claude Platform on AWS → API keys**). See [API key authentication](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#api-key-authentication). |
835| **Members** | No | N/A | Not applicable. AWS IAM manages access. |
836| **Billing** | Yes (limited) | No | Set an organization monthly spend limit; see [Spend limits](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#spend-limits). AWS Marketplace manages invoicing. View cost breakdowns on the **Cost** page. |
837| **Claude Code** | No | N/A | View Claude Code usage on the **Usage** page. |
835838 
836839### Switching organizations
837840 
from line 891
888891 # Omit the x-amz-security-token header if you use long-term IAM user credentials
889892 curl -i "https://aws-external-anthropic.us-west-2.api.aws/v1/messages" \
890893 --aws-sigv4 "aws:amz:us-west-2:aws-external-anthropic" \
891 --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
894 -u "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
892895 -H "x-amz-security-token: $AWS_SESSION_TOKEN" \
893896 -H "content-type: application/json" \
894897 -H "anthropic-version: 2023-06-01" \

build-with-claude/compaction-threshold Changed · +31 / -28 lines

from line 27
2727 Claude API: beta
2828 Claude Platform on AWS: beta
2929 Amazon Bedrock: beta
30 Google Cloud: beta
30 Claude Models on Google Cloud (Google managed): beta
3131 Microsoft Foundry: beta
3232---
3333 
from line 239
239239 $response = $client->beta->messages->create(
240240 maxTokens: 4096,
241241 messages: $messages,
242 model: 'claude-opus-5-5',
242 model: Model::CLAUDE_OPUS_5_5,
243243 betas: ['compact-2026-01-12'],
244244 contextManagement: [
245245 'edits' => [
from line 459
459459 $message = $client->beta->messages->create(
460460 maxTokens: 4096,
461461 messages: $messages,
462 model: 'claude-opus-5-5',
462 model: Model::CLAUDE_OPUS_5_5,
463463 betas: ['compact-2026-01-12'],
464464 contextManagement: [
465465 'edits' => [
from line 684
684684 ['role' => 'assistant', 'content' => "I'll help you build a web scraper..."],
685685 ['role' => 'user', 'content' => 'Add support for JavaScript-rendered pages']
686686 ],
687 model: 'claude-opus-5-5',
687 model: Model::CLAUDE_OPUS_5_5,
688688 betas: ['compact-2026-01-12'],
689689 contextManagement: [
690690 'edits' => [
from line 1070
10701070 
10711071#### Enforcing a total token budget
10721072 
1073When 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 end the task once a budget is reached.
1073When 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 conclude the task once a budget is reached.
10741074 
10751075This 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](https://platform.claude.com/docs/en/build-with-claude/compaction-threshold#trigger-configuration) with `pause_after_compaction` from [Pausing after compaction](https://platform.claude.com/docs/en/build-with-claude/compaction-threshold#pausing-after-compaction).
10761076 
from line 1180
11801180 compactionCount += 1;
11811181 messages.Add(new BetaAssistantMessageParam
11821182 {
1183 Content = response.Content.Select(b => new BetaContentBlockParam(b.Json)).ToList()
1183 Content = response.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList()
11841184 });
11851185 
11861186 // Estimate total tokens consumed; prompt wrap-up if over budget
from line 1884
18841884 try (var streamResponse = client.beta().messages().createStreaming(params)) {
18851885 streamResponse.stream().forEach(event -> {
18861886 event.contentBlockStart().ifPresent(startEvent -> {
1887 startEvent.contentBlock().compaction().ifPresent(c ->
1887 startEvent.contentBlock().compaction().ifPresent(compactionBlock ->
18881888 System.out.println("Compaction started...")
18891889 );
1890 startEvent.contentBlock().text().ifPresent(t ->
1890 startEvent.contentBlock().text().ifPresent(textBlock ->
18911891 System.out.println("Text response started...")
18921892 );
18931893 });
18941894 
18951895 event.contentBlockDelta().ifPresent(deltaEvent -> {
1896 deltaEvent.delta().compaction().ifPresent(cd ->
1897 System.out.println("Compaction complete: " + cd.content().map(String::length).orElse(0) + " chars")
1896 deltaEvent.delta().compaction().ifPresent(compactionDelta ->
1897 System.out.println("Compaction complete: " + compactionDelta.content().map(String::length).orElse(0) + " chars")
18981898 );
1899 deltaEvent.delta().text().ifPresent(td ->
1900 System.out.print(td.text())
1899 deltaEvent.delta().text().ifPresent(textDelta ->
1900 System.out.print(textDelta.text())
19011901 );
19021902 });
19031903 });
from line 1911
19111911 use Anthropic\Beta\Messages\BetaRawContentBlockStartEvent;
19121912 use Anthropic\Beta\Messages\BetaTextBlock;
19131913 use Anthropic\Beta\Messages\BetaTextDelta;
1914 use Anthropic\Messages\Model;
19141915 
19151916 $client = new Client();
19161917 $messages = [['role' => 'user', 'content' => 'Hello, Claude']];
from line 1919
19181919 $stream = $client->beta->messages->createStream(
19191920 maxTokens: 4096,
19201921 messages: $messages,
1921 model: 'claude-opus-5-5',
1922 model: Model::CLAUDE_OPUS_5_5,
19221923 betas: ['compact-2026-01-12'],
19231924 contextManagement: [
19241925 'edits' => [
from line 1943
19421943 case $event instanceof BetaRawContentBlockDeltaEvent:
19431944 switch (true) {
19441945 case $event->delta instanceof BetaCompactionContentBlockDelta:
1945 echo "Compaction complete: " . strlen($event->delta->content ?? '') . " chars\n";
1946 echo 'Compaction complete: ' . strlen($event->delta->content ?? '') . " chars\n";
19461947 break;
19471948 case $event->delta instanceof BetaTextDelta:
19481949 echo $event->delta->text;
from line 2204
22032204 $response = $client->beta->messages->create(
22042205 maxTokens: 4096,
22052206 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
2206 model: 'claude-opus-5-5',
2207 model: Model::CLAUDE_OPUS_5_5,
22072208 betas: ['compact-2026-01-12'],
22082209 system: [
22092210 [
from line 2444
24432444 ]
24442445 );
24452446 
2446 echo "Current tokens: " . $countResponse->inputTokens . "\n";
2447 echo "Original tokens: " . $countResponse->contextManagement->originalInputTokens . "\n";
2447 echo 'Current tokens: ' . $countResponse->inputTokens . "\n";
2448 echo 'Original tokens: ' . $countResponse->contextManagement->originalInputTokens . "\n";
24482449 ```
24492450 
24502451 ```ruby Ruby
from line 2592
25912592 return response.Content
25922593 .Select(block => block.Value)
25932594 .OfType<BetaTextBlock>()
2594 .Select(tb => tb.Text)
2595 .Select(textBlock => textBlock.Text)
25952596 .FirstOrDefault() ?? "";
25962597 }
25972598 ```
from line 2698
26972698 $client = new Client();
26982699 $messages = [];
26992700 
2700 function chat($client, &$messages, $userMessage) {
2701 function chat($client, &$messages, $userMessage)
2702 {
27012703 $messages[] = ['role' => 'user', 'content' => $userMessage];
27022704 
27032705 $response = $client->beta->messages->create(
from line 2727
27252727 return '';
27262728 }
27272729 
2728 echo chat($client, $messages, "Help me build a Python web scraper") . "\n";
2729 echo chat($client, $messages, "Add support for JavaScript-rendered pages") . "\n";
2730 echo chat($client, $messages, "Now add rate limiting and error handling") . "\n";
2730 echo chat($client, $messages, 'Help me build a Python web scraper') . "\n";
2731 echo chat($client, $messages, 'Add support for JavaScript-rendered pages') . "\n";
2732 echo chat($client, $messages, 'Now add rate limiting and error handling') . "\n";
27312733 ```
27322734 
27332735 ```ruby Ruby
from line 3029
30273029 return response.Content
30283030 .Select(block => block.Value)
30293031 .OfType<BetaTextBlock>()
3030 .Select(tb => tb.Text)
3032 .Select(textBlock => textBlock.Text)
30313033 .FirstOrDefault() ?? "";
30323034 }
30333035 ```
from line 3228
32263228 $client = new Client();
32273229 $messages = [];
32283230 
3229 function chat($client, &$messages, $userMessage) {
3231 function chat($client, &$messages, $userMessage)
3232 {
32303233 $messages[] = ['role' => 'user', 'content' => $userMessage];
32313234 
32323235 $response = $client->beta->messages->create(
from line 3291
32883291 return '';
32893292 }
32903293 
3291 echo chat($client, $messages, "Help me build a Python web scraper") . "\n";
3292 echo chat($client, $messages, "Add support for JavaScript-rendered pages") . "\n";
3293 echo chat($client, $messages, "Now add rate limiting and error handling") . "\n";
3294 echo chat($client, $messages, 'Help me build a Python web scraper') . "\n";
3295 echo chat($client, $messages, 'Add support for JavaScript-rendered pages') . "\n";
3296 echo chat($client, $messages, 'Now add rate limiting and error handling') . "\n";
32943297 ```
32953298 
32963299 ```ruby Ruby
from line 3380
33773380 Learn about context window sizes and management strategies.
33783381 </Card>
33793382 
3380 <Card title="Session memory compaction recipe" icon="book" href="https://platform.claude.com/cookbook/misc-session-memory-compaction">
3383 <Card title="Session memory compaction recipe (Claude Cookbook)" icon="book" href="https://platform.claude.com/cookbook/misc-session-memory-compaction">
33813384 Explore a practical implementation that manages long-running conversations with instant session memory compaction using background threading and prompt caching.
33823385 </Card>
33833386</CardGroup>

build-with-claude/context-editing Changed · +7 / -7 lines

from line 871
871871 messages: [
872872 ['role' => 'user', 'content' => 'Hello']
873873 ],
874 model: 'claude-opus-5-5',
874 model: Model::CLAUDE_OPUS_5_5,
875875 betas: ['context-management-2025-06-27'],
876876 contextManagement: [
877877 'edits' => [
from line 1093
10931093 messages: [
10941094 ['role' => 'user', 'content' => 'Hello']
10951095 ],
1096 model: 'claude-opus-5-5',
1096 model: Model::CLAUDE_OPUS_5_5,
10971097 betas: ['context-management-2025-06-27'],
10981098 contextManagement: [
10991099 'edits' => [
from line 1293
12931293 messages: [
12941294 ['role' => 'user', 'content' => 'Hello']
12951295 ],
1296 model: 'claude-opus-5-5',
1296 model: Model::CLAUDE_OPUS_5_5,
12971297 betas: ['context-management-2025-06-27'],
12981298 contextManagement: [
12991299 'edits' => [
from line 2032
20322032 ],
20332033 );
20342034 
2035 echo "Original tokens: " . $response->contextManagement->originalInputTokens . "\n";
2036 echo "After clearing: " . $response->inputTokens . "\n";
2037 echo "Savings: " . ($response->contextManagement->originalInputTokens - $response->inputTokens) . " tokens\n";
2035 echo 'Original tokens: ' . $response->contextManagement->originalInputTokens . "\n";
2036 echo 'After clearing: ' . $response->inputTokens . "\n";
2037 echo 'Savings: ' . ($response->contextManagement->originalInputTokens - $response->inputTokens) . " tokens\n";
20382038 ```
20392039 
20402040 ```ruby Ruby
from line 2258
22582258 messages: [
22592259 ['role' => 'user', 'content' => 'Hello']
22602260 ],
2261 model: 'claude-opus-5-5',
2261 model: Model::CLAUDE_OPUS_5_5,
22622262 betas: ['context-management-2025-06-27'],
22632263 tools: [
22642264 [

build-with-claude/effort Changed · +4 / -3 lines

from line 27
2727 Claude API: ga
2828 Claude Platform on AWS: ga
2929 Amazon Bedrock: ga
30 Google Cloud: ga
30 Claude Models on Google Cloud (Google managed): ga
3131 Microsoft Foundry: ga
3232---
3333 
from line 117
117117 Model = Model.ClaudeOpus5_5,
118118 MaxTokens = 4096,
119119 Messages = [
120 new UserMessageParam {
120 new UserMessageParam
121 {
121122 Content = "Analyze the trade-offs between microservices and monolithic architectures"
122123 }
123124 ],
from line 339
338339 
339340To get less thinking, lower the effort level. You can also send `thinking: {"type": "disabled"}` at `high` effort or below. At `xhigh` or `max`, it returns a 400 error, so use adaptive thinking there: omit the `thinking` field or send `thinking: {"type": "adaptive"}`.
340341 
341On the Claude API and Claude Models on Google Cloud (Google managed), Claude Haiku 5.5 also supports [changing effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta) with a per-message `output_config`, which preserves the prompt cache. With `thinking: {"type": "disabled"}`, effort can't change mid-conversation: a per-message `output_config.effort` that differs from the level in effect returns a 400 error. To vary effort per turn, use adaptive thinking.
342On the Claude API and Claude Models on Google Cloud (Google managed), Claude Haiku 5.5 also supports [changing effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta) with a per-message `output_config`, which preserves the prompt cache. With `thinking: {"type": "disabled"}`, effort can't change mid-conversation: a per-message `output_config.effort` that differs from the level in effect returns a 400 error. To vary effort for each turn, use adaptive thinking.
342343 
343344## Effort with tool use
344345 

build-with-claude/fast-mode Changed · +31 / -28 lines

from line 146
146146 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
147147 
148148 Message response = client.messages().create(
149 MessageCreateParams.builder()
150 .model(Model.CLAUDE_OPUS_5_5)
151 .maxTokens(4096L)
152 .speed(MessageCreateParams.Speed.FAST)
153 .addUserMessage("Refactor this module to use dependency injection")
154 .build());
149 MessageCreateParams.builder()
150 .model(Model.CLAUDE_OPUS_5_5)
151 .maxTokens(4096L)
152 .speed(MessageCreateParams.Speed.FAST)
153 .addUserMessage("Refactor this module to use dependency injection")
154 .build());
155155 
156156 response.content().stream()
157 .flatMap(block -> block.text().stream())
158 .forEach(textBlock -> IO.println(textBlock.text()));
157 .flatMap(block -> block.text().stream())
158 .forEach(textBlock -> IO.println(textBlock.text()));
159159 ```
160160 
161161 ```php PHP
from line 162
162162 $client = new Client();
163163 
164164 $response = $client->messages->create(
165 model: 'claude-opus-5-5',
165 model: Model::CLAUDE_OPUS_5_5,
166166 maxTokens: 4096,
167167 speed: 'fast',
168168 messages: [
from line 338
338338 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
339339 
340340 MessageCreateParams params = MessageCreateParams.builder()
341 .model(Model.CLAUDE_OPUS_5_5)
342 .maxTokens(1024L)
343 .speed(MessageCreateParams.Speed.FAST)
344 .addUserMessage("Hello")
345 .build();
341 .model(Model.CLAUDE_OPUS_5_5)
342 .maxTokens(1024L)
343 .speed(MessageCreateParams.Speed.FAST)
344 .addUserMessage("Hello")
345 .build();
346346 
347347 Message response = client.messages().create(params);
348348 IO.println(response.usage().speed().orElseThrow()); // "fast" or "standard"
from line 352
352352 $client = new Client();
353353 
354354 $response = $client->messages->create(
355 model: 'claude-opus-5-5',
355 model: Model::CLAUDE_OPUS_5_5,
356356 maxTokens: 1024,
357357 speed: 'fast',
358358 messages: [['role' => 'user', 'content' => 'Hello']],
from line 578
578578 import com.anthropic.errors.InternalServerException;
579579 import com.anthropic.errors.RateLimitException;
580580 // ...
581 // Disable SDK auto-retry so the fallback logic below handles it
581 // Disable SDK auto-retry so the fallback logic that follows handles it
582582 AnthropicClient client =
583 AnthropicOkHttpClient.builder().fromEnv().maxRetries(0).build();
583 AnthropicOkHttpClient.builder()
584 .fromEnv()
585 .maxRetries(0)
586 .build();
584587 
585588 Message createMessageWithFastFallback(
586589 MessageCreateParams params, int maxAttempts) {
from line 592
589592 } catch (RateLimitException e) {
590593 if (params.speed().isPresent()) {
591594 MessageCreateParams retryParams = params.toBuilder()
592 .speed(Optional.empty())
593 .build();
595 .speed(Optional.empty())
596 .build();
594597 return createMessageWithFastFallback(retryParams, maxAttempts);
595598 }
596599 throw e;
from line 607
604607 
605608 void main() {
606609 Message message = createMessageWithFastFallback(
607 MessageCreateParams.builder()
608 .model(Model.CLAUDE_OPUS_5_5)
609 .maxTokens(1024L)
610 .addUserMessage("Hello")
611 .speed(MessageCreateParams.Speed.FAST)
612 .build(),
613 3);
610 MessageCreateParams.builder()
611 .model(Model.CLAUDE_OPUS_5_5)
612 .maxTokens(1024L)
613 .addUserMessage("Hello")
614 .speed(MessageCreateParams.Speed.FAST)
615 .build(),
616 3);
614617 message.content().stream()
615 .flatMap(block -> block.text().stream())
616 .forEach(textBlock -> IO.println(textBlock.text()));
618 .flatMap(block -> block.text().stream())
619 .forEach(textBlock -> IO.println(textBlock.text()));
617620 }
618621 ```
619622 

build-with-claude/files Changed · +3 / -2 lines

from line 607
607607 $client = new Client();
608608 
609609 // Read the text file
610 $textContent = file_get_contents("document.txt");
610 $textContent = file_get_contents('document.txt');
611611 
612612 $message = $client->messages->create(
613613 maxTokens: 1024,
from line 668
668668 
669669#### List files
670670 
671Retrieve 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](https://platform.claude.com/docs/en/api/files/list). The SDK returns the first page and provides [auto-pagination](https://platform.claude.com/docs/en/api/overview#pagination) helpers. The CLI example bounds the total with `--max-items`:
671Retrieve 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](https://platform.claude.com/docs/en/api/files/list). The SDK returns the first page and provides [auto-pagination](https://platform.claude.com/docs/en/api/overview#pagination) helpers.
672672 
673673<CodeGroup>
674674 ```bash cURL
from line 678
678678 ```
679679 
680680 ```bash CLI
681 # List commands auto-paginate, so --max-items limits the total
681682 ant files list --max-items 10
682683 ```
683684 

build-with-claude/handling-stop-reasons Changed · +60 / -52 lines

from line 262
262262 "content": [
263263 {"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"}
264264 ],
265 }, # Just the tool_result, no additional text
265 }, # Only the tool_result, no additional text
266266 ]
267267 ```
268268 
from line 306
306306 },
307307 {
308308 role: "user",
309 // Just the tool_result, no additional text
309 // Only the tool_result, no additional text
310310 content: [{ type: "tool_result", tool_use_id: "toolu_123", content: "6912" }]
311311 }
312312 ];
from line 354
354354 },
355355 new UserMessageParam
356356 {
357 // Just the tool_result, no additional text
357 // Only the tool_result, no additional text
358358 Content = new List<ContentBlockParam>
359359 {
360360 new ToolResultBlockParam { ToolUseID = "toolu_123", Content = "6912" }
from line 384
384384 anthropic.NewAssistantMessage(
385385 anthropic.NewToolUseBlock("toolu_123", input, "calculator"),
386386 ),
387 // Just the tool_result, no additional text
387 // Only the tool_result, no additional text
388388 anthropic.NewUserMessage(
389389 anthropic.NewToolResultBlock("toolu_123", "6912", false),
390390 ),
from line 408
408408 MessageParam.ofAssistantOfContentBlockParams(List.of(ContentBlockParam.ofToolUse(toolUse))),
409409 MessageParam.ofUserOfContentBlockParams(List.of(
410410 ContentBlockParam.ofToolResult(
411 ToolResultBlockParam.builder().toolUseId("toolu_123").content("6912").build()),
411 ToolResultBlockParam.builder()
412 .toolUseId("toolu_123")
413 .content("6912")
414 .build()),
412415 // Don't add text after tool_result
413 ContentBlockParam.ofText(TextBlockParam.builder().text("Here's the result").build())
416 ContentBlockParam.ofText(TextBlockParam.builder()
417 .text("Here's the result")
418 .build())
414419 ))
415420 );
416421 
from line 423
418423 messages = List.of(
419424 MessageParam.ofUser("Calculate the sum of 1234 and 5678"),
420425 MessageParam.ofAssistantOfContentBlockParams(List.of(ContentBlockParam.ofToolUse(toolUse))),
421 // Just the tool_result, no additional text
426 // Only the tool_result, no additional text
422427 MessageParam.ofUserOfContentBlockParams(List.of(
423428 ContentBlockParam.ofToolResult(
424 ToolResultBlockParam.builder().toolUseId("toolu_123").content("6912").build())
429 ToolResultBlockParam.builder()
430 .toolUseId("toolu_123")
431 .content("6912")
432 .build())
425433 ))
426434 );
427435 ```
from line 475
467475 ],
468476 [
469477 'role' => 'user',
470 // Just the tool_result, no additional text
478 // Only the tool_result, no additional text
471479 'content' => [
472480 ['type' => 'tool_result', 'tool_use_id' => 'toolu_123', 'content' => '6912'],
473481 ],
from line 524
516524 },
517525 {
518526 role: "user",
519 # Just the tool_result, no additional text
527 # Only the tool_result, no additional text
520528 content: [
521529 { type: "tool_result", tool_use_id: "toolu_123", content: "6912" }
522530 ]
from line 855
847855 $response = $client->messages->create(
848856 maxTokens: 10,
849857 messages: [['role' => 'user', 'content' => 'Explain quantum physics']],
850 model: 'claude-opus-5-5',
858 model: Model::CLAUDE_OPUS_5_5,
851859 );
852860 
853861 if ($response->stopReason === 'max_tokens') {
from line 1159
11511159 $response = $client->messages->create(
11521160 maxTokens: 1024,
11531161 messages: [['role' => 'user', 'content' => 'Generate text until you say END']],
1154 model: 'claude-opus-5-5',
1162 model: Model::CLAUDE_OPUS_5_5,
11551163 stopSequences: ['END', 'STOP'],
11561164 );
11571165 
from line 1248
12401248 
12411249 
12421250 def execute_tool(name, tool_input):
1243 """Execute a tool and return the result."""
1251 """Run a tool and return the result."""
12441252 return f"Weather in {tool_input.get('location', 'unknown')}: 72°F"
12451253 
12461254 
from line 1260
12521260 )
12531261 
12541262 if response.stop_reason == "tool_use":
1255 # Extract and execute the tool
1263 # Extract and run the tool
12561264 for block in response.content:
12571265 if block.type == "tool_use":
12581266 result = execute_tool(block.name, block.input)
from line 1293
12851293 });
12861294 
12871295 if (response.stop_reason === "tool_use") {
1288 // Extract and execute the tool
1296 // Extract and run the tool
12891297 for (const block of response.content) {
12901298 if (block.type === "tool_use") {
12911299 const result = executeTool(block.name, block.input as Record<string, string>);
from line 1332
13241332 
13251333 if (response.StopReason == "tool_use")
13261334 {
1327 // Extract and execute the tool
1335 // Extract and run the tool
13281336 foreach (var block in response.Content)
13291337 {
13301338 if (block.TryPickToolUse(out var toolUse))
13311339 {
1332 // Execute toolUse.Name with toolUse.Input and return the result to Claude
1340 // Run toolUse.Name with toolUse.Input and return the result to Claude
13331341 }
13341342 }
13351343 }
from line 1370
13621370 }
13631371 
13641372 if response.StopReason == "tool_use" {
1365 // Extract and execute the tool
1373 // Extract and run the tool
13661374 for _, block := range response.Content {
13671375 if toolUse, ok := block.AsAny().(anthropic.ToolUseBlock); ok {
13681376 fmt.Println(toolUse.Name, toolUse.Input)
from line 1405
13971405 );
13981406 
13991407 if (response.stopReason().map(StopReason.TOOL_USE::equals).orElse(false)) {
1400 // Extract and execute the tool
1408 // Extract and run the tool
14011409 for (ContentBlock block : response.content()) {
14021410 block.toolUse().ifPresent(toolUse -> {
1403 // Execute toolUse.name() with toolUse.input() and return the result to Claude
1411 // Run toolUse.name() with toolUse.input() and return the result to Claude
14041412 });
14051413 }
14061414 }
from line 1437
14291437 );
14301438 
14311439 if ($response->stopReason === 'tool_use') {
1432 // Extract and execute the tool
1440 // Extract and run the tool
14331441 foreach ($response->content as $block) {
14341442 if ($block->type === 'tool_use') {
1435 // Execute $block->name with $block->input and return the result to Claude
1443 // Run $block->name with $block->input and return the result to Claude
14361444 }
14371445 }
14381446 }
from line 1469
14611469 )
14621470 
14631471 if response.stop_reason == :tool_use
1464 # Extract and execute the tool
1472 # Extract and run the tool
14651473 response.content.each do |block|
14661474 next unless block.type == :tool_use
1467 # Execute block.name with block.input and return the result to Claude
1475 # Run block.name with block.input and return the result to Claude
14681476 end
14691477 end
14701478 ```
from line 1866
18581866 $response = $client->messages->create(
18591867 maxTokens: 1024,
18601868 messages: [['role' => 'user', 'content' => '[Unsafe request]']],
1861 model: 'claude-opus-5-5',
1869 model: Model::CLAUDE_OPUS_5_5,
18621870 );
18631871 
18641872 if ($response->stopReason === 'refusal') {
from line 2332
23242332 ```python Python
23252333 def handle_server_tool_conversation(client, user_query, tools, max_continuations=5):
23262334 """
2327 Handle server tool conversations that may require multiple continuations.
2335 Handle server tool conversations that might require multiple continuations.
23282336 
2329 The server runs a sampling loop when executing server tools. If the loop
2337 The server uses a sampling loop to run server tools. If the loop
23302338 reaches its iteration limit, the API returns pause_turn. Continue the
23312339 conversation by sending the response back to let Claude finish.
23322340 """
from line 2349
23412349 )
23422350 
23432351 if response.stop_reason != "pause_turn":
2344 # Claude finished processing - return the final response
2352 # Claude finished processing: return the final response
23452353 return response
23462354 
23472355 # pause_turn: replace the full message list to maintain alternating roles
from line 2358
23502358 {"role": "assistant", "content": response.content},
23512359 ]
23522360 
2353 # Reached max continuations - return the last response
2361 # Reached max continuations: return the last response
23542362 return response
23552363 ```
23562364 
from line 2381
23732381 });
23742382 
23752383 if (response.stop_reason !== "pause_turn") {
2376 // Claude finished processing - return the final response
2384 // Claude finished processing: return the final response
23772385 return response;
23782386 }
23792387 
from line 2392
23842392 ];
23852393 }
23862394 
2387 // Reached max continuations - return the last response
2395 // Reached max continuations: return the last response
23882396 return response!;
23892397 }
23902398 ```
from line 2419
24112419 
24122420 if (response.StopReason != "pause_turn")
24132421 {
2414 // Claude finished processing - return the final response
2422 // Claude finished processing: return the final response
24152423 return response;
24162424 }
24172425 
from line 2434
24262434 ];
24272435 }
24282436 
2429 // Reached max continuations - return the last response
2437 // Reached max continuations: return the last response
24302438 return response;
24312439 }
24322440 ```
from line 2462
24542462 }
24552463 
24562464 if response.StopReason != "pause_turn" {
2457 // Claude finished processing - return the final response
2465 // Claude finished processing: return the final response
24582466 return response, nil
24592467 }
24602468 
from line 2477
24692477 }
24702478 }
24712479 
2472 // Reached max continuations - return the last response
2480 // Reached max continuations: return the last response
24732481 return response, nil
24742482 }
24752483 ```
from line 2505
24972505 response = client.messages().create(params.build());
24982506 
24992507 if (!response.stopReason().map(StopReason.PAUSE_TURN::equals).orElse(false)) {
2500 // Claude finished processing - return the final response
2508 // Claude finished processing: return the final response
25012509 return response;
25022510 }
25032511 // pause_turn: loop again and send the response back
25042512 }
25052513 
2506 // Reached max continuations - return the last response
2514 // Reached max continuations: return the last response
25072515 return response;
25082516 }
25092517 ```
from line 2535
25272535 );
25282536 
25292537 if ($response->stopReason !== 'pause_turn') {
2530 // Claude finished processing - return the final response
2538 // Claude finished processing: return the final response
25312539 return $response;
25322540 }
25332541 
from line 2546
25382546 ];
25392547 }
25402548 
2541 // Reached max continuations - return the last response
2549 // Reached max continuations: return the last response
25422550 return $response;
25432551 }
25442552 ```
from line 2564
25562564 tools: tools
25572565 )
25582566 
2559 # Claude finished processing - return the final response
2567 # Claude finished processing: return the final response
25602568 return response unless response.stop_reason == :pause_turn
25612569 
25622570 # pause_turn: replace the full message list to maintain alternating roles
from line 2574
25662574 ]
25672575 end
25682576 
2569 # Reached max continuations - return the last response
2577 # Reached max continuations: return the last response
25702578 response
25712579 end
25722580 ```
from line 2765
27572765 $response = $client->messages->create(
27582766 maxTokens: 1024,
27592767 messages: [['role' => 'user', 'content' => 'Hello!']],
2760 model: 'claude-opus-5-5',
2768 model: Model::CLAUDE_OPUS_5_5,
27612769 );
27622770 
27632771 // Handle successful response with stop_reason
from line 2814
28062814<CodeGroup>
28072815 ```bash cURL
28082816 # The message_delta event in the SSE stream carries stop_reason.
2809 curl --no-buffer https://api.anthropic.com/v1/messages \
2817 curl -N https://api.anthropic.com/v1/messages \
28102818 -H "x-api-key: $ANTHROPIC_API_KEY" \
28112819 -H "anthropic-version: 2023-06-01" \
28122820 -H "content-type: application/json" \
from line 2940
29322940 $stream = $client->messages->createStream(
29332941 maxTokens: 1024,
29342942 messages: [['role' => 'user', 'content' => 'Hello!']],
2935 model: 'claude-opus-5-5',
2943 model: Model::CLAUDE_OPUS_5_5,
29362944 );
29372945 
29382946 foreach ($stream as $event) {
from line 2989
29812989 )
29822990 
29832991 if response.stop_reason == "tool_use":
2984 # Execute tools and continue
2992 # Run tools and continue
29852993 tool_results = execute_tools(response.content)
29862994 messages.append({"role": "assistant", "content": response.content})
29872995 messages.append({"role": "user", "content": tool_results})
from line 3015
30073015 });
30083016 
30093017 if (response.stop_reason === "tool_use") {
3010 // Execute tools and continue
3018 // Run tools and continue
30113019 const toolResults = executeTools(response.content);
30123020 messages.push({ role: "assistant", content: response.content });
30133021 messages.push({ role: "user", content: toolResults });
from line 3047
30393047 
30403048 if (response.StopReason == "tool_use")
30413049 {
3042 // Execute tools and continue
3050 // Run tools and continue
30433051 var toolResults = ExecuteTools(response.Content);
30443052 messages.Add(new AssistantMessageParam
30453053 {
from line 3088
30803088 return response, nil
30813089 }
30823090 
3083 // Execute tools and continue
3091 // Run tools and continue
30843092 toolResults := executeTools(response.Content)
30853093 var contentParams []anthropic.ContentBlockParamUnion
30863094 for _, block := range response.Content {
from line 3123
31153123 return response;
31163124 }
31173125 
3118 // Execute tools and continue
3126 // Run tools and continue
31193127 List<ToolResultBlockParam> toolResults = executeTools(response.content());
31203128 messages.add(response.toParam());
31213129 messages.add(MessageParam.ofUserOfContentBlockParams(
from line 3150
31423150 return $response;
31433151 }
31443152 
3145 // Execute tools and continue
3153 // Run tools and continue
31463154 $toolResults = execute_tools($response->content);
31473155 $messages[] = ['role' => 'assistant', 'content' => $response->content];
31483156 $messages[] = ['role' => 'user', 'content' => $toolResults];
from line 3173
31653173 # Final response
31663174 return response unless response.stop_reason == :tool_use
31673175 
3168 # Execute tools and continue
3176 # Run tools and continue
31693177 tool_results = execute_tools(response.content)
31703178 messages << { role: "assistant", content: response.content }
31713179 messages << { role: "user", content: tool_results }

build-with-claude/mid-conversation-effort-example Changed · +180 / -174 lines

from line 199
199199 
200200 static final Model MODEL = Model.CLAUDE_OPUS_5_5;
201201 static final boolean DOC_TEST_MODE =
202 !Objects.requireNonNullElse(System.getenv("DOC_TEST_MODE"), "").isEmpty();
202 !Objects.requireNonNullElse(System.getenv("DOC_TEST_MODE"), "").isEmpty();
203203 static final OutputConfig.Effort EFFORT = OutputConfig.Effort.XHIGH;
204204 
205205 static final String SYSTEM_PROMPT =
206 "You are a helpful general-purpose agent. Answer the user's request directly.";
206 "You are a helpful general-purpose agent. Answer the user's request directly.";
207207 
208208 static final int REQUEST_TIMEOUT_SECONDS = 600;
209209 static final RequestOptions REQUEST_OPTIONS =
210 RequestOptions.builder().timeout(Duration.ofSeconds(REQUEST_TIMEOUT_SECONDS)).build();
210 RequestOptions.builder()
211 .timeout(Duration.ofSeconds(REQUEST_TIMEOUT_SECONDS))
212 .build();
211213 static final int BASH_TIMEOUT_SECONDS = 60;
212214 static final int TOOL_RESULT_MAX_CHARS = 8000;
213215 static final int MAX_CONCURRENT = 10;
from line 218
216218 static final int MAX_MAIN_TURNS = DOC_TEST_MODE ? 1 : 30;
217219 static final int TURNS_BETWEEN_REFRESHERS = 10;
218220 static final Path JOURNAL_PATH = Path.of(Optional.ofNullable(System.getenv("ORCH_JOURNAL"))
219 .filter(path -> !path.isEmpty())
220 .orElse("orchestration_journal.json"));
221 .filter(path -> !path.isEmpty())
222 .orElse("orchestration_journal.json"));
221223 ```
222224 
223225 ```php PHP
from line 332
330332 
331333 ```java Java
332334 static final String MODE_ENTER = """
333 Orchestration mode is on: optimize for the most exhaustive, correct answer rather than \
334 the fastest one. Use the Workflow tool on every substantive task, sized to the problem's \
335 natural decomposition rather than the maximum the tool allows. See the Workflow tool's \
336 description for standing consent, granularity guidance, and quality patterns. Work solo \
337 only on conversational or trivial turns.""";
335 Orchestration mode is on: optimize for the most exhaustive, correct answer rather than \
336 the fastest one. Use the Workflow tool on every substantive task, sized to the problem's \
337 natural decomposition rather than the maximum the tool allows. See the Workflow tool's \
338 description for standing consent, granularity guidance, and quality patterns. Work solo \
339 only on conversational or trivial turns.""";
338340 static final String MODE_REFRESH =
339 "Orchestration mode is still on. Use the Workflow tool; see its standing consent section.";
341 "Orchestration mode is still on. Use the Workflow tool; see its standing consent section.";
340342 static final String MODE_EXIT =
341 "Orchestration mode is off. The Workflow tool's standard opt-in rule applies again.";
343 "Orchestration mode is off. The Workflow tool's standard opt-in rule applies again.";
342344 ```
343345 
344346 ```php PHP
from line 664
662664 
663665 ```java Java
664666 static final Tool WORKFLOW_TOOL = Tool.builder()
665 .name("Workflow")
666 .description("""
667 Orchestrate a multiagent workflow: split a large task into independent subtasks \
668 and run them as parallel agents, then collect their results.
667 .name("Workflow")
668 .description("""
669 Orchestrate a multiagent workflow: split a large task into independent subtasks \
670 and run them as parallel agents, then collect their results.
669671 
670 Opt-in: only use this tool when the user explicitly asks for a workflow, or when a \
671 system message confirms that orchestration mode is on.
672 Opt-in: only use this tool when the user explicitly asks for a workflow, or when a \
673 system message confirms that orchestration mode is on.
672674 
673 Quality patterns: adversarial verification (a second wave of agents checks the first \
674 wave's findings against the source), a completeness critic (one agent hunts for what \
675 the others missed), and multiphase sequencing (understand, design, implement, and \
676 review as separate workflow calls, reading results between phases). A useful default \
677 is hybrid: scout inline first to discover the work-list, then fan out over it.
675 Quality patterns: adversarial verification (a second wave of agents checks the first \
676 wave's findings against the source), a completeness critic (one agent hunts for what \
677 the others missed), and multiphase sequencing (understand, design, implement, and \
678 review as separate workflow calls, reading results between phases). A useful default \
679 is hybrid: scout inline first to discover the work-list, then fan out over it.
678680 
679 Granularity: scope each subtask to a distinct concern, component, or question rather \
680 than per line or per file section. Scale the count to what the user asked for: a \
681 focused review of a module of a few hundred lines rarely needs more than about ten \
682 subtasks; a broad audit of a large codebase can justify more.
681 Granularity: scope each subtask to a distinct concern, component, or question rather \
682 than per line or per file section. Scale the count to what the user asked for: a \
683 focused review of a module of a few hundred lines rarely needs more than about ten \
684 subtasks; a broad audit of a large codebase can justify more.
683685 
684 Standing consent: while a system message confirms orchestration mode is on, that \
685 opt-in is standing. Author and run a workflow for every substantive task by default, \
686 and lean toward verifying findings adversarially. Work solo only on conversational \
687 turns or trivial mechanical edits. When a system message says the mode is off, \
688 revert to the opt-in rule above.""")
689 .inputSchema(Tool.InputSchema.builder()
690 .properties(Tool.InputSchema.Properties.builder()
691 .putAdditionalProperty("subtasks", JsonValue.from(Map.of(
692 "type", "array",
693 "items", Map.of("type", "string"),
694 "description", "Independent subtask prompts to run as parallel agents")))
695 .build())
696 .putAdditionalProperty("required", JsonValue.from(List.of("subtasks")))
697 .build())
698 .build();
686 Standing consent: while a system message confirms orchestration mode is on, that \
687 opt-in is standing. Author and run a workflow for every substantive task by default, \
688 and lean toward verifying findings adversarially. Work solo only on conversational \
689 turns or trivial mechanical edits. When a system message says the mode is off, \
690 revert to the opt-in rule above.""")
691 .inputSchema(Tool.InputSchema.builder()
692 .properties(Tool.InputSchema.Properties.builder()
693 .putAdditionalProperty("subtasks", JsonValue.from(Map.of(
694 "type", "array",
695 "items", Map.of("type", "string"),
696 "description", "Independent subtask prompts to run as parallel agents")))
697 .build())
698 .putAdditionalProperty("required", JsonValue.from(List.of("subtasks")))
699 .build())
700 .build();
699701 
700702 static final ToolBash20250124 BASH_TOOL = ToolBash20250124.builder().build();
701703 
702704 static final Tool REPORT_TOOL = Tool.builder()
703 .name("report_findings")
704 .description("""
705 Report the final findings for your subtask. Call this exactly once, when you are \
706 done investigating; it ends your task.""")
707 .inputSchema(Tool.InputSchema.builder()
708 .properties(Tool.InputSchema.Properties.builder()
709 .putAdditionalProperty("summary", JsonValue.from(Map.of(
710 "type", "string",
711 "description", "Two or three sentences of synthesis")))
712 .putAdditionalProperty("findings", JsonValue.from(Map.of(
713 "type", "array",
714 "items", Map.of(
715 "type", "object",
716 "properties", Map.of(
717 "claim", Map.of(
718 "type", "string",
719 "description", "The finding, one sentence"),
720 "evidence", Map.of(
721 "type", "string",
722 "description", "How it was verified (file, line, or command output)"),
723 "severity", Map.of(
724 "type", "string",
725 "enum", List.of("high", "medium", "low", "info"))),
726 "required", List.of("claim", "evidence", "severity")))))
727 .build())
728 .putAdditionalProperty("required", JsonValue.from(List.of("summary", "findings")))
729 .build())
730 .build();
705 .name("report_findings")
706 .description("""
707 Report the final findings for your subtask. Call this exactly once, when you are \
708 done investigating; it ends your task.""")
709 .inputSchema(Tool.InputSchema.builder()
710 .properties(Tool.InputSchema.Properties.builder()
711 .putAdditionalProperty("summary", JsonValue.from(Map.of(
712 "type", "string",
713 "description", "Two or three sentences of synthesis")))
714 .putAdditionalProperty("findings", JsonValue.from(Map.of(
715 "type", "array",
716 "items", Map.of(
717 "type", "object",
718 "properties", Map.of(
719 "claim", Map.of(
720 "type", "string",
721 "description", "The finding, one sentence"),
722 "evidence", Map.of(
723 "type", "string",
724 "description", "How it was verified (file, line, or command output)"),
725 "severity", Map.of(
726 "type", "string",
727 "enum", List.of("high", "medium", "low", "info"))),
728 "required", List.of("claim", "evidence", "severity")))))
729 .build())
730 .putAdditionalProperty("required", JsonValue.from(List.of("summary", "findings")))
731 .build())
732 .build();
731733 ```
732734 
733735 ```php PHP
from line 1058
10561058 return (output, process.ExitCode != 0);
10571059 }
10581060 
1059 // Execute one bash tool call requested by the model.
1061 // Run one bash tool call requested by the model.
10601062 async Task<(string Output, bool IsError)> HandleBashBlock(ToolUseBlock block)
10611063 {
10621064 if (block.Input.GetValueOrDefault("restart").ValueKind is JsonValueKind.True)
from line 1126
11241126 return fmt.Sprintf("(%s)\n%s", err, output), true
11251127 }
11261128 
1127 // handleBashBlock executes one bash tool call requested by the model.
1129 // handleBashBlock runs one bash tool call requested by the model.
11281130 func handleBashBlock(ctx context.Context, block anthropic.ToolUseBlock) (string, bool) {
11291131 var input struct {
11301132 Command string `json:"command"`
from line 1159
11571159 try {
11581160 var dir = Files.createTempDirectory("orchestration-");
11591161 Files.writeString(dir.resolve("sample.py"), """
1160 def fib(n):
1161 return n if n < 2 else fib(n - 1) + fib(n - 2)
1162 def fib(n):
1163 return n if n < 2 else fib(n - 1) + fib(n - 2)
11621164 
1163 print(fib(10))
1164 """);
1165 print(fib(10))
1166 """);
11651167 Runtime.getRuntime().addShutdownHook(new Thread(() -> {
11661168 // Best-effort cleanup; the OS tmp sweeper handles leftovers.
11671169 try (var paths = Files.walk(dir)) {
from line 1184
11821184 Process process;
11831185 try {
11841186 process = new ProcessBuilder("bash", "-c", command)
1185 .directory(WORK_DIR.toFile())
1186 .redirectErrorStream(true)
1187 .start();
1187 .directory(WORK_DIR.toFile())
1188 .redirectErrorStream(true)
1189 .start();
11881190 } catch (IOException error) {
11891191 return new ToolOutput("(" + error + ")", true);
11901192 }
1191 // Drain stdout on another thread so a filled pipe cannot stall the timeout wait below.
1193 // Drain stdout on another thread so a filled pipe cannot stall the timeout wait that follows.
11921194 CompletableFuture<String> outputReader = CompletableFuture.supplyAsync(() -> {
11931195 try (var stdout = process.getInputStream()) {
11941196 return new String(stdout.readAllBytes(), StandardCharsets.UTF_8);
from line 1208
12061208 output = "(no output)";
12071209 } else if (output.length() > TOOL_RESULT_MAX_CHARS) {
12081210 output = output.substring(0, TOOL_RESULT_MAX_CHARS)
1209 + "\n(truncated at " + TOOL_RESULT_MAX_CHARS + " chars)";
1211 + "\n(truncated at " + TOOL_RESULT_MAX_CHARS + " chars)";
12101212 }
12111213 int exitCode = process.exitValue();
12121214 return exitCode == 0
1213 ? new ToolOutput(output, false)
1214 : new ToolOutput("(exit code " + exitCode + ")\n" + output, true);
1215 ? new ToolOutput(output, false)
1216 : new ToolOutput("(exit code " + exitCode + ")\n" + output, true);
12151217 }
12161218 
12171219 // A tool call's input fields, or an empty map if the model sent something other than an object.
from line 1221
12191221 return toolUse._input() instanceof JsonObject object ? object.values() : Map.of();
12201222 }
12211223 
1222 // Execute one bash tool call requested by the model.
1224 // Run one bash tool call requested by the model.
12231225 ToolOutput handleBashBlock(ToolUseBlock toolUse) throws InterruptedException {
12241226 Map<String, JsonValue> input = toolInput(toolUse);
12251227 if (input.get("restart") instanceof JsonBoolean restart && restart.value()) {
from line 1291
12891291 return [$output, $exitCode !== 0];
12901292 }
12911293 
1292 /** Execute one bash tool call requested by the model. */
1294 /** Run one bash tool call requested by the model. */
12931295 function handleBashBlock(ToolUseBlock $block): array
12941296 {
12951297 if (($block->input['restart'] ?? null) === true) {
from line 1339
13371339 stdin.close
13381340 reader = Thread.new { stdout_and_stderr.read.scrub }
13391341 # Enforce the time limit with a monotonic-clock deadline so a timed-out command is
1340 # stopped rather than left running in the background.
1342 # ended rather than left running in the background.
13411343 deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + BASH_TIMEOUT_SECONDS
13421344 until wait_thr.join(0.1)
13431345 next if Process.clock_gettime(Process::CLOCK_MONOTONIC) < deadline
from line 1373
13711373 end
13721374 end
13731375 
1374 # Execute one bash tool call requested by the model.
1376 # Run one bash tool call requested by the model.
13751377 def handle_bash_block(block)
13761378 input = parse_tool_input(block.input)
13771379 return ["Shell restarted.", false] if input["restart"] == true
from line 1707
17051707 
17061708 ```java Java
17071709 static final String SUBAGENT_SYSTEM = """
1708 You are one agent in a larger parallel fan-out, assigned a single subtask. \
1709 Investigate it directly, using bash to check facts rather than guessing, and finish \
1710 by calling report_findings exactly once. Return findings, not narration.""";
1710 You are one agent in a larger parallel fan-out, assigned a single subtask. \
1711 Investigate it directly, using bash to check facts rather than guessing, and finish \
1712 by calling report_findings exactly once. Return findings, not narration.""";
17111713 
17121714 // One subagent: a small nested agent loop with the bash tool plus report_findings.
17131715 // Subagents inherit the main loop's effort level.
from line 1718
17161718 messages.add(MessageParam.ofUser(prompt));
17171719 for (int turn = 0; turn < MAX_SUBAGENT_TURNS; turn++) {
17181720 MessageCreateParams params = MessageCreateParams.builder()
1719 .model(model)
1720 .maxTokens(64000L)
1721 .system(SUBAGENT_SYSTEM)
1722 .outputConfig(OutputConfig.builder().effort(EFFORT).build())
1723 .addTool(BASH_TOOL)
1724 .addTool(REPORT_TOOL)
1725 .messages(messages)
1726 .build();
1721 .model(model)
1722 .maxTokens(64000L)
1723 .system(SUBAGENT_SYSTEM)
1724 .outputConfig(OutputConfig.builder()
1725 .effort(EFFORT)
1726 .build())
1727 .addTool(BASH_TOOL)
1728 .addTool(REPORT_TOOL)
1729 .messages(messages)
1730 .build();
17271731 MessageAccumulator accumulator = MessageAccumulator.create();
17281732 try (var stream = client.messages().createStreaming(params, REQUEST_OPTIONS)) {
17291733 stream.stream().forEach(accumulator::accumulate);
from line 1740
17361740 }
17371741 if (!StopReason.TOOL_USE.equals(stopReason)) {
17381742 String text = response.content().stream()
1739 .flatMap(block -> block.text().stream())
1740 .map(TextBlock::text)
1741 .collect(Collectors.joining());
1743 .flatMap(block -> block.text().stream())
1744 .map(TextBlock::text)
1745 .collect(Collectors.joining());
17421746 if (StopReason.MAX_TOKENS.equals(stopReason)) {
17431747 text += "\n\n(warning: subagent response was truncated at max_tokens)";
17441748 }
from line 1749
17451749 return text;
17461750 }
17471751 List<ToolUseBlock> toolUses = response.content().stream()
1748 .flatMap(block -> block.toolUse().stream())
1749 .toList();
1752 .flatMap(block -> block.toolUse().stream())
1753 .toList();
17501754 List<ContentBlockParam> toolResults = new ArrayList<>();
17511755 String report = null;
17521756 for (ToolUseBlock toolUse : toolUses) {
from line 1763
17591763 default -> new ToolOutput("unknown tool: " + toolUse.name(), true);
17601764 };
17611765 toolResults.add(ContentBlockParam.ofToolResult(ToolResultBlockParam.builder()
1762 .toolUseId(toolUse.id())
1763 .content(result.output())
1764 .isError(result.isError())
1765 .build()));
1766 .toolUseId(toolUse.id())
1767 .content(result.output())
1768 .isError(result.isError())
1769 .build()));
17661770 }
17671771 if (report != null) {
17681772 return report;
from line 2132
21282132 Map<String, String> loadJournal() {
21292133 try {
21302134 return Objects.requireNonNullElseGet(
2131 JOURNAL_MAPPER.readValue(Files.readString(JOURNAL_PATH), new TypeReference<HashMap<String, String>>() {}),
2132 HashMap::new);
2135 JOURNAL_MAPPER.readValue(Files.readString(JOURNAL_PATH), new TypeReference<HashMap<String, String>>() {}),
2136 HashMap::new);
21332137 } catch (IOException _) {
21342138 return new HashMap<>();
21352139 }
from line 2615
26112615 List<String> normalizeSubtasks(JsonValue rawSubtasks) {
26122616 List<String> tasks = switch (rawSubtasks) {
26132617 case JsonArray array -> array.values().stream()
2614 .map(item -> item instanceof JsonString text ? text.value() : item.toString())
2615 .toList();
2618 .map(item -> item instanceof JsonString text ? text.value() : item.toString())
2619 .toList();
26162620 case JsonString string -> parseSubtaskString(string.value());
26172621 default -> List.of();
26182622 };
26192623 return tasks.stream()
2620 .filter(Objects::nonNull)
2621 .map(String::strip)
2622 .filter(task -> !task.isEmpty())
2623 .toList();
2624 .filter(Objects::nonNull)
2625 .map(String::strip)
2626 .filter(task -> !task.isEmpty())
2627 .toList();
26242628 }
26252629 
26262630 List<String> parseSubtaskString(String encoded) {
from line 2638
26342638 
26352639 String verifyPromptFor(String subtask, String result) {
26362640 return """
2637 Adversarially verify the subagent result below: try to REFUTE it. Re-derive the \
2638 claims yourself with bash rather than trusting the result, and look for evidence \
2639 that contradicts them. Default to refuted if uncertain. Call report_findings with \
2640 summary 'refuted: <why>' or 'confirmed: <why>', citing the file:line or command \
2641 output that decided it.
2641 Adversarially verify the subagent result below: try to REFUTE it. Re-derive the \
2642 claims yourself with bash rather than trusting the result, and look for evidence \
2643 that contradicts them. Default to refuted if uncertain. Call report_findings with \
2644 summary 'refuted: <why>' or 'confirmed: <why>', citing the file:line or command \
2645 output that decided it.
26422646 
2643 Subtask: %s
2647 Subtask: %s
26442648 
2645 Result to verify:
2646 %s""".formatted(subtask, result);
2649 Result to verify:
2650 %s""".formatted(subtask, result);
26472651 }
26482652 
26492653 // invokeAll waits for every job, so each future is finished when it is read here.
26502654 List<String> runAll(ExecutorService pool, List<String> prompts, Model model) throws InterruptedException {
26512655 List<Callable<String>> jobs = prompts.stream()
2652 .<Callable<String>>map(prompt -> () -> journaled(prompt, () -> runSubagent(model, prompt)))
2653 .toList();
2656 .<Callable<String>>map(prompt -> () -> journaled(prompt, () -> runSubagent(model, prompt)))
2657 .toList();
26542658 return pool.invokeAll(jobs).stream()
2655 .map(future -> switch (future.state()) {
2656 case SUCCESS -> future.resultNow();
2657 // Isolation boundary: one bad subagent should not end the run.
2658 case FAILED -> "(subagent failed: " + future.exceptionNow() + ")";
2659 case CANCELLED, RUNNING -> "(subagent failed: cancelled)";
2660 })
2661 .toList();
2659 .map(future -> switch (future.state()) {
2660 case SUCCESS -> future.resultNow();
2661 // Isolation boundary: one bad subagent should not end the run.
2662 case FAILED -> "(subagent failed: " + future.exceptionNow() + ")";
2663 case CANCELLED, RUNNING -> "(subagent failed: cancelled)";
2664 })
2665 .toList();
26622666 }
26632667 
26642668 // Run subtasks as parallel subagents, then run a second verification wave over
from line 2683
26792683 results = runAll(pool, subtasks, model);
26802684 System.err.println("[workflow] verifying " + results.size() + " results");
26812685 List<String> verifyPrompts = IntStream.range(0, subtasks.size())
2682 .mapToObj(index -> verifyPromptFor(subtasks.get(index), results.get(index)))
2683 .toList();
2686 .mapToObj(index -> verifyPromptFor(subtasks.get(index), results.get(index)))
2687 .toList();
26842688 verdicts = runAll(pool, verifyPrompts, model);
26852689 }
26862690 String joined = IntStream.range(0, subtasks.size())
2687 .mapToObj(index -> """
2688 [agent %d: %s]
2689 %s
2691 .mapToObj(index -> """
2692 [agent %d: %s]
2693 %s
26902694 
2691 [verify %d]
2692 %s""".formatted(index + 1, subtasks.get(index), results.get(index), index + 1, verdicts.get(index)))
2693 .collect(Collectors.joining("\n\n"));
2695 [verify %d]
2696 %s""".formatted(index + 1, subtasks.get(index), results.get(index), index + 1, verdicts.get(index)))
2697 .collect(Collectors.joining("\n\n"));
26942698 if (dropped > 0) {
26952699 joined = """
2696 (note: %d subtasks beyond MAX_TOTAL_SUBTASKS=%d were not run; rerun them in a follow-up Workflow call)
2700 (note: %d subtasks beyond MAX_TOTAL_SUBTASKS=%d were not run; rerun them in a follow-up Workflow call)
26972701 
2698 %s""".formatted(dropped, MAX_TOTAL_SUBTASKS, joined);
2702 %s""".formatted(dropped, MAX_TOTAL_SUBTASKS, joined);
26992703 }
27002704 return new ToolOutput(joined, false);
27012705 }
from line 3235
32313235 return due;
32323236 }
32333237 
3234 // Send one user turn through the loop, executing tool calls until the model stops.
3238 // Send one user turn through the loop, running tool calls until the model stops.
32353239 async Task<string> Turn(string userInput)
32363240 {
32373241 // Mid-conversation system messages follow the user turn they apply to, which keeps
from line 3357
33533357 return due
33543358 }
33553359 
3356 // turn sends one user turn through the loop, executing tool calls until the model stops.
3360 // turn sends one user turn through the loop, running tool calls until the model stops.
33573361 func (agent *modeAgent) turn(ctx context.Context, userInput string) (string, error) {
33583362 // Mid-conversation system messages follow the user turn they apply to, which keeps
33593363 // the cached prefix ahead of them untouched.
from line 3477
34733477 return MessageParam.ofSystem(content);
34743478 }
34753479 
3476 // Send one user turn through the loop, executing tool calls until the model stops.
3480 // Send one user turn through the loop, running tool calls until the model stops.
34773481 String turn(String userInput) throws InterruptedException {
34783482 // Mid-conversation system messages follow the user turn they apply to, which keeps
34793483 // the cached prefix ahead of them untouched.
from line 3487
34833487 
34843488 for (int turn = 0; turn < MAX_MAIN_TURNS; turn++) {
34853489 MessageCreateParams params = MessageCreateParams.builder()
3486 .model(model)
3487 .maxTokens(64000L)
3488 .system(SYSTEM_PROMPT) // static for the whole session
3489 .outputConfig(OutputConfig.builder().effort(EFFORT).build())
3490 .addTool(WORKFLOW_TOOL)
3491 .addTool(BASH_TOOL)
3492 .messages(messages)
3493 .build();
3490 .model(model)
3491 .maxTokens(64000L)
3492 .system(SYSTEM_PROMPT) // static for the whole session
3493 .outputConfig(OutputConfig.builder()
3494 .effort(EFFORT)
3495 .build())
3496 .addTool(WORKFLOW_TOOL)
3497 .addTool(BASH_TOOL)
3498 .messages(messages)
3499 .build();
34943500 MessageAccumulator accumulator = MessageAccumulator.create();
34953501 try (var stream = client.messages().createStreaming(params, REQUEST_OPTIONS)) {
34963502 stream.stream().forEach(accumulator::accumulate);
from line 3510
35043510 }
35053511 if (!StopReason.TOOL_USE.equals(stopReason)) {
35063512 String text = response.content().stream()
3507 .flatMap(block -> block.text().stream())
3508 .map(TextBlock::text)
3509 .collect(Collectors.joining());
3513 .flatMap(block -> block.text().stream())
3514 .map(TextBlock::text)
3515 .collect(Collectors.joining());
35103516 if (StopReason.MAX_TOKENS.equals(stopReason)) {
35113517 // Drop the truncated assistant message so later turns do not build on it.
35123518 messages.removeLast();
from line 3522
35163522 }
35173523 
35183524 List<ToolUseBlock> toolUses = response.content().stream()
3519 .flatMap(block -> block.toolUse().stream())
3520 .toList();
3525 .flatMap(block -> block.toolUse().stream())
3526 .toList();
35213527 List<ContentBlockParam> toolResults = new ArrayList<>();
35223528 for (ToolUseBlock toolUse : toolUses) {
35233529 ToolOutput result = switch (toolUse.name()) {
35243530 case "Workflow" -> runWorkflow(model,
3525 toolInput(toolUse).getOrDefault("subtasks", JsonValue.from(List.of())));
3531 toolInput(toolUse).getOrDefault("subtasks", JsonValue.from(List.of())));
35263532 case "bash" -> handleBashBlock(toolUse);
35273533 default -> new ToolOutput("unknown tool: " + toolUse.name(), true);
35283534 };
35293535 toolResults.add(ContentBlockParam.ofToolResult(ToolResultBlockParam.builder()
3530 .toolUseId(toolUse.id())
3531 .content(result.output())
3532 .isError(result.isError())
3533 .build()));
3536 .toolUseId(toolUse.id())
3537 .content(result.output())
3538 .isError(result.isError())
3539 .build()));
35343540 }
35353541 messages.add(MessageParam.ofUserOfContentBlockParams(toolResults));
35363542 }
from line 3853
38473853 ```java Java
38483854 void main(String[] args) throws InterruptedException {
38493855 String task = args.length > 0 ? args[0] : """
3850 Explore the current directory, then give a thorough review: what it does, \
3851 code-quality issues, and concrete improvements.""";
3856 Explore the current directory, then give a thorough review: what it does, \
3857 code-quality issues, and concrete improvements.""";
38523858 ModeAgent agent = new ModeAgent(MODEL);
38533859 IO.println(agent.turn(task));
38543860 agent.setMode(false);

build-with-claude/pdf-support Changed · +227 / -200 lines

The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.

from line 11
1111 Claude API: ga
1212 Claude Platform on AWS: ga
1313 Amazon Bedrock: ga
14 Google Cloud: ga
14 Claude Models on Google Cloud (Google managed): ga
1515 Microsoft Foundry: ga
1616---
1717 
from line 262
262262 
263263 // Create document block with URL
264264 DocumentBlockParam documentParam = DocumentBlockParam.builder()
265 .source(
266 UrlPdfSource.builder()
267 .url(
268 "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
269 )
270 .build()
271 )
272 .build();
265 .source(
266 UrlPdfSource.builder()
267 .url(
268 "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
269 )
270 .build()
271 )
272 .build();
273273 
274274 // Create a message with document and text content blocks
275275 MessageCreateParams params = MessageCreateParams.builder()
276 .model(Model.CLAUDE_OPUS_5_5)
277 .maxTokens(1024)
278 .addUserMessageOfContentBlockParams(
279 List.of(
280 ContentBlockParam.ofDocument(documentParam),
281 ContentBlockParam.ofText(
282 TextBlockParam.builder()
283 .text("What are the key findings in this document?")
284 .build()
285 )
276 .model(Model.CLAUDE_OPUS_5_5)
277 .maxTokens(1024)
278 .addUserMessageOfContentBlockParams(
279 List.of(
280 ContentBlockParam.ofDocument(documentParam),
281 ContentBlockParam.ofText(
282 TextBlockParam.builder()
283 .text("What are the key findings in this document?")
284 .build()
285 )
286 )
286287 )
287 )
288 .build();
288 .build();
289289 
290290 Message message = client.messages().create(params);
291291 System.out.println(message.content());
from line 383
383383 
384384 # Create a JSON request file using the pdf_base64.txt content
385385 jq -n --rawfile PDF_BASE64 pdf_base64.txt '{
386 "model": "claude-opus-5-5",
387 "max_tokens": 1024,
388 "messages": [{
389 "role": "user",
390 "content": [{
391 "type": "document",
392 "source": {
393 "type": "base64",
394 "media_type": "application/pdf",
395 "data": $PDF_BASE64
396 }
397 },
398 {
399 "type": "text",
400 "text": "What are the key findings in this document?"
401 }]
386 "model": "claude-opus-5-5",
387 "max_tokens": 1024,
388 "messages": [{
389 "role": "user",
390 "content": [{
391 "type": "document",
392 "source": {
393 "type": "base64",
394 "media_type": "application/pdf",
395 "data": $PDF_BASE64
396 }
397 },
398 {
399 "type": "text",
400 "text": "What are the key findings in this document?"
402401 }]
402 }]
403403 }' > request.json
404404 
405405 # Send the API request using the JSON file
from line 588
588588 
589589 // Method 1: Download and encode a remote PDF
590590 String pdfUrl =
591 "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf";
592 HttpClient httpClient = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build();
593 HttpRequest request = HttpRequest.newBuilder().uri(URI.create(pdfUrl)).GET().build();
591 "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf";
592 HttpClient httpClient = HttpClient.newBuilder()
593 .followRedirects(HttpClient.Redirect.NORMAL)
594 .build();
595 HttpRequest request = HttpRequest.newBuilder()
596 .uri(URI.create(pdfUrl))
597 .GET()
598 .build();
594599 
595600 HttpResponse<byte[]> response = httpClient.send(
596 request,
597 HttpResponse.BodyHandlers.ofByteArray()
601 request,
602 HttpResponse.BodyHandlers.ofByteArray()
598603 );
599604 String pdfBase64 = Base64.getEncoder().encodeToString(response.body());
600605 
from line 609
604609 
605610 // Create document block with base64 data
606611 DocumentBlockParam documentParam = DocumentBlockParam.builder()
607 .source(Base64PdfSource.builder().data(pdfBase64).build())
608 .build();
612 .source(Base64PdfSource.builder()
613 .data(pdfBase64)
614 .build())
615 .build();
609616 
610617 // Create a message with document and text content blocks
611618 MessageCreateParams params = MessageCreateParams.builder()
612 .model(Model.CLAUDE_OPUS_5_5)
613 .maxTokens(1024)
614 .addUserMessageOfContentBlockParams(
615 List.of(
616 ContentBlockParam.ofDocument(documentParam),
617 ContentBlockParam.ofText(
618 TextBlockParam.builder()
619 .text("What are the key findings in this document?")
620 .build()
621 )
619 .model(Model.CLAUDE_OPUS_5_5)
620 .maxTokens(1024)
621 .addUserMessageOfContentBlockParams(
622 List.of(
623 ContentBlockParam.ofDocument(documentParam),
624 ContentBlockParam.ofText(
625 TextBlockParam.builder()
626 .text("What are the key findings in this document?")
627 .build()
628 )
629 )
622630 )
623 )
624 .build();
631 .build();
625632 
626633 Message message = client.messages().create(params);
627634 System.out.println(message.content());
from line 678
671678 # First, load and encode the PDF
672679 pdf_url = "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
673680 pdf_bytes = URI.open(pdf_url, "rb") { |f| f.read }
674 pdf_data = [pdf_bytes].pack("m0") # Base64-encode without newlines
681 pdf_data = [pdf_bytes].pack("m0") # Encode as base64 without newlines
675682 
676683 # Alternative: Load from a local file
677684 # pdf_data = [File.binread("document.pdf")].pack("m0")
from line 915
908915 
909916 // Upload the PDF file
910917 FileMetadata file = client
911 .files()
912 .upload(FileUploadParams.builder().file(Path.of("/path/to/document.pdf")).build());
918 .files()
919 .upload(FileUploadParams.builder()
920 .file(Path.of("/path/to/document.pdf"))
921 .build());
913922 
914923 // Use the uploaded file in a message
915924 MessageCreateParams params = MessageCreateParams.builder()
916 .model(Model.CLAUDE_OPUS_5_5)
917 .maxTokens(1024)
918 .addUserMessageOfContentBlockParams(
919 List.of(
920 ContentBlockParam.ofDocument(
921 DocumentBlockParam.builder().fileSource(file.id()).build()
922 ),
923 ContentBlockParam.ofText(
924 TextBlockParam.builder()
925 .text("What are the key findings in this document?")
926 .build()
927 )
925 .model(Model.CLAUDE_OPUS_5_5)
926 .maxTokens(1024)
927 .addUserMessageOfContentBlockParams(
928 List.of(
929 ContentBlockParam.ofDocument(
930 DocumentBlockParam.builder()
931 .fileSource(file.id())
932 .build()
933 ),
934 ContentBlockParam.ofText(
935 TextBlockParam.builder()
936 .text("What are the key findings in this document?")
937 .build()
938 )
939 )
928940 )
929 )
930 .build();
941 .build();
931942 
932943 Message message = client.messages().create(params);
933944 System.out.println(message.content());
from line 1270
12591270 
12601271 // Download and encode the PDF
12611272 String pdfUrl =
1262 "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf";
1263 HttpClient httpClient = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build();
1264 HttpRequest request = HttpRequest.newBuilder().uri(URI.create(pdfUrl)).GET().build();
1273 "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf";
1274 HttpClient httpClient = HttpClient.newBuilder()
1275 .followRedirects(HttpClient.Redirect.NORMAL)
1276 .build();
1277 HttpRequest request = HttpRequest.newBuilder()
1278 .uri(URI.create(pdfUrl))
1279 .GET()
1280 .build();
12651281 
12661282 HttpResponse<byte[]> response = httpClient.send(
1267 request,
1268 HttpResponse.BodyHandlers.ofByteArray()
1283 request,
1284 HttpResponse.BodyHandlers.ofByteArray()
12691285 );
12701286 String pdfBase64 = Base64.getEncoder().encodeToString(response.body());
12711287 
12721288 MessageCreateParams params = MessageCreateParams.builder()
1273 .model(Model.CLAUDE_OPUS_5_5)
1274 .maxTokens(1024)
1275 .addUserMessageOfContentBlockParams(
1276 List.of(
1277 ContentBlockParam.ofDocument(
1278 DocumentBlockParam.builder()
1279 .source(Base64PdfSource.builder().data(pdfBase64).build())
1280 .cacheControl(CacheControlEphemeral.builder().build())
1281 .build()
1282 ),
1283 ContentBlockParam.ofText(
1284 TextBlockParam.builder()
1285 .text(
1286 "Which model has the highest human preference win rates across each use-case?"
1287 )
1288 .build()
1289 )
1289 .model(Model.CLAUDE_OPUS_5_5)
1290 .maxTokens(1024)
1291 .addUserMessageOfContentBlockParams(
1292 List.of(
1293 ContentBlockParam.ofDocument(
1294 DocumentBlockParam.builder()
1295 .source(Base64PdfSource.builder()
1296 .data(pdfBase64)
1297 .build())
1298 .cacheControl(CacheControlEphemeral.builder().build())
1299 .build()
1300 ),
1301 ContentBlockParam.ofText(
1302 TextBlockParam.builder()
1303 .text(
1304 "Which model has the highest human preference win rates across each use-case?"
1305 )
1306 .build()
1307 )
1308 )
12901309 )
1291 )
1292 .build();
1310 .build();
12931311 
12941312 Message message = client.messages().create(params);
12951313 System.out.println(message);
from line 1354
13361354 # Load and encode the PDF
13371355 pdf_url = "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
13381356 pdf_bytes = URI.open(pdf_url, "rb") { |f| f.read }
1339 pdf_data = [pdf_bytes].pack("m0") # Base64-encode without newlines
1357 pdf_data = [pdf_bytes].pack("m0") # Encode as base64 without newlines
13401358 
13411359 anthropic = Anthropic::Client.new
13421360 
from line 1396
13781396 curl -sL "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf" | base64 | tr -d '\n' > pdf_base64.txt
13791397 # Create a JSON request file using the pdf_base64.txt content
13801398 jq -n --rawfile PDF_BASE64 pdf_base64.txt '{
1381 "requests": [
1382 {
1383 "custom_id": "my-first-request",
1384 "params": {
1385 "model": "claude-opus-5-5",
1386 "max_tokens": 1024,
1387 "messages": [{
1388 "role": "user",
1389 "content": [{
1390 "type": "document",
1391 "source": {
1392 "type": "base64",
1393 "media_type": "application/pdf",
1394 "data": $PDF_BASE64
1395 }
1396 },
1397 {
1398 "type": "text",
1399 "text": "Which model has the highest human preference win rates across each use-case?"
1400 }]
1401 }]
1402 }
1403 },
1404 {
1405 "custom_id": "my-second-request",
1406 "params": {
1407 "model": "claude-opus-5-5",
1408 "max_tokens": 1024,
1409 "messages": [{
1410 "role": "user",
1411 "content": [{
1412 "type": "document",
1413 "source": {
1414 "type": "base64",
1415 "media_type": "application/pdf",
1416 "data": $PDF_BASE64
1417 }
1418 },
1419 {
1420 "type": "text",
1421 "text": "Extract 5 key insights from this document."
1422 }]
1423 }]
1424 }
1425 }]
1399 "requests": [
1400 {
1401 "custom_id": "my-first-request",
1402 "params": {
1403 "model": "claude-opus-5-5",
1404 "max_tokens": 1024,
1405 "messages": [{
1406 "role": "user",
1407 "content": [{
1408 "type": "document",
1409 "source": {
1410 "type": "base64",
1411 "media_type": "application/pdf",
1412 "data": $PDF_BASE64
1413 }
1414 },
1415 {
1416 "type": "text",
1417 "text": "Which model has the highest human preference win rates across each use-case?"
1418 }]
1419 }]
1420 }
1421 },
1422 {
1423 "custom_id": "my-second-request",
1424 "params": {
1425 "model": "claude-opus-5-5",
1426 "max_tokens": 1024,
1427 "messages": [{
1428 "role": "user",
1429 "content": [{
1430 "type": "document",
1431 "source": {
1432 "type": "base64",
1433 "media_type": "application/pdf",
1434 "data": $PDF_BASE64
1435 }
1436 },
1437 {
1438 "type": "text",
1439 "text": "Extract 5 key insights from this document."
1440 }]
1441 }]
1442 }
1443 }]
14261444 }' > request.json
14271445 
14281446 # Then make the API call using the JSON file
from line 1755
17371755 
17381756 // Download and encode the PDF
17391757 String pdfUrl =
1740 "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf";
1741 HttpClient httpClient = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build();
1742 HttpRequest request = HttpRequest.newBuilder().uri(URI.create(pdfUrl)).GET().build();
1758 "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf";
1759 HttpClient httpClient = HttpClient.newBuilder()
1760 .followRedirects(HttpClient.Redirect.NORMAL)
1761 .build();
1762 HttpRequest request = HttpRequest.newBuilder()
1763 .uri(URI.create(pdfUrl))
1764 .GET()
1765 .build();
17431766 
17441767 HttpResponse<byte[]> response = httpClient.send(
1745 request,
1746 HttpResponse.BodyHandlers.ofByteArray()
1768 request,
1769 HttpResponse.BodyHandlers.ofByteArray()
17471770 );
17481771 String pdfBase64 = Base64.getEncoder().encodeToString(response.body());
17491772 
17501773 BatchCreateParams params = BatchCreateParams.builder()
1751 .addRequest(
1752 BatchCreateParams.Request.builder()
1753 .customId("my-first-request")
1754 .params(
1755 BatchCreateParams.Request.Params.builder()
1756 .model(Model.CLAUDE_OPUS_5_5)
1757 .maxTokens(1024)
1758 .addUserMessageOfContentBlockParams(
1759 List.of(
1760 ContentBlockParam.ofDocument(
1761 DocumentBlockParam.builder()
1762 .source(Base64PdfSource.builder().data(pdfBase64).build())
1763 .build()
1764 ),
1765 ContentBlockParam.ofText(
1766 TextBlockParam.builder()
1767 .text(
1768 "Which model has the highest human preference win rates across each use-case?"
1769 )
1770 .build()
1771 )
1774 .addRequest(
1775 BatchCreateParams.Request.builder()
1776 .customId("my-first-request")
1777 .params(
1778 BatchCreateParams.Request.Params.builder()
1779 .model(Model.CLAUDE_OPUS_5_5)
1780 .maxTokens(1024)
1781 .addUserMessageOfContentBlockParams(
1782 List.of(
1783 ContentBlockParam.ofDocument(
1784 DocumentBlockParam.builder()
1785 .source(Base64PdfSource.builder()
1786 .data(pdfBase64)
1787 .build())
1788 .build()
1789 ),
1790 ContentBlockParam.ofText(
1791 TextBlockParam.builder()
1792 .text(
1793 "Which model has the highest human preference win rates across each use-case?"
1794 )
1795 .build()
1796 )
1797 )
1798 )
1799 .build()
17721800 )
1773 )
1774 .build()
1775 )
1776 .build()
1777 )
1778 .addRequest(
1779 BatchCreateParams.Request.builder()
1780 .customId("my-second-request")
1781 .params(
1782 BatchCreateParams.Request.Params.builder()
1783 .model(Model.CLAUDE_OPUS_5_5)
1784 .maxTokens(1024)
1785 .addUserMessageOfContentBlockParams(
1786 List.of(
1787 ContentBlockParam.ofDocument(
1788 DocumentBlockParam.builder()
1789 .source(Base64PdfSource.builder().data(pdfBase64).build())
1790 .build()
1791 ),
1792 ContentBlockParam.ofText(
1793 TextBlockParam.builder()
1794 .text("Extract 5 key insights from this document.")
1795 .build()
1796 )
1801 .build()
1802 )
1803 .addRequest(
1804 BatchCreateParams.Request.builder()
1805 .customId("my-second-request")
1806 .params(
1807 BatchCreateParams.Request.Params.builder()
1808 .model(Model.CLAUDE_OPUS_5_5)
1809 .maxTokens(1024)
1810 .addUserMessageOfContentBlockParams(
1811 List.of(
1812 ContentBlockParam.ofDocument(
1813 DocumentBlockParam.builder()
1814 .source(Base64PdfSource.builder()
1815 .data(pdfBase64)
1816 .build())
1817 .build()
1818 ),
1819 ContentBlockParam.ofText(
1820 TextBlockParam.builder()
1821 .text("Extract 5 key insights from this document.")
1822 .build()
1823 )
1824 )
1825 )
1826 .build()
17971827 )
1798 )
1799 .build()
1800 )
1801 .build()
1802 )
1803 .build();
1828 .build()
1829 )
1830 .build();
18041831 
18051832 MessageBatch batch = client.messages().batches().create(params);
18061833 System.out.println(batch);
from line 1906
18791906 # Load and encode the PDF
18801907 pdf_url = "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
18811908 pdf_bytes = URI.open(pdf_url, "rb") { |f| f.read }
1882 pdf_data = [pdf_bytes].pack("m0") # Base64-encode without newlines
1909 pdf_data = [pdf_bytes].pack("m0") # Encode as base64 without newlines
18831910 
18841911 anthropic = Anthropic::Client.new
18851912 
18861913 

build-with-claude/preserved-thinking Changed · +3 / -3 lines

from line 1254
12541254When 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.
12551255 
12561256<Frame>
1257 ![Simple compaction: request 4 sends the full history with thinking; request 5 sends one summary message, so nothing is checked](https://platform.claude.com/docs/images/preserved-thinking-simple-compaction.svg)
1257 ![Simple compaction: request 5 sends one user message (summary plus next instruction), so no old thinking is sent or checked](https://platform.claude.com/docs/images/preserved-thinking-simple-compaction.svg)
12581258</Frame>
12591259 
12601260```json
from line 1277
12771277The rest of this section covers a summary you write yourself.
12781278 
12791279<Frame>
1280 ![Keep-tail compaction: thinking on kept turns 3 and 4 fails; with drop\_block, the API drops it and the request succeeds](https://platform.claude.com/docs/images/preserved-thinking-keep-tail-compaction.svg)
1280 ![Keep-tail compaction: a summary of turns 1 and 2, then turns 3 to 5 verbatim. Thinking on 3 and 4 fails; drop\_block succeeds](https://platform.claude.com/docs/images/preserved-thinking-keep-tail-compaction.svg)
12811281</Frame>
12821282 
12831283Fix: 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.
from line 1530
15301530 </Accordion>
15311531 
15321532 <Accordion title="Does changing effort or other thinking settings between requests invalidate earlier thinking?">
1533 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. Where the model and platform support [per-message effort](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#effort-changes), a per-message effort change keeps the prompt cache and is used as the new effort level until changed again.
1533 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. Where the model and platform support per-message effort, a [per-message effort change](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#effort-changes) keeps the prompt cache and is used as the new effort level until changed again.
15341534 </Accordion>
15351535 
15361536 <Accordion title="My tool list changes mid-session. How do I avoid invalidating the conversation?">

build-with-claude/prompt-caching Changed · +229 / -225 lines

The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.

from line 133
133133 // ...
134134 public class PromptCachingExample {
135135 
136 public static void main(String[] args) {
137 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
138 
139 MessageCreateParams params = MessageCreateParams.builder()
140 .model(Model.CLAUDE_OPUS_5_5)
141 .maxTokens(1024)
142 .cacheControl(CacheControlEphemeral.builder().build())
143 .system("You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.")
144 .addUserMessage("Analyze the major themes in 'Pride and Prejudice'.")
145 .build();
146 
147 Message message = client.messages().create(params);
148 System.out.println(message.usage());
149 }
136 public static void main(String[] args) {
137 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
138 
139 MessageCreateParams params = MessageCreateParams.builder()
140 .model(Model.CLAUDE_OPUS_5_5)
141 .maxTokens(1024)
142 .cacheControl(CacheControlEphemeral.builder().build())
143 .system("You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.")
144 .addUserMessage("Analyze the major themes in 'Pride and Prejudice'.")
145 .build();
146 
147 Message message = client.messages().create(params);
148 System.out.println(message.usage());
149 }
150150 }
151151 ```
152152 
153153 ```php PHP
154154 use Anthropic\Messages\CacheControlEphemeral;
155 use Anthropic\Messages\Model;
155156 // ...
156157 $client = new Client();
157158 
from line 161
160161 messages: [
161162 ['role' => 'user', 'content' => "Analyze the major themes in 'Pride and Prejudice'."]
162163 ],
163 model: 'claude-opus-5-5',
164 model: Model::CLAUDE_OPUS_5_5,
164165 cacheControl: CacheControlEphemeral::with(),
165 system: "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.",
166 system: 'You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.',
166167 );
167168 echo json_encode($response->usage);
168169 ```
from line 411
410411 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
411412 
412413 MessageCreateParams params = MessageCreateParams.builder()
413 .model(Model.CLAUDE_OPUS_5_5)
414 .maxTokens(1024)
415 .cacheControl(CacheControlEphemeral.builder().build())
416 .system("You are a helpful assistant that remembers our conversation.")
417 .addUserMessage("My name is Alex. I work on machine learning.")
418 .addAssistantMessage("Nice to meet you, Alex! How can I help with your ML work today?")
419 .addUserMessage("What did I say I work on?")
420 .build();
414 .model(Model.CLAUDE_OPUS_5_5)
415 .maxTokens(1024)
416 .cacheControl(CacheControlEphemeral.builder().build())
417 .system("You are a helpful assistant that remembers our conversation.")
418 .addUserMessage("My name is Alex. I work on machine learning.")
419 .addAssistantMessage("Nice to meet you, Alex! How can I help with your ML work today?")
420 .addUserMessage("What did I say I work on?")
421 .build();
421422 
422423 Message message = client.messages().create(params);
423424 System.out.println(message.usage());
from line 428
427428 
428429 ```php PHP
429430 use Anthropic\Messages\CacheControlEphemeral;
431 use Anthropic\Messages\Model;
430432 // ...
431433 $client = new Client();
432434 
from line 439
437439 ['role' => 'assistant', 'content' => 'Nice to meet you, Alex! How can I help with your ML work today?'],
438440 ['role' => 'user', 'content' => 'What did I say I work on?'],
439441 ],
440 model: 'claude-opus-5-5',
442 model: Model::CLAUDE_OPUS_5_5,
441443 cacheControl: CacheControlEphemeral::with(),
442444 system: 'You are a helpful assistant that remembers our conversation.',
443445 );
from line 603
601603 
602604These minimums apply on every platform where each model is available.
603605 
604Shorter prompts cannot be cached, even if marked with `cache_control`. Any requests to cache fewer than this number of tokens are processed without caching, and no error is returned. To verify whether a prompt was cached, check the [response usage fields](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#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).
606Shorter prompts cannot be cached, even if marked with `cache_control`. Any requests to cache fewer than this number of tokens are processed without caching, and no error is returned. To check whether a prompt was cached, look at the [response usage fields](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#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).
605607 
606608If 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.
607609 
from line 748
746748### Cache storage and sharing
747749 
748750<Warning>
749 Prompt caching uses [workspace](https://platform.claude.com/docs/en/manage-claude/workspaces)-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 Claude Models on Google Cloud (Google managed) maintain organization-level cache isolation. If you use multiple workspaces, review your caching strategy to account for this difference.
751 Prompt caching uses [workspace](https://platform.claude.com/docs/en/manage-claude/workspaces)-level isolation. Caches are isolated by 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 Claude Models on Google Cloud (Google managed) maintain organization-level cache isolation. If you use multiple workspaces, review your caching strategy to account for this difference.
750752</Warning>
751753 
752* **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 Claude Models on Google Cloud (Google managed) use organization-level isolation only.
754* **Organization and workspace isolation:** Caches are isolated between organizations. Different organizations never share caches, even if they use identical prompts. Caches are also isolated by workspace within an organization on the Claude API, Claude Platform on AWS, and Microsoft Foundry; Bedrock and Claude Models on Google Cloud (Google managed) use organization-level isolation only.
753755 
754756* **Exact matching:** Cache hits require 100 percent identical prompt segments, including all text and images up to and including the block marked with cache control.
755757 
from line 1031
10291031 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
10301032 
10311033 Message prewarm = client.messages().create(MessageCreateParams.builder()
1032 .model(Model.CLAUDE_OPUS_5_5)
1033 .maxTokens(0)
1034 .systemOfTextBlockParams(List.of(TextBlockParam.builder()
1035 .text("You are an expert software engineer with deep knowledge of distributed systems...")
1036 .cacheControl(CacheControlEphemeral.builder().build())
1037 .build()))
1038 .addUserMessage("warmup")
1039 .build());
1034 .model(Model.CLAUDE_OPUS_5_5)
1035 .maxTokens(0)
1036 .systemOfTextBlockParams(List.of(TextBlockParam.builder()
1037 .text("You are an expert software engineer with deep knowledge of distributed systems...")
1038 .cacheControl(CacheControlEphemeral.builder().build())
1039 .build()))
1040 .addUserMessage("warmup")
1041 .build());
10401042 
10411043 IO.println(prewarm.stopReason()); // Optional[max_tokens]
10421044 IO.println(prewarm.content()); // []
from line 1394
13921394 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
13931395 
13941396 List<TextBlockParam> systemPrompt = List.of(TextBlockParam.builder()
1395 .text("You are an expert software engineer with deep knowledge of distributed systems...")
1396 .cacheControl(CacheControlEphemeral.builder().build())
1397 .build());
1397 .text("You are an expert software engineer with deep knowledge of distributed systems...")
1398 .cacheControl(CacheControlEphemeral.builder().build())
1399 .build());
13981400 
13991401 // Call this at application startup or on a scheduled interval.
14001402 void prewarmCache() {
14011403 client.messages().create(MessageCreateParams.builder()
1402 .model(Model.CLAUDE_OPUS_5_5)
1403 .maxTokens(0)
1404 .systemOfTextBlockParams(systemPrompt)
1405 .addUserMessage("warmup")
1406 .build());
1404 .model(Model.CLAUDE_OPUS_5_5)
1405 .maxTokens(0)
1406 .systemOfTextBlockParams(systemPrompt)
1407 .addUserMessage("warmup")
1408 .build());
14071409 }
14081410 
14091411 // The real user request; benefits from a warm cache.
14101412 Message respond(String userMessage) {
14111413 return client.messages().create(MessageCreateParams.builder()
1412 .model(Model.CLAUDE_OPUS_5_5)
1413 .maxTokens(1024)
1414 .systemOfTextBlockParams(systemPrompt)
1415 .addUserMessage(userMessage)
1416 .build());
1414 .model(Model.CLAUDE_OPUS_5_5)
1415 .maxTokens(1024)
1416 .systemOfTextBlockParams(systemPrompt)
1417 .addUserMessage(userMessage)
1418 .build());
14171419 }
14181420 
14191421 void main() {
from line 1425
14231425 // Later, when the user submits a message, the system-prompt prefix is already cached.
14241426 Message response = respond("How do I implement a binary search tree?");
14251427 response.content().stream()
1426 .flatMap(block -> block.text().stream())
1427 .forEach(textBlock -> IO.println(textBlock.text()));
1428 .flatMap(block -> block.text().stream())
1429 .forEach(textBlock -> IO.println(textBlock.text()));
14281430 }
14291431 ```
14301432 
from line 1705
17031705 // ...
17041706 public class LegalDocumentAnalysisExample {
17051707 
1706 public static void main(String[] args) {
1707 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
1708 
1709 MessageCreateParams params = MessageCreateParams.builder()
1710 .model(Model.CLAUDE_OPUS_5_5)
1711 .maxTokens(1024)
1712 .systemOfTextBlockParams(
1713 List.of(
1714 TextBlockParam.builder()
1715 .text("You are an AI assistant tasked with analyzing legal documents.")
1716 .build(),
1717 TextBlockParam.builder()
1718 .text(
1719 "Here is the full text of a complex legal agreement: [Insert full text of a 50-page legal agreement here]"
1708 public static void main(String[] args) {
1709 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
1710 
1711 MessageCreateParams params = MessageCreateParams.builder()
1712 .model(Model.CLAUDE_OPUS_5_5)
1713 .maxTokens(1024)
1714 .systemOfTextBlockParams(
1715 List.of(
1716 TextBlockParam.builder()
1717 .text("You are an AI assistant tasked with analyzing legal documents.")
1718 .build(),
1719 TextBlockParam.builder()
1720 .text(
1721 "Here is the full text of a complex legal agreement: [Insert full text of a 50-page legal agreement here]"
1722 )
1723 .cacheControl(CacheControlEphemeral.builder().build())
1724 .build()
1725 )
17201726 )
1721 .cacheControl(CacheControlEphemeral.builder().build())
1722 .build()
1723 )
1724 )
1725 .addUserMessage("What are the key terms and conditions in this agreement?")
1726 .build();
1727 
1728 Message message = client.messages().create(params);
1729 System.out.println(message.usage());
1730 }
1727 .addUserMessage("What are the key terms and conditions in this agreement?")
1728 .build();
1729 
1730 Message message = client.messages().create(params);
1731 System.out.println(message.usage());
1732 }
17311733 }
17321734 ```
17331735 
from line 1744
17421744 'content' => 'What are the key terms and conditions in this agreement?'
17431745 ]
17441746 ],
1745 model: 'claude-opus-5-5',
1747 model: Model::CLAUDE_OPUS_5_5,
17461748 system: [
17471749 [
17481750 'type' => 'text',
from line 2098
20962098 // ...
20972099 public class ConversationWithCacheControlExample {
20982100 
2099 public static void main(String[] args) {
2100 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
2101 
2102 // Create ephemeral system prompt
2103 TextBlockParam systemPrompt = TextBlockParam.builder()
2104 .text("...long system prompt")
2105 .cacheControl(CacheControlEphemeral.builder().build())
2106 .build();
2107 
2108 // Create message params
2109 MessageCreateParams params = MessageCreateParams.builder()
2110 .model(Model.CLAUDE_OPUS_5_5)
2111 .maxTokens(1024)
2112 .systemOfTextBlockParams(List.of(systemPrompt))
2113 // First user message (without cache control)
2114 .addUserMessage("Hello, can you tell me more about the solar system?")
2115 // Assistant response
2116 .addAssistantMessage(
2117 "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 would like to know more about?"
2118 )
2119 // Second user message (with cache control)
2120 .addUserMessageOfContentBlockParams(
2121 List.of(
2122 ContentBlockParam.ofText(TextBlockParam.builder().text("Good to know.").build()),
2123 ContentBlockParam.ofText(
2124 TextBlockParam.builder()
2125 .text("Tell me more about Mars.")
2126 .cacheControl(CacheControlEphemeral.builder().build())
2127 .build()
2128 )
2129 )
2130 )
2131 .build();
2132 
2133 Message message = client.messages().create(params);
2134 System.out.println(message.usage());
2135 }
2101 public static void main(String[] args) {
2102 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
2103 
2104 // Create ephemeral system prompt
2105 TextBlockParam systemPrompt = TextBlockParam.builder()
2106 .text("...long system prompt")
2107 .cacheControl(CacheControlEphemeral.builder().build())
2108 .build();
2109 
2110 // Create message params
2111 MessageCreateParams params = MessageCreateParams.builder()
2112 .model(Model.CLAUDE_OPUS_5_5)
2113 .maxTokens(1024)
2114 .systemOfTextBlockParams(List.of(systemPrompt))
2115 // First user message (without cache control)
2116 .addUserMessage("Hello, can you tell me more about the solar system?")
2117 // Assistant response
2118 .addAssistantMessage(
2119 "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 would like to know more about?"
2120 )
2121 // Second user message (with cache control)
2122 .addUserMessageOfContentBlockParams(
2123 List.of(
2124 ContentBlockParam.ofText(TextBlockParam.builder()
2125 .text("Good to know.")
2126 .build()),
2127 ContentBlockParam.ofText(
2128 TextBlockParam.builder()
2129 .text("Tell me more about Mars.")
2130 .cacheControl(CacheControlEphemeral.builder().build())
2131 .build()
2132 )
2133 )
2134 )
2135 .build();
2136 
2137 Message message = client.messages().create(params);
2138 System.out.println(message.usage());
2139 }
21362140 }
21372141 ```
21382142 
from line 2157
21532157 ],
21542158 [
21552159 'role' => 'assistant',
2156 '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 would like to know more about?"
2160 '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 would like to know more about?'
21572161 ],
21582162 [
21592163 'role' => 'user',
from line 2171
21672171 ]
21682172 ]
21692173 ],
2170 model: 'claude-opus-5-5',
2174 model: Model::CLAUDE_OPUS_5_5,
21712175 system: [
21722176 [
21732177 'type' => 'text',
from line 2805
28012805 // ...
28022806 public class MultipleCacheBreakpointsExample {
28032807 
2804 public static void main(String[] args) {
2805 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
2806 
2807 // Search tool schema
2808 InputSchema searchSchema = InputSchema.builder()
2809 .properties(
2810 JsonValue.from(
2811 Map.of("query", Map.of("type", "string", "description", "Search query"))
2812 )
2813 )
2814 .putAdditionalProperty("required", JsonValue.from(List.of("query")))
2815 .build();
2816 
2817 // Get document tool schema
2818 InputSchema getDocSchema = InputSchema.builder()
2819 .properties(
2820 JsonValue.from(
2821 Map.of("doc_id", Map.of("type", "string", "description", "Document ID"))
2822 )
2823 )
2824 .putAdditionalProperty("required", JsonValue.from(List.of("doc_id")))
2825 .build();
2826 
2827 MessageCreateParams params = MessageCreateParams.builder()
2828 .model(Model.CLAUDE_OPUS_5_5)
2829 .maxTokens(1024)
2830 // Tools with cache control on the last one
2831 .addTool(
2832 Tool.builder()
2833 .name("search_documents")
2834 .description("Search through the knowledge base")
2835 .inputSchema(searchSchema)
2836 .build()
2837 )
2838 .addTool(
2839 Tool.builder()
2840 .name("get_document")
2841 .description("Retrieve a specific document by ID")
2842 .inputSchema(getDocSchema)
2843 .cacheControl(CacheControlEphemeral.builder().build())
2844 .build()
2845 )
2846 // System prompts with cache control on instructions and context separately
2847 .systemOfTextBlockParams(
2848 List.of(
2849 TextBlockParam.builder()
2850 .text(
2851 "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"
2808 public static void main(String[] args) {
2809 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
2810 
2811 // Search tool schema
2812 InputSchema searchSchema = InputSchema.builder()
2813 .properties(
2814 JsonValue.from(
2815 Map.of("query", Map.of("type", "string", "description", "Search query"))
2816 )
28522817 )
2853 .cacheControl(CacheControlEphemeral.builder().build())
2854 .build(),
2855 TextBlockParam.builder()
2856 .text(
2857 "# 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...]"
2818 .putAdditionalProperty("required", JsonValue.from(List.of("query")))
2819 .build();
2820 
2821 // Get document tool schema
2822 InputSchema getDocSchema = InputSchema.builder()
2823 .properties(
2824 JsonValue.from(
2825 Map.of("doc_id", Map.of("type", "string", "description", "Document ID"))
2826 )
28582827 )
2859 .cacheControl(CacheControlEphemeral.builder().build())
2860 .build()
2861 )
2862 )
2863 // Conversation history
2864 .addUserMessage("Can you search for information about Mars rovers?")
2865 .addAssistantMessageOfContentBlockParams(
2866 List.of(
2867 ContentBlockParam.ofToolUse(
2868 ToolUseBlockParam.builder()
2869 .id("tool_1")
2870 .name("search_documents")
2871 .input(JsonValue.from(Map.of("query", "Mars rovers")))
2872 .build()
2873 )
2874 )
2875 )
2876 .addUserMessageOfContentBlockParams(
2877 List.of(
2878 ContentBlockParam.ofToolResult(
2879 ToolResultBlockParam.builder()
2880 .toolUseId("tool_1")
2881 .content(
2882 "Found 3 relevant documents: Document 3 (Mars Exploration), Document 7 (Rover Technology), Document 9 (Mission History)"
2883 )
2884 .build()
2885 )
2886 )
2887 )
2888 .addAssistantMessageOfContentBlockParams(
2889 List.of(
2890 ContentBlockParam.ofText(
2891 TextBlockParam.builder()
2892 .text(
2893 "I found 3 relevant documents about Mars rovers. Let me get more details from the Mars Exploration document."
2894 )
2895 .build()
2896 )
2897 )
2898 )
2899 .addUserMessageOfContentBlockParams(
2900 List.of(
2901 ContentBlockParam.ofText(
2902 TextBlockParam.builder()
2903 .text("Yes, please tell me about the Perseverance rover specifically.")
2904 .cacheControl(CacheControlEphemeral.builder().build())
2905 .build()
2906 )
2907 )
2908 )
2909 .build();
2910 
2911 Message message = client.messages().create(params);
2912 System.out.println(message.usage());
2913 }
2828 .putAdditionalProperty("required", JsonValue.from(List.of("doc_id")))
2829 .build();
2830 
2831 MessageCreateParams params = MessageCreateParams.builder()
2832 .model(Model.CLAUDE_OPUS_5_5)
2833 .maxTokens(1024)
2834 // Tools with cache control on the last one
2835 .addTool(
2836 Tool.builder()
2837 .name("search_documents")
2838 .description("Search through the knowledge base")
2839 .inputSchema(searchSchema)
2840 .build()
2841 )
2842 .addTool(
2843 Tool.builder()
2844 .name("get_document")
2845 .description("Retrieve a specific document by ID")
2846 .inputSchema(getDocSchema)
2847 .cacheControl(CacheControlEphemeral.builder().build())
2848 .build()
2849 )
2850 // System prompts with cache control on instructions and context separately
2851 .systemOfTextBlockParams(
2852 List.of(
2853 TextBlockParam.builder()
2854 .text(
2855 "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"
2856 )
2857 .cacheControl(CacheControlEphemeral.builder().build())
2858 .build(),
2859 TextBlockParam.builder()
2860 .text(
2861 "# 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...]"
2862 )
2863 .cacheControl(CacheControlEphemeral.builder().build())
2864 .build()
2865 )
2866 )
2867 // Conversation history
2868 .addUserMessage("Can you search for information about Mars rovers?")
2869 .addAssistantMessageOfContentBlockParams(
2870 List.of(
2871 ContentBlockParam.ofToolUse(
2872 ToolUseBlockParam.builder()
2873 .id("tool_1")
2874 .name("search_documents")
2875 .input(JsonValue.from(Map.of("query", "Mars rovers")))
2876 .build()
2877 )
2878 )
2879 )
2880 .addUserMessageOfContentBlockParams(
2881 List.of(
2882 ContentBlockParam.ofToolResult(
2883 ToolResultBlockParam.builder()
2884 .toolUseId("tool_1")
2885 .content(
2886 "Found 3 relevant documents: Document 3 (Mars Exploration), Document 7 (Rover Technology), Document 9 (Mission History)"
2887 )
2888 .build()
2889 )
2890 )
2891 )
2892 .addAssistantMessageOfContentBlockParams(
2893 List.of(
2894 ContentBlockParam.ofText(
2895 TextBlockParam.builder()
2896 .text(
2897 "I found 3 relevant documents about Mars rovers. Let me get more details from the Mars Exploration document."
2898 )
2899 .build()
2900 )
2901 )
2902 )
2903 .addUserMessageOfContentBlockParams(
2904 List.of(
2905 ContentBlockParam.ofText(
2906 TextBlockParam.builder()
2907 .text("Yes, please tell me about the Perseverance rover specifically.")
2908 .cacheControl(CacheControlEphemeral.builder().build())
2909 .build()
2910 )
2911 )
2912 )
2913 .build();
2914 
2915 Message message = client.messages().create(params);
2916 System.out.println(message.usage());
2917 }
29142918 }
29152919 ```
29162920 
from line 2969
29652969 ]
29662970 ]
29672971 ],
2968 model: 'claude-opus-5-5',
2972 model: Model::CLAUDE_OPUS_5_5,
29692973 system: [
29702974 [
29712975 'type' => 'text',
from line 3273
32693273 
32703274 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.
32713275 
3272 2. On the Claude API, Claude Platform on AWS, and Microsoft Foundry, caches are isolated per workspace within an organization. On Bedrock and Claude Models on Google Cloud (Google managed), caches are isolated per organization. In every case, caches are never shared across organizations, even for identical prompts. See [Cache storage and sharing](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#cache-storage-and-sharing) for details.
3276 2. On the Claude API, Claude Platform on AWS, and Microsoft Foundry, caches are isolated by workspace within an organization. On Bedrock and Claude Models on Google Cloud (Google managed), caches are isolated by organization. In every case, caches are never shared across organizations, even for identical prompts. See [Cache storage and sharing](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#cache-storage-and-sharing) for details.
32733277 
32743278 3. The caching mechanism is designed to maintain the integrity and privacy of each unique conversation or context.
32753279 
32763280 

build-with-claude/prompt-engineering/claude-prompting-best-practices Changed · +4 / -2 lines

from line 213
213213 messages: [
214214 ['role' => 'user', 'content' => 'How do I sort a list of dictionaries by key?']
215215 ],
216 model: 'claude-opus-5-5',
216 model: Model::CLAUDE_OPUS_5_5,
217217 system: 'You are a helpful coding assistant specializing in Python.',
218218 );
219219 
from line 716
716716 client.messages().create(MessageCreateParams.builder()
717717 .model(Model.CLAUDE_SONNET_4_5_20250929)
718718 .maxTokens(16000L)
719 .thinking(ThinkingConfigEnabled.builder().budgetTokens(10000L).build())
719 .thinking(ThinkingConfigEnabled.builder()
720 .budgetTokens(10000L)
721 .build())
720722 .addUserMessage("...")
721723 .build());
722724 

build-with-claude/refusals-and-fallback Changed · +23 / -18 lines

from line 121
121121 $client = new Client();
122122 
123123 $response = $client->beta->messages->create(
124 model: 'claude-fable-5',
124 model: Model::CLAUDE_FABLE_5,
125125 maxTokens: 1024,
126126 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
127127 fallbacks: 'default',
from line 184
184184| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------ |
185185| `"cyber"` | The request could enable cyber harm, such as malware or exploit development. Benign cybersecurity work can also trigger this category. | No |
186186| `"bio"` | The request could enable biological harm, such as dangerous lab methods. Beneficial life sciences work can also trigger this category. | Yes |
187| `"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 |
187| `"frontier_llm"` | The request could help with 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 |
188188| `"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](https://platform.claude.com/docs/en/build-with-claude/thinking). See [Keep reasoning in thinking blocks](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks). | Yes |
189189| `"general_harms"` | The request falls under a usage-policy area outside the four named categories. Benign work can also trigger this category. | No |
190190 
from line 219
219219 
220220There 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.
221221 
222| Your situation | Use | Why |
223| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
224| Claude API or Claude Models on Google Cloud (Anthropic managed), simplest setup | [Server-side fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#server-side-fallback) | One request, one response. The API handles the retry. |
225| Any platform, using an Anthropic SDK | [The SDK middleware](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#client-side-fallback) | Configure once on the client. Retries happen automatically. |
226| Raw HTTP or custom retry logic | [A manual retry](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#manual-retry) with [fallback credit](https://platform.claude.com/docs/en/build-with-claude/fallback-credit) | Full control. Fallback credit keeps the cost down. |
222| Your situation | Use | Why |
223| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
224| Claude API or Claude Models on Google Cloud (Anthropic managed), simplest setup | [Server-side fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#server-side-fallback) | One request, one response. The API handles the retry. |
225| Any platform, using an Anthropic SDK | [Client-side fallback with the SDK middleware](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#client-side-fallback) | Configure once on the client. Retries occur automatically. |
226| Raw HTTP or custom retry logic | [A manual retry](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#manual-retry) with [fallback credit](https://platform.claude.com/docs/en/build-with-claude/fallback-credit) | Full control. Fallback credit keeps the cost down. |
227227 
228228Server-side fallback and the SDK middleware apply fallback credit for you. You only need the [Fallback credit](https://platform.claude.com/docs/en/build-with-claude/fallback-credit) page when you build the retry yourself. Claude Haiku 5.5 has neither server-side fallback nor fallback credit, so use the SDK middleware or a manual retry.
229229 
from line 418
418418 IO.println("""
419419 {"stop_reason":"%s","model":"%s","served_by_fallback":%b}\
420420 """.formatted(
421 response.stopReason().map(BetaStopReason::asString).orElse("null"),
422 response.model().asString(),
423 servedByFallback));
421 response.stopReason().map(BetaStopReason::asString).orElse("null"),
422 response.model().asString(),
423 servedByFallback));
424424 ```
425425 
426426 ```php PHP
from line 429
429429 $response = $client->beta->messages->create(
430430 maxTokens: 1024,
431431 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
432 model: 'claude-fable-5',
432 model: Model::CLAUDE_FABLE_5,
433433 fallbacks: 'default',
434434 betas: ['server-side-fallback-2026-07-01'],
435435 );
from line 596
596596 $client = new Client();
597597 
598598 $response = $client->beta->messages->create(
599 model: 'claude-fable-5',
599 model: Model::CLAUDE_FABLE_5,
600600 maxTokens: 1024,
601601 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
602602 fallbacks: [['model' => 'claude-opus-4-8']],
from line 726
726726 
727727### Non-streaming responses
728728 
729On 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 the beginning. 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`.
729On a non-streaming request, a mid-output decline behaves differently: the response omits the declined model's partial output, and the fallback model starts a new answer. 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`.
730730 
731731<Note>
732732 **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.
from line 916
916916 )),
917917 )
918918 
919 // One state per conversation: requests sharing it stay pinned to the
919 // One state for each conversation: requests sharing it stay pinned to the
920920 // model that accepted, so a follow-up never re-asks a model that refused.
921921 state := &betafallback.BetaFallbackState{}
922922 conversation := betafallback.WithBetaFallbackState(state)
from line 997
997997 BetaMessageAccumulator accumulator = BetaMessageAccumulator.create();
998998 try (StreamResponse<BetaRawMessageStreamEvent> streamResponse = client.beta()
999999 .messages()
1000 .createStreaming(params, RequestOptions.builder().fallbackState(state).build())) {
1000 .createStreaming(params, RequestOptions.builder()
1001 .fallbackState(state)
1002 .build())) {
10011003 streamResponse.stream()
10021004 .peek(accumulator::accumulate)
10031005 .forEach(event -> event.contentBlockDelta()
from line 1011
10091011 // Non-streaming: reusing the same state keeps the conversation pinned.
10101012 BetaMessage message = client.beta()
10111013 .messages()
1012 .create(params, RequestOptions.builder().fallbackState(state).build());
1014 .create(params, RequestOptions.builder()
1015 .fallbackState(state)
1016 .build());
10131017 IO.println("served by: " + message.model().asString());
10141018 }
10151019 ```
from line 1025
10211025 use Anthropic\Lib\Middleware\BetaFallbackState;
10221026 use Anthropic\Lib\Middleware\RefusalFallbackMiddleware;
10231027 use Anthropic\Lib\Streaming\MessageAccumulator;
1028 use Anthropic\Messages\Model;
10241029 
10251030 // Configure the fallback chain once. On a refusal, the middleware retries the
10261031 // request down the chain and sends the fallback-credit beta header for you.
from line 1042
10371042 // Streaming: on a refusal the middleware splices the fallback model's events
10381043 // onto the still-open stream. The accumulator's model is the serving model.
10391044 $stream = $client->beta->messages->createStream(
1040 model: 'claude-fable-5',
1045 model: Model::CLAUDE_FABLE_5,
10411046 maxTokens: 1024,
10421047 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
10431048 requestOptions: ['fallbackState' => $state],
from line 1060
10551060 // Non-streaming: same middleware. Reusing the state keeps the conversation
10561061 // pinned to the model that accepted.
10571062 $message = $client->beta->messages->create(
1058 model: 'claude-fable-5',
1063 model: Model::CLAUDE_FABLE_5,
10591064 maxTokens: 1024,
10601065 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
10611066 requestOptions: ['fallbackState' => $state],

build-with-claude/search-results Changed · +32 / -20 lines

from line 518
518518 input.get("query").asStringOrThrow()
519519 );
520520 
521 // Append Claude's entire turn to the running conversation, then the tool result.
521 // Append Claude's turn, then the tool result, to the running conversation.
522522 // Rebuilding only the tool_use block would drop any other content blocks Claude
523 // returned (e.g. leading text when the tool call is not forced) — append the
524 // full turn, as the other language tabs do.
523 // returned, for example leading text when the tool call is not forced.
525524 messages.add(response.toParam());
526525 messages.add(MessageParam.ofUserOfContentBlockParams(List.of(
527526 ContentBlockParam.ofToolResult(
from line 554
555554 .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.")
556555 .build()
557556 ))
558 .citations(CitationsConfigParam.builder().enabled(true).build())
557 .citations(CitationsConfigParam.builder()
558 .enabled(true)
559 .build())
559560 .build()
560561 ),
561562 ToolResultBlockParam.Content.Block.ofSearchResult(
from line 568
567568 .text("If you encounter timeout errors, first check the configuration settings. Common causes include network latency and incorrect timeout values.")
568569 .build()
569570 ))
570 .citations(CitationsConfigParam.builder().enabled(true).build())
571 .citations(CitationsConfigParam.builder()
572 .enabled(true)
573 .build())
571574 .build()
572575 )
573576 );
from line 595
592595 ]
593596 ];
594597 
595 function searchKnowledgeBase($query) {
598 function searchKnowledgeBase($query)
599 {
596600 return [
597601 [
598602 'type' => 'search_result',
from line 1050
10461050 .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.")
10471051 .build()
10481052 ))
1049 .citations(CitationsConfigParam.builder().enabled(true).build())
1053 .citations(CitationsConfigParam.builder()
1054 .enabled(true)
1055 .build())
10501056 .build()
10511057 ),
10521058 ContentBlockParam.ofSearchResult(
from line 1064
10581064 .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.")
10591065 .build()
10601066 ))
1061 .citations(CitationsConfigParam.builder().enabled(true).build())
1067 .citations(CitationsConfigParam.builder()
1068 .enabled(true)
1069 .build())
10621070 .build()
10631071 ),
10641072 ContentBlockParam.ofText(
from line 1122
11141122 ]
11151123 ]
11161124 ],
1117 model: 'claude-opus-5-5',
1125 model: Model::CLAUDE_OPUS_5_5,
11181126 );
11191127 
11201128 echo json_encode($message, JSON_PRETTY_PRINT);
from line 1451
14431451 }
14441452 
14451453 # Replay a conversation that provides search results both ways: the first
1446 # user message carries a pre-fetched result, the tool result returns another
1454 # user message carries a pre-fetched result, and the tool result returns another
14471455 response = client.messages.create(
14481456 model="claude-opus-5-5",
14491457 max_tokens=1024,
from line 1537
15291537 };
15301538 
15311539 // Replay a conversation that provides search results both ways: the first
1532 // user message carries a pre-fetched result, the tool result returns another
1540 // user message carries a pre-fetched result, and the tool result returns another
15331541 const response = await client.messages.create({
15341542 model: "claude-opus-5-5",
15351543 max_tokens: 1024,
from line 1609
16011609 AnthropicClient client = new();
16021610 
16031611 // Replay a conversation that provides search results both ways: the first
1604 // user message carries a pre-fetched result, the tool result returns another
1612 // user message carries a pre-fetched result, and the tool result returns another
16051613 var response = await client.Messages.Create(new()
16061614 {
16071615 Model = Model.ClaudeOpus5_5,
from line 1705
16971705 }
16981706 
16991707 // Replay a conversation that provides search results both ways: the first
1700 // user message carries a pre-fetched result, the tool result returns another
1708 // user message carries a pre-fetched result, and the tool result returns another
17011709 response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
17021710 Model: anthropic.ModelClaudeOpus5_5,
17031711 MaxTokens: 1024,
from line 1780
17721780 .build();
17731781 
17741782 // Replay a conversation that provides search results both ways: the first
1775 // user message carries a pre-fetched result, the tool result returns another
1783 // user message carries a pre-fetched result, and the tool result returns another
17761784 MessageCreateParams params = MessageCreateParams.builder()
17771785 .model(Model.CLAUDE_OPUS_5_5)
17781786 .maxTokens(1024L)
from line 1792
17841792 .content(List.of(TextBlockParam.builder()
17851793 .text("Acme Dashboard is a monitoring tool for distributed systems. It supports real-time alerting and custom metric dashboards.")
17861794 .build()))
1787 .citations(CitationsConfigParam.builder().enabled(true).build())
1795 .citations(CitationsConfigParam.builder()
1796 .enabled(true)
1797 .build())
17881798 .build()),
17891799 ContentBlockParam.ofText(TextBlockParam.builder()
17901800 .text("What does Acme Dashboard do, and what plans is it available on?")
from line 1820
18101820 .content(List.of(TextBlockParam.builder()
18111821 .text("Acme Dashboard is available on the Starter plan at $10 per user per month and the Enterprise plan with custom pricing.")
18121822 .build()))
1813 .citations(CitationsConfigParam.builder().enabled(true).build())
1823 .citations(CitationsConfigParam.builder()
1824 .enabled(true)
1825 .build())
18141826 .build())
18151827 ))
18161828 .build())
from line 1850
18381850 ];
18391851 
18401852 // Replay a conversation that provides search results both ways: the first
1841 // user message carries a pre-fetched result, the tool result returns another
1853 // user message carries a pre-fetched result, and the tool result returns another
18421854 $response = $client->messages->create(
18431855 maxTokens: 1024,
18441856 tools: [$knowledgeBaseTool],
from line 1912
19001912 ]
19011913 ]
19021914 ],
1903 model: 'claude-opus-5-5',
1915 model: Model::CLAUDE_OPUS_5_5,
19041916 );
19051917 
19061918 echo json_encode($response, JSON_PRETTY_PRINT);
from line 1934
19221934 }
19231935 
19241936 # Replay a conversation that provides search results both ways: the first
1925 # user message carries a pre-fetched result, the tool result returns another
1937 # user message carries a pre-fetched result, and the tool result returns another
19261938 response = client.messages.create(
19271939 model: Anthropic::Model::CLAUDE_OPUS_5_5,
19281940 max_tokens: 1024,
from line 2128
21162128 
21172129## Limitations
21182130 
2119* Search result content blocks are available on Claude API, Amazon Bedrock, and Claude Models on Google Cloud (Google managed).
2131* Search result content blocks are available on the Claude API, Amazon Bedrock, and Claude Models on Google Cloud (Google managed).
21202132* Only text content is supported within search results (no images or other media).
21212133* `search_result` blocks can only appear in user messages (including inside tool results). Assistant messages with search results are rejected.
21222134* When the [web search tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool) is enabled in the same request, citations must be enabled on all `search_result` blocks.

build-with-claude/skills-guide Changed · +19 / -18 lines

from line 257
257257 messages: [
258258 ['role' => 'user', 'content' => 'Create a presentation about renewable energy']
259259 ],
260 model: 'claude-opus-5-5',
260 model: Model::CLAUDE_OPUS_5_5,
261261 container: [
262262 'skills' => [
263263 [
from line 616
616616 );
617617 
618618 // Step 2: Extract file IDs from the response
619 function extractFileIds($response) {
619 function extractFileIds($response)
620 {
620621 $fileIds = [];
621622 foreach ($response->content as $item) {
622623 if ($item->type === 'bash_code_execution_tool_result') {
from line 2071
20702071 
20712072 var skill = await client.Skills.Create(parameters);
20722073 
2073 // Option 2: Using individual files (path-qualified filenames preserve the Skill's directory layout)
2074 // Option 2: Using individual files (path-qualified file names preserve the Skill's directory layout)
20742075 var parameters2 = new SkillCreateParams
20752076 {
20762077 Files =
from line 2161
21602161 
21612162 Skill skill = client.skills().create(params);
21622163 
2163 // Option 2: Using individual files (path-qualified filenames preserve the Skill's directory layout)
2164 // Option 2: Using individual files (path-qualified file names preserve the Skill's directory layout)
21642165 SkillCreateParams params2 = SkillCreateParams.builder()
21652166 .addFile(MultipartField.<InputStream>builder()
21662167 .value(Files.newInputStream(Path.of("financial_skill/SKILL.md")))
from line 2507
25062507 
25072508### Deleting a Skill
25082509 
2509Deleting a Skill also removes all of its versions.
2510Deleting a Skill also deletes all of its versions.
25102511 
25112512<CodeGroup>
25122513 ```bash cURL
from line 3540
35393540 
35403541### Request limits
35413542 
3542* **Maximum Skills per request:** 20
3543* **Maximum Skills for each request:** 20
35433544 
35443545* **Maximum Skill upload size:** 30 MB (all files combined, uncompressed)
35453546 
from line 3886
38853886 "tools": [{"type": "code_execution_20250825", "name": "code_execution"}]
38863887 }'
38873888 
3888 # Changing the Skills list ([xlsx] vs [xlsx, pptx]) changes the prefix: a cache miss, while an identical list is a cache hit
3889 # Changing the Skills list ([xlsx] versus [xlsx, pptx]) changes the prefix: a cache miss, whereas an identical list is a cache hit
38893890 curl https://api.anthropic.com/v1/messages \
38903891 -H "x-api-key: $ANTHROPIC_API_KEY" \
38913892 -H "anthropic-version: 2023-06-01" \
from line 3923
39223923 name: code_execution
39233924 YAML
39243925 
3925 # Changing the Skills list ([xlsx] vs [xlsx, pptx]) changes the prefix: a cache miss, while an identical list is a cache hit
3926 # Changing the Skills list ([xlsx] versus [xlsx, pptx]) changes the prefix: a cache miss, whereas an identical list is a cache hit
39263927 ant messages create <<'YAML'
39273928 model: claude-opus-5-5
39283929 max_tokens: 4096
from line 3958
39573958 tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
39583959 )
39593960 
3960 # Changing the Skills list ([xlsx] vs [xlsx, pptx]) changes the prefix: a cache miss, while an identical list is a cache hit
3961 # Changing the Skills list ([xlsx] versus [xlsx, pptx]) changes the prefix: a cache miss, whereas an identical list is a cache hit
39613962 response2 = client.messages.create(
39623963 model="claude-opus-5-5",
39633964 max_tokens=4096,
from line 3991
39903991 tools: [{ type: "code_execution_20250825", name: "code_execution" }]
39913992 });
39923993 
3993 // Changing the Skills list ([xlsx] vs [xlsx, pptx]) changes the prefix: a cache miss, while an identical list is a cache hit
3994 // Changing the Skills list ([xlsx] versus [xlsx, pptx]) changes the prefix: a cache miss, whereas an identical list is a cache hit
39943995 const response2 = await client.messages.create({
39953996 model: "claude-opus-5-5",
39963997 max_tokens: 4096,
from line 4033
40324033 var response1 = await client.Messages.Create(parameters1);
40334034 Console.WriteLine(response1);
40344035 
4035 // Different Skill set ([xlsx] vs [xlsx, pptx]) = a different prefix: a cache miss (an identical set is a cache hit)
4036 // Changing the Skills list ([xlsx] versus [xlsx, pptx]) changes the prefix: a cache miss, whereas an identical list is a cache hit
40364037 var parameters2 = new MessageCreateParams
40374038 {
40384039 Model = Model.ClaudeOpus5_5,
from line 4094
40934094 }
40944095 fmt.Println(response1)
40954096 
4096 // Changing the Skills list ([xlsx] vs [xlsx, pptx]) changes the prefix: a cache miss, while an identical list is a cache hit
4097 // Changing the Skills list ([xlsx] versus [xlsx, pptx]) changes the prefix: a cache miss, whereas an identical list is a cache hit
40974098 response2, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
40984099 Model: anthropic.ModelClaudeOpus5_5,
40994100 MaxTokens: 4096,
from line 4155
41544155 Message response1 = client.messages().create(params1);
41554156 System.out.println(response1);
41564157 
4157 // Changing the Skills list ([xlsx] vs [xlsx, pptx]) changes the prefix: a cache miss, while an identical list is a cache hit
4158 // Changing the Skills list ([xlsx] versus [xlsx, pptx]) changes the prefix: a cache miss, whereas an identical list is a cache hit
41584159 MessageCreateParams params2 = MessageCreateParams.builder()
41594160 .model(Model.CLAUDE_OPUS_5_5)
41604161 .maxTokens(4096L)
from line 4191
41904191 messages: [
41914192 ['role' => 'user', 'content' => 'Analyze sales data']
41924193 ],
4193 model: 'claude-opus-5-5',
4194 model: Model::CLAUDE_OPUS_5_5,
41944195 container: [
41954196 'skills' => [
41964197 ['type' => 'anthropic', 'skillID' => 'xlsx', 'version' => 'latest']
from line 4203
42024203 );
42034204 echo $response1;
42044205 
4205 // Changing the Skills list ([xlsx] vs [xlsx, pptx]) changes the prefix: a cache miss, while an identical list is a cache hit
4206 // Changing the Skills list ([xlsx] versus [xlsx, pptx]) changes the prefix: a cache miss, whereas an identical list is a cache hit
42064207 $response2 = $client->messages->create(
42074208 maxTokens: 4096,
42084209 messages: [
42094210 ['role' => 'user', 'content' => 'Create a presentation']
42104211 ],
4211 model: 'claude-opus-5-5',
4212 model: Model::CLAUDE_OPUS_5_5,
42124213 container: [
42134214 'skills' => [
42144215 ['type' => 'anthropic', 'skillID' => 'xlsx', 'version' => 'latest'],
from line 4238
42374238 )
42384239 puts response1
42394240 
4240 # Changing the Skills list ([xlsx] vs [xlsx, pptx]) changes the prefix: a cache miss, while an identical list is a cache hit
4241 # Changing the Skills list ([xlsx] versus [xlsx, pptx]) changes the prefix: a cache miss, whereas an identical list is a cache hit
42414242 response2 = client.messages.create(
42424243 model: Anthropic::Model::CLAUDE_OPUS_5_5,
42434244 max_tokens: 4096,
from line 4461
44604461 echo $message;
44614462 } catch (BadRequestException $e) {
44624463 if (str_contains($e->getMessage(), 'skill')) {
4463 echo "Skill error: " . $e->getMessage();
4464 echo 'Skill error: ' . $e->getMessage();
44644465 } else {
44654466 throw $e;
44664467 }

build-with-claude/streaming Changed · +16 / -16 lines

from line 98
9898 try (var streamResponse = client.messages().createStreaming(params)) {
9999 streamResponse.stream().forEach(event -> {
100100 event.contentBlockDelta().ifPresent(deltaEvent ->
101 deltaEvent.delta().text().ifPresent(td ->
102 System.out.print(td.text())
101 deltaEvent.delta().text().ifPresent(textDelta ->
102 System.out.print(textDelta.text())
103103 )
104104 );
105105 });
from line 114
114114 messages: [
115115 ['role' => 'user', 'content' => 'Hello']
116116 ],
117 model: 'claude-opus-5-5',
117 model: Model::CLAUDE_OPUS_5_5,
118118 );
119119 
120120 foreach ($stream as $message) {
from line 493
493493 try (var streamResponse = client.messages().createStreaming(params)) {
494494 streamResponse.stream().forEach(event -> {
495495 event.contentBlockDelta().ifPresent(deltaEvent ->
496 deltaEvent.delta().text().ifPresent(td ->
497 System.out.print(td.text())
496 deltaEvent.delta().text().ifPresent(textDelta ->
497 System.out.print(textDelta.text())
498498 )
499499 );
500500 });
from line 509
509509 messages: [
510510 ['role' => 'user', 'content' => 'Hello']
511511 ],
512 model: 'claude-opus-5-5',
512 model: Model::CLAUDE_OPUS_5_5,
513513 );
514514 
515515 foreach ($stream as $message) {
from line 797
797797 try (var streamResponse = client.messages().createStreaming(params)) {
798798 streamResponse.stream().forEach(event -> {
799799 event.contentBlockDelta().ifPresent(deltaEvent ->
800 deltaEvent.delta().text().ifPresent(td ->
801 System.out.print(td.text())
800 deltaEvent.delta().text().ifPresent(textDelta ->
801 System.out.print(textDelta.text())
802802 )
803803 );
804804 });
from line 813
813813 messages: [
814814 ['role' => 'user', 'content' => 'What is the weather like in San Francisco?']
815815 ],
816 model: 'claude-opus-5',
816 model: Model::CLAUDE_OPUS_5,
817817 toolChoice: ['type' => 'any'],
818818 tools: [
819819 [
from line 1111
11111111 try (var streamResponse = client.messages().createStreaming(params)) {
11121112 streamResponse.stream().forEach(event -> {
11131113 event.contentBlockDelta().ifPresent(deltaEvent -> {
1114 deltaEvent.delta().thinking().ifPresent(td ->
1115 IO.print(td.thinking())
1114 deltaEvent.delta().thinking().ifPresent(thinkingDelta ->
1115 IO.print(thinkingDelta.thinking())
11161116 );
1117 deltaEvent.delta().text().ifPresent(td ->
1118 IO.print(td.text())
1117 deltaEvent.delta().text().ifPresent(textDelta ->
1118 IO.print(textDelta.text())
11191119 );
11201120 });
11211121 });
from line 1130
11301130 messages: [
11311131 ['role' => 'user', 'content' => 'What is the greatest common divisor of 1071 and 462?']
11321132 ],
1133 model: 'claude-opus-5-5',
1133 model: Model::CLAUDE_OPUS_5_5,
11341134 thinking: ['type' => 'adaptive', 'display' => 'summarized'],
11351135 );
11361136 
from line 1344
13441344 try (var streamResponse = client.messages().createStreaming(params)) {
13451345 streamResponse.stream().forEach(event -> {
13461346 event.contentBlockDelta().ifPresent(deltaEvent ->
1347 deltaEvent.delta().text().ifPresent(td ->
1348 System.out.print(td.text())
1347 deltaEvent.delta().text().ifPresent(textDelta ->
1348 System.out.print(textDelta.text())
13491349 )
13501350 );
13511351 });
Feedback