thinking-steering-and-cost changedbuild-with-claude/thinking-steering-and-cost
Nearest release: v2.1.309, published 3 hours before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Recorded here
Lines+675added
Lines−692removed
From line
116
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits16to this page, all time
The whole hunk
from line 116, old and new numbered
/
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 116
116116
117117For multi-turn applications, this means you can pass back conversation history in whatever shape you have it:
118118
119* Assistant turns without thinking are valid history as-is.
119* Assistant turns that Claude produced without thinking are valid history as-is.
120120* You can resume a conversation that started without thinking, or that used a different thinking configuration, without rewriting its history.
121121* History assembled from mixed sources doesn't need thinking blocks reinserted at the start of each assistant turn to pass validation.
122122
from line 131
131131The following example demonstrates the invalidation with a multi-turn script you can run yourself:
132132
133133<Accordion title="Effort changes invalidate the prompt cache">
134 <Tabs>
135 <Tab title="cURL">
136 <Note>
137 This workflow doesn't translate well to a one-off shell command. Use the Claude SDK to run it; per-turn HTTP requests follow the examples on the [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) page.
138 </Note>
139 </Tab>
140
141 <Tab title="CLI">
142 <Note>
143 This workflow doesn't translate well to a one-off shell command. Use the Claude SDK to run it; per-turn CLI commands follow the examples on the [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) page.
144 </Note>
145 </Tab>
146
147 <Tab title="Python">
148 ```python
149 import requests
150
151 client = Anthropic()
152
153
154 def fetch_article_content(url):
155 text = requests.get(url).text
156 lines = (line.strip() for line in text.splitlines())
157 return "\n".join(line for line in lines if line)
158
159
160 # Fetch the content of the article
161 book_url = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
162 book_content = fetch_article_content(book_url)
163 # Use just enough text for caching (first few chapters)
164 LARGE_TEXT = book_content[:10000]
165
166 # No system prompt - caching in messages instead
167 MESSAGES = [
134 <CodeGroup exclude="shell:cURL, shell:CLI">
135 <CodeGroupItem language="cURL">
136 This workflow needs more logic than a single shell command. Use the Claude SDK to run it; per-turn HTTP requests follow the examples on the [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) page.
137 </CodeGroupItem>
138
139 <CodeGroupItem language="CLI">
140 This workflow needs more logic than a single shell command. Use the Claude SDK to run it; per-turn CLI commands follow the examples on the [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) page.
141 </CodeGroupItem>
142
143 ```python Python
144 import requests
145
146 client = Anthropic()
147
148
149 def fetch_article_content(url):
150 text = requests.get(url).text
151 lines = (line.strip() for line in text.splitlines())
152 return "\n".join(line for line in lines if line)
153
154
155 # Fetch the content of the article
156 book_url = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
157 book_content = fetch_article_content(book_url)
158 # Use just enough text for caching (first few chapters)
159 LARGE_TEXT = book_content[:10000]
160
161 # No system prompt: caching in messages instead
162 MESSAGES = [
163 {
164 "role": "user",
165 "content": [
166 {
167 "type": "text",
168 "text": LARGE_TEXT,
169 "cache_control": {"type": "ephemeral"},
170 },
171 {"type": "text", "text": "Analyze the tone of this passage."},
172 ],
173 }
174 ]
175
176 # First request: establish cache
177 print("First request - establishing cache")
178 response1 = client.messages.create(
179 model="claude-opus-5-5",
180 max_tokens=16000,
181 thinking={"type": "adaptive"},
182 messages=MESSAGES,
183 )
184
185 print(f"First response usage: {response1.usage}")
186
187 MESSAGES.append({"role": "assistant", "content": response1.content})
188 MESSAGES.append({"role": "user", "content": "Analyze the characters in this passage."})
189
190 # Second request: same configuration (cache hit expected)
191 print("\nSecond request - same configuration (cache hit expected)")
192 response2 = client.messages.create(
193 model="claude-opus-5-5",
194 max_tokens=16000,
195 thinking={"type": "adaptive"},
196 messages=MESSAGES,
197 )
198
199 print(f"Second response usage: {response2.usage}")
200
201 MESSAGES.append({"role": "assistant", "content": response2.content})
202 MESSAGES.append({"role": "user", "content": "Analyze the setting in this passage."})
203
204 # Third request: different effort level (cache miss expected)
205 print("\nThird request - different effort level (cache miss expected)")
206 response3 = client.messages.create(
207 model="claude-opus-5-5",
208 max_tokens=16000,
209 thinking={"type": "adaptive"},
210 output_config={"effort": "low"},
211 messages=MESSAGES,
212 )
213
214 print(f"Third response usage: {response3.usage}")
215 ```
216
217 ```typescript TypeScript
218
219 const client = new Anthropic();
220
221 async function fetchArticleContent(url: string): Promise<string> {
222 const response = await fetch(url);
223 const text = await response.text();
224 const lines = text.split("\n").map((line) => line.trim());
225 return lines.filter((line) => line).join("\n");
226 }
227
228 const bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
229 const bookContent = await fetchArticleContent(bookUrl);
230 const LARGE_TEXT = bookContent.substring(0, 10000);
231
232 // No system prompt: caching in messages instead
233 const messages: Anthropic.MessageParam[] = [
234 {
235 role: "user",
236 content: [
168237 {
169 "role": "user",
170 "content": [
171 {
172 "type": "text",
173 "text": LARGE_TEXT,
174 "cache_control": {"type": "ephemeral"},
175 },
176 {"type": "text", "text": "Analyze the tone of this passage."},
177 ],
238 type: "text",
239 text: LARGE_TEXT,
240 cache_control: { type: "ephemeral" }
241 },
242 {
243 type: "text",
244 text: "Analyze the tone of this passage."
178245 }
179 ]
180
181 # First request - establish cache
182 print("First request - establishing cache")
183 response1 = client.messages.create(
184 model="claude-opus-5-5",
185 max_tokens=16000,
186 thinking={"type": "adaptive"},
187 messages=MESSAGES,
188 )
189
190 print(f"First response usage: {response1.usage}")
191
192 MESSAGES.append({"role": "assistant", "content": response1.content})
193 MESSAGES.append({"role": "user", "content": "Analyze the characters in this passage."})
194
195 # Second request - same configuration (cache hit expected)
196 print("\nSecond request - same configuration (cache hit expected)")
197 response2 = client.messages.create(
198 model="claude-opus-5-5",
199 max_tokens=16000,
200 thinking={"type": "adaptive"},
201 messages=MESSAGES,
202 )
203
204 print(f"Second response usage: {response2.usage}")
205
206 MESSAGES.append({"role": "assistant", "content": response2.content})
207 MESSAGES.append({"role": "user", "content": "Analyze the setting in this passage."})
208
209 # Third request - different effort level (cache miss expected)
210 print("\nThird request - different effort level (cache miss expected)")
211 response3 = client.messages.create(
212 model="claude-opus-5-5",
213 max_tokens=16000,
214 thinking={"type": "adaptive"},
215 output_config={"effort": "low"},
216 messages=MESSAGES,
217 )
218
219 print(f"Third response usage: {response3.usage}")
220 ```
221 </Tab>
222
223 <Tab title="TypeScript">
224 ```typescript
225
226 const client = new Anthropic();
227
228 async function fetchArticleContent(url: string): Promise<string> {
229 const response = await fetch(url);
230 const text = await response.text();
231 const lines = text.split("\n").map((line) => line.trim());
232 return lines.filter((line) => line).join("\n");
246 ]
233247 }
234
235 const bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
236 const bookContent = await fetchArticleContent(bookUrl);
237 const LARGE_TEXT = bookContent.substring(0, 10000);
238
239 // No system prompt - caching in messages instead
240 const messages: Anthropic.MessageParam[] = [
248 ];
249
250 // First request: establish cache
251 console.log("First request - establishing cache");
252 const response1 = await client.messages.create({
253 model: "claude-opus-5-5",
254 max_tokens: 16000,
255 thinking: { type: "adaptive" },
256 messages
257 });
258
259 console.log("First response usage: ", response1.usage);
260
261 messages.push(
262 { role: "assistant", content: response1.content },
263 { role: "user", content: "Analyze the characters in this passage." }
264 );
265
266 // Second request: same configuration (cache hit expected)
267 console.log("\nSecond request - same configuration (cache hit expected)");
268 const response2 = await client.messages.create({
269 model: "claude-opus-5-5",
270 max_tokens: 16000,
271 thinking: { type: "adaptive" },
272 messages
273 });
274
275 console.log("Second response usage: ", response2.usage);
276
277 messages.push(
278 { role: "assistant", content: response2.content },
279 { role: "user", content: "Analyze the setting in this passage." }
280 );
281
282 // Third request: different effort level (cache miss expected)
283 console.log("\nThird request - different effort level (cache miss expected)");
284 const response3 = await client.messages.create({
285 model: "claude-opus-5-5",
286 max_tokens: 16000,
287 thinking: { type: "adaptive" },
288 output_config: { effort: "low" },
289 messages
290 });
291
292 console.log("Third response usage: ", response3.usage);
293 ```
294
295 ```csharp C#
296 AnthropicClient client = new();
297
298 string bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
299 string bookContent = await FetchArticleContent(bookUrl);
300 string largeText = bookContent.Substring(0, Math.Min(10000, bookContent.Length));
301
302 Console.WriteLine("First request - establishing cache");
303 var parameters1 = new MessageCreateParams
304 {
305 Model = Model.ClaudeOpus5_5,
306 MaxTokens = 16000,
307 Thinking = new ThinkingConfigAdaptive(),
308 Messages =
309 [
310 new UserMessageParam
311 {
312 Content = new List<ContentBlockParam>
313 {
314 new ContentBlockParam(new TextBlockParam()
315 {
316 Text = largeText,
317 CacheControl = new CacheControlEphemeral(),
318 }),
319 new ContentBlockParam(new TextBlockParam()
320 {
321 Text = "Analyze the tone of this passage."
322 }),
323 }
324 }
325 ]
326 };
327
328 var response1 = await client.Messages.Create(parameters1);
329 Console.WriteLine($"First response usage: {response1.Usage}");
330
331 Console.WriteLine("\nSecond request - same configuration (cache hit expected)");
332 var parameters2 = new MessageCreateParams
333 {
334 Model = Model.ClaudeOpus5_5,
335 MaxTokens = 16000,
336 Thinking = new ThinkingConfigAdaptive(),
337 Messages =
338 [
339 new UserMessageParam
340 {
341 Content = new List<ContentBlockParam>
342 {
343 new ContentBlockParam(new TextBlockParam()
344 {
345 Text = largeText,
346 CacheControl = new CacheControlEphemeral(),
347 }),
348 new ContentBlockParam(new TextBlockParam()
349 {
350 Text = "Analyze the tone of this passage."
351 }),
352 }
353 },
354 new AssistantMessageParam
355 {
356 Content = response1.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
357 },
358 new UserMessageParam { Content = "Analyze the characters in this passage." }
359 ]
360 };
361
362 var response2 = await client.Messages.Create(parameters2);
363 Console.WriteLine($"Second response usage: {response2.Usage}");
364
365 Console.WriteLine("\nThird request - different effort level (cache miss expected)");
366 var parameters3 = new MessageCreateParams
367 {
368 Model = Model.ClaudeOpus5_5,
369 MaxTokens = 16000,
370 Thinking = new ThinkingConfigAdaptive(),
371 OutputConfig = new OutputConfig
241372 {
242 role: "user",
243 content: [
373 Effort = Effort.Low
374 },
375 Messages =
376 [
377 new UserMessageParam
244378 {
245 type: "text",
246 text: LARGE_TEXT,
247 cache_control: { type: "ephemeral" }
379 Content = new List<ContentBlockParam>
380 {
381 new ContentBlockParam(new TextBlockParam()
382 {
383 Text = largeText,
384 CacheControl = new CacheControlEphemeral(),
385 }),
386 new ContentBlockParam(new TextBlockParam()
387 {
388 Text = "Analyze the tone of this passage."
389 }),
390 }
248391 },
392 new AssistantMessageParam
249393 {
250 type: "text",
251 text: "Analyze the tone of this passage."
252 }
253 ]
254 }
255 ];
256
257 // First request - establish cache
258 console.log("First request - establishing cache");
259 const response1 = await client.messages.create({
260 model: "claude-opus-5-5",
261 max_tokens: 16000,
262 thinking: { type: "adaptive" },
263 messages
264 });
265
266 console.log("First response usage: ", response1.usage);
267
268 messages.push(
269 { role: "assistant", content: response1.content },
270 { role: "user", content: "Analyze the characters in this passage." }
271 );
272
273 // Second request - same configuration (cache hit expected)
274 console.log("\nSecond request - same configuration (cache hit expected)");
275 const response2 = await client.messages.create({
276 model: "claude-opus-5-5",
277 max_tokens: 16000,
278 thinking: { type: "adaptive" },
279 messages
280 });
281
282 console.log("Second response usage: ", response2.usage);
283
284 messages.push(
285 { role: "assistant", content: response2.content },
286 { role: "user", content: "Analyze the setting in this passage." }
287 );
288
289 // Third request - different effort level (cache miss expected)
290 console.log("\nThird request - different effort level (cache miss expected)");
291 const response3 = await client.messages.create({
292 model: "claude-opus-5-5",
293 max_tokens: 16000,
294 thinking: { type: "adaptive" },
295 output_config: { effort: "low" },
296 messages
297 });
298
299 console.log("Third response usage: ", response3.usage);
300 ```
301 </Tab>
302
303 <Tab title="C#">
304 ```csharp
305 AnthropicClient client = new();
306
307 string bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
308 string bookContent = await FetchArticleContent(bookUrl);
309 string largeText = bookContent.Substring(0, Math.Min(10000, bookContent.Length));
310
311 Console.WriteLine("First request - establishing cache");
312 var parameters1 = new MessageCreateParams
313 {
314 Model = Model.ClaudeOpus5_5,
315 MaxTokens = 16000,
316 Thinking = new ThinkingConfigAdaptive(),
317 Messages =
318 [
319 new UserMessageParam
320 {
321 Content = new List<ContentBlockParam>
322 {
323 new ContentBlockParam(new TextBlockParam()
324 {
325 Text = largeText,
326 CacheControl = new CacheControlEphemeral(),
327 }),
328 new ContentBlockParam(new TextBlockParam()
329 {
330 Text = "Analyze the tone of this passage."
331 }),
332 }
333 }
334 ]
335 };
336
337 var response1 = await client.Messages.Create(parameters1);
338 Console.WriteLine($"First response usage: {response1.Usage}");
339
340 Console.WriteLine("\nSecond request - same configuration (cache hit expected)");
341 var parameters2 = new MessageCreateParams
342 {
343 Model = Model.ClaudeOpus5_5,
344 MaxTokens = 16000,
345 Thinking = new ThinkingConfigAdaptive(),
346 Messages =
347 [
348 new UserMessageParam
349 {
350 Content = new List<ContentBlockParam>
351 {
352 new ContentBlockParam(new TextBlockParam()
353 {
354 Text = largeText,
355 CacheControl = new CacheControlEphemeral(),
356 }),
357 new ContentBlockParam(new TextBlockParam()
358 {
359 Text = "Analyze the tone of this passage."
360 }),
361 }
362 },
363 new AssistantMessageParam
364 {
365 Content = response1.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
366 },
367 new UserMessageParam { Content = "Analyze the characters in this passage." }
368 ]
369 };
370
371 var response2 = await client.Messages.Create(parameters2);
372 Console.WriteLine($"Second response usage: {response2.Usage}");
373
374 Console.WriteLine("\nThird request - different effort level (cache miss expected)");
375 var parameters3 = new MessageCreateParams
376 {
377 Model = Model.ClaudeOpus5_5,
378 MaxTokens = 16000,
379 Thinking = new ThinkingConfigAdaptive(),
380 OutputConfig = new OutputConfig
394 Content = response1.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
395 },
396 new UserMessageParam { Content = "Analyze the characters in this passage." },
397 new AssistantMessageParam
398 {
399 Content = response2.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
400 },
401 new UserMessageParam { Content = "Analyze the setting in this passage." }
402 ]
403 };
404
405 var response3 = await client.Messages.Create(parameters3);
406 Console.WriteLine($"Third response usage: {response3.Usage}");
407
408 static async Task<string> FetchArticleContent(string url)
409 {
410 using HttpClient httpClient = new();
411 string content = await httpClient.GetStringAsync(url);
412 return content;
413 }
414 ```
415
416 ```go Go
417 client := anthropic.NewClient()
418
419 bookURL := "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
420 bookContent, err := fetchArticleContent(bookURL)
421 if err != nil {
422 log.Fatal(err)
423 }
424
425 largeText := bookContent
426 if len(largeText) > 10000 {
427 largeText = largeText[:10000]
428 }
429
430 // No system prompt: caching in messages instead
431 messages := []anthropic.MessageParam{
432 anthropic.NewUserMessage(
433 anthropic.ContentBlockParamUnion{OfText: &anthropic.TextBlockParam{
434 Text: largeText,
435 CacheControl: anthropic.NewCacheControlEphemeralParam(),
436 }},
437 anthropic.NewTextBlock("Analyze the tone of this passage."),
438 ),
439 }
440
441 // First request: establish cache
442 fmt.Println("First request - establishing cache")
443 response1, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
444 Model: anthropic.ModelClaudeOpus5_5,
445 MaxTokens: 16000,
446 Thinking: anthropic.ThinkingConfigParamUnion{
447 OfAdaptive: &anthropic.ThinkingConfigAdaptiveParam{},
448 },
449 Messages: messages,
450 })
451 if err != nil {
452 log.Fatal(err)
453 }
454 fmt.Printf("First response usage: %s\n", response1.Usage.RawJSON())
455
456 messages = append(messages, response1.ToParam())
457 messages = append(messages, anthropic.NewUserMessage(anthropic.NewTextBlock("Analyze the characters in this passage.")))
458
459 // Second request: same configuration (cache hit expected)
460 fmt.Println("\nSecond request - same configuration (cache hit expected)")
461 response2, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
462 Model: anthropic.ModelClaudeOpus5_5,
463 MaxTokens: 16000,
464 Thinking: anthropic.ThinkingConfigParamUnion{
465 OfAdaptive: &anthropic.ThinkingConfigAdaptiveParam{},
466 },
467 Messages: messages,
468 })
469 if err != nil {
470 log.Fatal(err)
471 }
472 fmt.Printf("Second response usage: %s\n", response2.Usage.RawJSON())
473
474 messages = append(messages, response2.ToParam())
475 messages = append(messages, anthropic.NewUserMessage(anthropic.NewTextBlock("Analyze the setting in this passage.")))
476
477 // Third request: different effort level (cache miss expected)
478 fmt.Println("\nThird request - different effort level (cache miss expected)")
479 response3, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
480 Model: anthropic.ModelClaudeOpus5_5,
481 MaxTokens: 16000,
482 Thinking: anthropic.ThinkingConfigParamUnion{
483 OfAdaptive: &anthropic.ThinkingConfigAdaptiveParam{},
484 },
485 OutputConfig: anthropic.OutputConfigParam{
486 Effort: anthropic.OutputConfigEffortLow,
487 },
488 Messages: messages,
489 })
490 if err != nil {
491 log.Fatal(err)
492 }
493 fmt.Printf("Third response usage: %s\n", response3.Usage.RawJSON())
494 ```
495
496 ```java Java
497 import com.anthropic.models.messages.CacheControlEphemeral;
498 // ...
499 void main() throws Exception {
500 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
501
502 String bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
503 String bookContent = fetchArticleContent(bookUrl);
504 String largeText = bookContent.substring(0, Math.min(10000, bookContent.length()));
505
506 // First request: establish cache
507 IO.println("First request - establishing cache");
508 MessageCreateParams params1 = MessageCreateParams.builder()
509 .model(Model.CLAUDE_OPUS_5_5)
510 .maxTokens(16000L)
511 .thinking(ThinkingConfigAdaptive.builder().build())
512 .addUserMessageOfContentBlockParams(List.of(
513 ContentBlockParam.ofText(TextBlockParam.builder()
514 .text(largeText)
515 .cacheControl(CacheControlEphemeral.builder().build())
516 .build()),
517 ContentBlockParam.ofText(TextBlockParam.builder()
518 .text("Analyze the tone of this passage.")
519 .build())
520 ))
521 .build();
522
523 Message response1 = client.messages().create(params1);
524 IO.println("First response usage: " + response1.usage());
525
526 // Second request: same configuration (cache hit expected)
527 IO.println("\nSecond request - same configuration (cache hit expected)");
528 MessageCreateParams params2 = MessageCreateParams.builder()
529 .model(Model.CLAUDE_OPUS_5_5)
530 .maxTokens(16000L)
531 .thinking(ThinkingConfigAdaptive.builder().build())
532 .addUserMessageOfContentBlockParams(List.of(
533 ContentBlockParam.ofText(TextBlockParam.builder()
534 .text(largeText)
535 .cacheControl(CacheControlEphemeral.builder().build())
536 .build()),
537 ContentBlockParam.ofText(TextBlockParam.builder()
538 .text("Analyze the tone of this passage.")
539 .build())
540 ))
541 .addAssistantMessageOfContentBlockParams(response1.content().stream()
542 .map(block -> block.toParam())
543 .collect(Collectors.toList()))
544 .addUserMessage("Analyze the characters in this passage.")
545 .build();
546
547 Message response2 = client.messages().create(params2);
548 IO.println("Second response usage: " + response2.usage());
549
550 // Third request: different effort level (cache miss expected)
551 IO.println("\nThird request - different effort level (cache miss expected)");
552 MessageCreateParams params3 = MessageCreateParams.builder()
553 .model(Model.CLAUDE_OPUS_5_5)
554 .maxTokens(16000L)
555 .thinking(ThinkingConfigAdaptive.builder().build())
556 .outputConfig(OutputConfig.builder()
557 .effort(OutputConfig.Effort.LOW)
558 .build())
559 .addUserMessageOfContentBlockParams(List.of(
560 ContentBlockParam.ofText(TextBlockParam.builder()
561 .text(largeText)
562 .cacheControl(CacheControlEphemeral.builder().build())
563 .build()),
564 ContentBlockParam.ofText(TextBlockParam.builder()
565 .text("Analyze the tone of this passage.")
566 .build())
567 ))
568 .addAssistantMessageOfContentBlockParams(response1.content().stream()
569 .map(block -> block.toParam())
570 .collect(Collectors.toList()))
571 .addUserMessage("Analyze the characters in this passage.")
572 .addAssistantMessageOfContentBlockParams(response2.content().stream()
573 .map(block -> block.toParam())
574 .collect(Collectors.toList()))
575 .addUserMessage("Analyze the setting in this passage.")
576 .build();
577
578 Message response3 = client.messages().create(params3);
579 IO.println("Third response usage: " + response3.usage());
580 }
581
582 String fetchArticleContent(String url) throws Exception {
583 HttpClient client = HttpClient.newHttpClient();
584 HttpRequest request = HttpRequest.newBuilder()
585 .uri(URI.create(url))
586 .build();
587 HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
588 return response.body();
589 }
590 ```
591
592 ```php PHP
593 function fetchArticleContent($url)
594 {
595 $content = file_get_contents($url);
596 $lines = explode("\n", $content);
597 $cleanedLines = array_filter(array_map('trim', $lines));
598 return implode("\n", $cleanedLines);
599 }
600
601 $client = new Client();
602
603 $bookUrl = 'https://www.gutenberg.org/cache/epub/1342/pg1342.txt';
604 $bookContent = fetchArticleContent($bookUrl);
605 $largeText = substr($bookContent, 0, 10000);
606
607 echo "First request - establishing cache\n";
608 $response1 = $client->messages->create(
609 maxTokens: 16000,
610 messages: [[
611 'role' => 'user',
612 'content' => [
613 [
614 'type' => 'text',
615 'text' => $largeText,
616 'cache_control' => ['type' => 'ephemeral']
617 ],
618 [
619 'type' => 'text',
620 'text' => 'Analyze the tone of this passage.'
621 ]
622 ]
623 ]],
624 model: 'claude-opus-5-5',
625 thinking: ['type' => 'adaptive'],
626 );
627
628 echo 'First response usage: ' . json_encode($response1->usage) . "\n";
629
630 echo "\nSecond request - same configuration (cache hit expected)\n";
631 $response2 = $client->messages->create(
632 maxTokens: 16000,
633 messages: [
634 [
635 'role' => 'user',
636 'content' => [
637 [
638 'type' => 'text',
639 'text' => $largeText,
640 'cache_control' => ['type' => 'ephemeral']
641 ],
642 [
643 'type' => 'text',
644 'text' => 'Analyze the tone of this passage.'
645 ]
646 ]
647 ],
648 [
649 'role' => 'assistant',
650 'content' => $response1->content
651 ],
652 [
653 'role' => 'user',
654 'content' => 'Analyze the characters in this passage.'
655 ]
656 ],
657 model: 'claude-opus-5-5',
658 thinking: ['type' => 'adaptive'],
659 );
660
661 echo 'Second response usage: ' . json_encode($response2->usage) . "\n";
662
663 echo "\nThird request - different effort level (cache miss expected)\n";
664 $response3 = $client->messages->create(
665 maxTokens: 16000,
666 messages: [
667 [
668 'role' => 'user',
669 'content' => [
670 [
671 'type' => 'text',
672 'text' => $largeText,
673 'cache_control' => ['type' => 'ephemeral']
674 ],
675 [
676 'type' => 'text',
677 'text' => 'Analyze the tone of this passage.'
678 ]
679 ]
680 ],
681 [
682 'role' => 'assistant',
683 'content' => $response1->content
684 ],
685 [
686 'role' => 'user',
687 'content' => 'Analyze the characters in this passage.'
688 ],
689 [
690 'role' => 'assistant',
691 'content' => $response2->content
692 ],
693 [
694 'role' => 'user',
695 'content' => 'Analyze the setting in this passage.'
696 ]
697 ],
698 model: 'claude-opus-5-5',
699 thinking: ['type' => 'adaptive'],
700 outputConfig: ['effort' => 'low'],
701 );
702
703 echo 'Third response usage: ' . json_encode($response3->usage) . "\n";
704 ```
705
706 ```ruby Ruby
707 require "net/http"
708 require "uri"
709
710 def fetch_article_content(url)
711 uri = URI.parse(url)
712 response = Net::HTTP.get_response(uri)
713 text = response.body
714
715 lines = text.split("\n").map(&:strip)
716 lines.reject(&:empty?).join("\n")
717 end
718
719 client = Anthropic::Client.new
720
721 book_url = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
722 book_content = fetch_article_content(book_url)
723 large_text = book_content[0...10000]
724
725 puts "First request - establishing cache"
726 response1 = client.messages.create(
727 model: "claude-opus-5-5",
728 max_tokens: 16000,
729 thinking: {
730 type: "adaptive"
731 },
732 messages: [{
733 role: "user",
734 content: [
381735 {
382 Effort = Effort.Low
736 type: "text",
737 text: large_text,
738 cache_control: { type: "ephemeral" }
383739 },
384 Messages =
385 [
386 new UserMessageParam
387 {
388 Content = new List<ContentBlockParam>
389 {
390 new ContentBlockParam(new TextBlockParam()
391 {
392 Text = largeText,
393 CacheControl = new CacheControlEphemeral(),
394 }),
395 new ContentBlockParam(new TextBlockParam()
396 {
397 Text = "Analyze the tone of this passage."
398 }),
399 }
400 },
401 new AssistantMessageParam
402 {
403 Content = response1.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
404 },
405 new UserMessageParam { Content = "Analyze the characters in this passage." },
406 new AssistantMessageParam
407 {
408 Content = response2.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
409 },
410 new UserMessageParam { Content = "Analyze the setting in this passage." }
411 ]
412 };
413
414 var response3 = await client.Messages.Create(parameters3);
415 Console.WriteLine($"Third response usage: {response3.Usage}");
416
417 static async Task<string> FetchArticleContent(string url)
418 {
419 using HttpClient httpClient = new();
420 string content = await httpClient.GetStringAsync(url);
421 return content;
422 }
423 ```
424 </Tab>
425
426 <Tab title="Go">
427 ```go
428 client := anthropic.NewClient()
429
430 bookURL := "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
431 bookContent, err := fetchArticleContent(bookURL)
432 if err != nil {
433 log.Fatal(err)
434 }
435
436 largeText := bookContent
437 if len(largeText) > 10000 {
438 largeText = largeText[:10000]
439 }
440
441 // No system prompt - caching in messages instead
442 messages := []anthropic.MessageParam{
443 anthropic.NewUserMessage(
444 anthropic.ContentBlockParamUnion{OfText: &anthropic.TextBlockParam{
445 Text: largeText,
446 CacheControl: anthropic.NewCacheControlEphemeralParam(),
447 }},
448 anthropic.NewTextBlock("Analyze the tone of this passage."),
449 ),
450 }
451
452 // First request - establish cache
453 fmt.Println("First request - establishing cache")
454 response1, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
455 Model: anthropic.ModelClaudeOpus5_5,
456 MaxTokens: 16000,
457 Thinking: anthropic.ThinkingConfigParamUnion{
458 OfAdaptive: &anthropic.ThinkingConfigAdaptiveParam{},
459 },
460 Messages: messages,
461 })
462 if err != nil {
463 log.Fatal(err)
464 }
465 fmt.Printf("First response usage: %s\n", response1.Usage.RawJSON())
466
467 messages = append(messages, response1.ToParam())
468 messages = append(messages, anthropic.NewUserMessage(anthropic.NewTextBlock("Analyze the characters in this passage.")))
469
470 // Second request - same configuration (cache hit expected)
471 fmt.Println("\nSecond request - same configuration (cache hit expected)")
472 response2, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
473 Model: anthropic.ModelClaudeOpus5_5,
474 MaxTokens: 16000,
475 Thinking: anthropic.ThinkingConfigParamUnion{
476 OfAdaptive: &anthropic.ThinkingConfigAdaptiveParam{},
477 },
478 Messages: messages,
479 })
480 if err != nil {
481 log.Fatal(err)
482 }
483 fmt.Printf("Second response usage: %s\n", response2.Usage.RawJSON())
484
485 messages = append(messages, response2.ToParam())
486 messages = append(messages, anthropic.NewUserMessage(anthropic.NewTextBlock("Analyze the setting in this passage.")))
487
488 // Third request - different effort level (cache miss expected)
489 fmt.Println("\nThird request - different effort level (cache miss expected)")
490 response3, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
491 Model: anthropic.ModelClaudeOpus5_5,
492 MaxTokens: 16000,
493 Thinking: anthropic.ThinkingConfigParamUnion{
494 OfAdaptive: &anthropic.ThinkingConfigAdaptiveParam{},
495 },
496 OutputConfig: anthropic.OutputConfigParam{
497 Effort: anthropic.OutputConfigEffortLow,
498 },
499 Messages: messages,
500 })
501 if err != nil {
502 log.Fatal(err)
503 }
504 fmt.Printf("Third response usage: %s\n", response3.Usage.RawJSON())
505 ```
506 </Tab>
507
508 <Tab title="Java">
509 ```java
510 import com.anthropic.models.messages.CacheControlEphemeral;
511 // ...
512 void main() throws Exception {
513 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
514
515 String bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
516 String bookContent = fetchArticleContent(bookUrl);
517 String largeText = bookContent.substring(0, Math.min(10000, bookContent.length()));
518
519 // First request - establishing cache
520 IO.println("First request - establishing cache");
521 MessageCreateParams params1 = MessageCreateParams.builder()
522 .model(Model.CLAUDE_OPUS_5_5)
523 .maxTokens(16000L)
524 .thinking(ThinkingConfigAdaptive.builder().build())
525 .addUserMessageOfContentBlockParams(List.of(
526 ContentBlockParam.ofText(TextBlockParam.builder()
527 .text(largeText)
528 .cacheControl(CacheControlEphemeral.builder().build())
529 .build()),
530 ContentBlockParam.ofText(TextBlockParam.builder()
531 .text("Analyze the tone of this passage.")
532 .build())
533 ))
534 .build();
535
536 Message response1 = client.messages().create(params1);
537 IO.println("First response usage: " + response1.usage());
538
539 // Second request - same configuration (cache hit expected)
540 IO.println("\nSecond request - same configuration (cache hit expected)");
541 MessageCreateParams params2 = MessageCreateParams.builder()
542 .model(Model.CLAUDE_OPUS_5_5)
543 .maxTokens(16000L)
544 .thinking(ThinkingConfigAdaptive.builder().build())
545 .addUserMessageOfContentBlockParams(List.of(
546 ContentBlockParam.ofText(TextBlockParam.builder()
547 .text(largeText)
548 .cacheControl(CacheControlEphemeral.builder().build())
549 .build()),
550 ContentBlockParam.ofText(TextBlockParam.builder()
551 .text("Analyze the tone of this passage.")
552 .build())
553 ))
554 .addAssistantMessageOfContentBlockParams(response1.content().stream()
555 .map(block -> block.toParam())
556 .collect(Collectors.toList()))
557 .addUserMessage("Analyze the characters in this passage.")
558 .build();
559
560 Message response2 = client.messages().create(params2);
561 IO.println("Second response usage: " + response2.usage());
562
563 // Third request - different effort level (cache miss expected)
564 IO.println("\nThird request - different effort level (cache miss expected)");
565 MessageCreateParams params3 = MessageCreateParams.builder()
566 .model(Model.CLAUDE_OPUS_5_5)
567 .maxTokens(16000L)
568 .thinking(ThinkingConfigAdaptive.builder().build())
569 .outputConfig(OutputConfig.builder()
570 .effort(OutputConfig.Effort.LOW)
571 .build())
572 .addUserMessageOfContentBlockParams(List.of(
573 ContentBlockParam.ofText(TextBlockParam.builder()
574 .text(largeText)
575 .cacheControl(CacheControlEphemeral.builder().build())
576 .build()),
577 ContentBlockParam.ofText(TextBlockParam.builder()
578 .text("Analyze the tone of this passage.")
579 .build())
580 ))
581 .addAssistantMessageOfContentBlockParams(response1.content().stream()
582 .map(block -> block.toParam())
583 .collect(Collectors.toList()))
584 .addUserMessage("Analyze the characters in this passage.")
585 .addAssistantMessageOfContentBlockParams(response2.content().stream()
586 .map(block -> block.toParam())
587 .collect(Collectors.toList()))
588 .addUserMessage("Analyze the setting in this passage.")
589 .build();
590
591 Message response3 = client.messages().create(params3);
592 IO.println("Third response usage: " + response3.usage());
593 }
594
595 String fetchArticleContent(String url) throws Exception {
596 HttpClient client = HttpClient.newHttpClient();
597 HttpRequest request = HttpRequest.newBuilder()
598 .uri(URI.create(url))
599 .build();
600 HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
601 return response.body();
602 }
603 ```
604 </Tab>
605
606 <Tab title="PHP">
607 ```php
608 function fetchArticleContent($url) {
609 $content = file_get_contents($url);
610 $lines = explode("\n", $content);
611 $cleanedLines = array_filter(array_map('trim', $lines));
612 return implode("\n", $cleanedLines);
613 }
614
615 $client = new Client();
616
617 $bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
618 $bookContent = fetchArticleContent($bookUrl);
619 $largeText = substr($bookContent, 0, 10000);
620
621 echo "First request - establishing cache\n";
622 $response1 = $client->messages->create(
623 maxTokens: 16000,
624 messages: [[
625 'role' => 'user',
626 'content' => [
627 [
628 'type' => 'text',
629 'text' => $largeText,
630 'cache_control' => ['type' => 'ephemeral']
631 ],
632 [
633 'type' => 'text',
634 'text' => 'Analyze the tone of this passage.'
635 ]
636 ]
637 ]],
638 model: 'claude-opus-5-5',
639 thinking: ['type' => 'adaptive'],
640 );
641
642 echo "First response usage: " . json_encode($response1->usage) . "\n";
643
644 echo "\nSecond request - same configuration (cache hit expected)\n";
645 $response2 = $client->messages->create(
646 maxTokens: 16000,
647 messages: [
648 [
649 'role' => 'user',
650 'content' => [
651 [
652 'type' => 'text',
653 'text' => $largeText,
654 'cache_control' => ['type' => 'ephemeral']
655 ],
656 [
657 'type' => 'text',
658 'text' => 'Analyze the tone of this passage.'
659 ]
660 ]
661 ],
662 [
663 'role' => 'assistant',
664 'content' => $response1->content
665 ],
666 [
667 'role' => 'user',
668 'content' => 'Analyze the characters in this passage.'
669 ]
670 ],
671 model: 'claude-opus-5-5',
672 thinking: ['type' => 'adaptive'],
673 );
674
675 echo "Second response usage: " . json_encode($response2->usage) . "\n";
676
677 echo "\nThird request - different effort level (cache miss expected)\n";
678 $response3 = $client->messages->create(
679 maxTokens: 16000,
680 messages: [
681 [
682 'role' => 'user',
683 'content' => [
684 [
685 'type' => 'text',
686 'text' => $largeText,
687 'cache_control' => ['type' => 'ephemeral']
688 ],
689 [
690 'type' => 'text',
691 'text' => 'Analyze the tone of this passage.'
692 ]
693 ]
694 ],
695 [
696 'role' => 'assistant',
697 'content' => $response1->content
698 ],
699 [
700 'role' => 'user',
701 'content' => 'Analyze the characters in this passage.'
702 ],
703 [
704 'role' => 'assistant',
705 'content' => $response2->content
706 ],
707 [
708 'role' => 'user',
709 'content' => 'Analyze the setting in this passage.'
710 ]
711 ],
712 model: 'claude-opus-5-5',
713 thinking: ['type' => 'adaptive'],
714 outputConfig: ['effort' => 'low'],
715 );
716
717 echo "Third response usage: " . json_encode($response3->usage) . "\n";
718 ```
719 </Tab>
720
721 <Tab title="Ruby">
722 ```ruby
723 require "net/http"
724 require "uri"
725
726 def fetch_article_content(url)
727 uri = URI.parse(url)
728 response = Net::HTTP.get_response(uri)
729 text = response.body
730
731 lines = text.split("\n").map(&:strip)
732 lines.reject(&:empty?).join("\n")
733 end
734
735 client = Anthropic::Client.new
736
737 book_url = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
738 book_content = fetch_article_content(book_url)
739 large_text = book_content[0...10000]
740
741 puts "First request - establishing cache"
742 response1 = client.messages.create(
743 model: "claude-opus-5-5",
744 max_tokens: 16000,
745 thinking: {
746 type: "adaptive"
747 },
748 messages: [{
740 {
741 type: "text",
742 text: "Analyze the tone of this passage."
743 }
744 ]
745 }]
746 )
747
748 puts "First response usage: #{response1.usage}"
749
750 puts "\nSecond request - same configuration (cache hit expected)"
751 response2 = client.messages.create(
752 model: "claude-opus-5-5",
753 max_tokens: 16000,
754 thinking: {
755 type: "adaptive"
756 },
757 messages: [
758 {
749759 role: "user",
750760 content: [
751761 {
from line 768
758768 text: "Analyze the tone of this passage."
759769 }
760770 ]
761 }]
762 )
763
764 puts "First response usage: #{response1.usage}"
765
766 puts "\nSecond request - same configuration (cache hit expected)"
767 response2 = client.messages.create(
768 model: "claude-opus-5-5",
769 max_tokens: 16000,
770 thinking: {
771 type: "adaptive"
772771 },
773 messages: [
774 {
775 role: "user",
776 content: [
777 {
778 type: "text",
779 text: large_text,
780 cache_control: { type: "ephemeral" }
781 },
782 {
783 type: "text",
784 text: "Analyze the tone of this passage."
785 }
786 ]
787 },
788 {
789 role: "assistant",
790 content: response1.content
791 },
792 {
793 role: "user",
794 content: "Analyze the characters in this passage."
795 }
796 ]
797 )
798
799 puts "Second response usage: #{response2.usage}"
800
801 puts "\nThird request - different effort level (cache miss expected)"
802 response3 = client.messages.create(
803 model: "claude-opus-5-5",
804 max_tokens: 16000,
805 thinking: {
806 type: "adaptive"
772 {
773 role: "assistant",
774 content: response1.content
807775 },
808 output_config: {
809 effort: "low"
776 {
777 role: "user",
778 content: "Analyze the characters in this passage."
779 }
780 ]
781 )
782
783 puts "Second response usage: #{response2.usage}"
784
785 puts "\nThird request - different effort level (cache miss expected)"
786 response3 = client.messages.create(
787 model: "claude-opus-5-5",
788 max_tokens: 16000,
789 thinking: {
790 type: "adaptive"
791 },
792 output_config: {
793 effort: "low"
794 },
795 messages: [
796 {
797 role: "user",
798 content: [
799 {
800 type: "text",
801 text: large_text,
802 cache_control: { type: "ephemeral" }
803 },
804 {
805 type: "text",
806 text: "Analyze the tone of this passage."
807 }
808 ]
810809 },
811 messages: [
812 {
813 role: "user",
814 content: [
815 {
816 type: "text",
817 text: large_text,
818 cache_control: { type: "ephemeral" }
819 },
820 {
821 type: "text",
822 text: "Analyze the tone of this passage."
823 }
824 ]
825 },
826 {
827 role: "assistant",
828 content: response1.content
829 },
830 {
831 role: "user",
832 content: "Analyze the characters in this passage."
833 },
834 {
835 role: "assistant",
836 content: response2.content
837 },
838 {
839 role: "user",
840 content: "Analyze the setting in this passage."
841 }
842 ]
843 )
844
845 puts "Third response usage: #{response3.usage}"
846 ```
847 </Tab>
848 </Tabs>
810 {
811 role: "assistant",
812 content: response1.content
813 },
814 {
815 role: "user",
816 content: "Analyze the characters in this passage."
817 },
818 {
819 role: "assistant",
820 content: response2.content
821 },
822 {
823 role: "user",
824 content: "Analyze the setting in this passage."
825 }
826 ]
827 )
828
829 puts "Third response usage: #{response3.usage}"
830 ```
831 </CodeGroup>
849832
850833 Here is the output of the script (you might see slightly different numbers):
851834
852835
No line in this hunk matches that.