handling-stop-reasons changedbuild-with-claude/handling-stop-reasons
Nearest release: v2.1.315, published under an hour 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+219added
Lines−118removed
From line
2,326
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits26to this page, all time
The whole hunk
from line 2326, old and new numbered
/
from line 2326
23262326
23272327### Implement retry logic for pause\_turn
23282328
2329When you use [server tools](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools), the API might return `pause_turn` if the server-side sampling loop reaches its iteration limit (default 10). Handle this by continuing the conversation:
2329When you use [server tools](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools), the API might return `pause_turn` if the server-side sampling loop reaches its iteration limit (default 10). Handle this by adding the paused response to your messages unchanged and sending the request again. If the response includes a `container`, [send its ID back](https://platform.claude.com/docs/en/agents-and-tools/tool-use/code-execution-tool#container-reuse) as well. Without it, the next request starts a new container, and files from earlier in the turn are lost.
23302330
2331<CodeGroup exclude="shell">
2331<CodeGroup exclude="shell:cURL, shell:CLI">
2332 <CodeGroupItem language="cURL">
2333 This workflow needs more logic than a single shell command. Use the [Claude SDK](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) to run it.
2334 </CodeGroupItem>
2335
2336 <CodeGroupItem language="CLI">
2337 This workflow needs more logic than a single shell command. Use the [Claude SDK](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) to run it.
2338 </CodeGroupItem>
2339
23322340 ```python Python
2333 def handle_server_tool_conversation(client, user_query, tools, max_continuations=5):
2334 """
2335 Handle server tool conversations that might require multiple continuations.
2341 client = anthropic.Anthropic()
23362342
2337 The server uses a sampling loop to run server tools. If the loop
2338 reaches its iteration limit, the API returns pause_turn. Continue the
2339 conversation by sending the response back to let Claude finish.
2340 """
2343
2344 def handle_server_tool_conversation(client, user_query, tools, max_requests=5):
23412345 messages = [{"role": "user", "content": user_query}]
2346 container_id = None
23422347
2343 for _ in range(max_continuations):
2348 for _ in range(max_requests):
23442349 response = client.messages.create(
23452350 model="claude-opus-5-5",
23462351 max_tokens=4096,
23472352 messages=messages,
23482353 tools=tools,
2354 container=container_id,
23492355 )
23502356
23512357 if response.stop_reason != "pause_turn":
2352 # Claude finished processing: return the final response
2358 # Not paused: return the response
23532359 return response
23542360
2355 # pause_turn: replace the full message list to maintain alternating roles
2356 messages = [
2357 {"role": "user", "content": user_query},
2358 {"role": "assistant", "content": response.content},
2359 ]
2361 # pause_turn: add the paused response as an assistant message, then continue
2362 messages.append({"role": "assistant", "content": response.content})
23602363
2361 # Reached max continuations: return the last response
2364 # If the tools ran in a container, send its ID back so its files are kept
2365 if response.container:
2366 container_id = response.container.id
2367
2368 # Still paused after max_requests requests: return the last response
23622369 return response
2370
2371
2372 response = handle_server_tool_conversation(
2373 client,
2374 "Use the code execution tool to find the 1,000th prime number.",
2375 [{"type": "code_execution_20250825", "name": "code_execution"}],
2376 )
2377 print(response.stop_reason)
23632378 ```
23642379
23652380 ```typescript TypeScript
2381 const client = new Anthropic();
2382
23662383 async function handleServerToolConversation(
23672384 client: Anthropic,
23682385 userQuery: string,
23692386 tools: Anthropic.ToolUnion[],
2370 maxContinuations = 5
2387 maxRequests = 5
23712388 ): Promise<Anthropic.Message> {
2372 let messages: Anthropic.MessageParam[] = [{ role: "user", content: userQuery }];
2389 const messages: Anthropic.MessageParam[] = [{ role: "user", content: userQuery }];
2390 let containerId: string | null = null;
23732391 let response: Anthropic.Message;
2392 let requestCount = 0;
23742393
2375 for (let i = 0; i < maxContinuations; i++) {
2394 do {
23762395 response = await client.messages.create({
23772396 model: "claude-opus-5-5",
23782397 max_tokens: 4096,
23792398 messages,
2380 tools
2399 tools,
2400 container: containerId
23812401 });
23822402
23832403 if (response.stop_reason !== "pause_turn") {
2384 // Claude finished processing: return the final response
2404 // Not paused: return the response
23852405 return response;
23862406 }
23872407
2388 // pause_turn: replace the full message list to maintain alternating roles
2389 messages = [
2390 { role: "user", content: userQuery },
2391 { role: "assistant", content: response.content }
2392 ];
2393 }
2408 // pause_turn: add the paused response as an assistant message, then continue
2409 messages.push({ role: "assistant", content: response.content });
23942410
2395 // Reached max continuations: return the last response
2396 return response!;
2411 // If the tools ran in a container, send its ID back so its files are kept
2412 if (response.container) {
2413 containerId = response.container.id;
2414 }
2415 } while (++requestCount < maxRequests);
2416
2417 // Still paused after maxRequests requests: return the last response
2418 return response;
23972419 }
2420
2421 const response = await handleServerToolConversation(
2422 client,
2423 "Use the code execution tool to find the 1,000th prime number.",
2424 [{ type: "code_execution_20250825", name: "code_execution" }]
2425 );
2426 console.log(response.stop_reason);
23982427 ```
23992428
24002429 ```csharp C#
2430 // A server tool turn can run for minutes, longer than the SDK's default timeout,
2431 // which it sets from MaxTokens (about 2 minutes at 4096).
2432 AnthropicClient client = new() { Timeout = TimeSpan.FromMinutes(10) };
2433
24012434 static async Task<Message> HandleServerToolConversation(
24022435 AnthropicClient client,
24032436 string userQuery,
24042437 List<ToolUnion> tools,
2405 int maxContinuations = 5)
2438 int maxRequests = 5)
24062439 {
24072440 List<MessageParam> messages = [new UserMessageParam { Content = userQuery }];
2408 Message response = null!;
2441 MessageCreateParamsContainer? container = null;
2442 Message response;
2443 var requestCount = 0;
24092444
2410 for (var i = 0; i < maxContinuations; i++)
2445 do
24112446 {
24122447 response = await client.Messages.Create(new MessageCreateParams
24132448 {
from line 2449
24142449 Model = Model.ClaudeOpus5_5,
24152450 MaxTokens = 4096,
24162451 Messages = messages,
2417 Tools = tools
2452 Tools = tools,
2453 Container = container
24182454 });
24192455
2420 if (response.StopReason != "pause_turn")
2456 if (response.StopReason != StopReason.PauseTurn)
24212457 {
2422 // Claude finished processing: return the final response
2458 // Not paused: return the response
24232459 return response;
24242460 }
24252461
2426 // pause_turn: replace the full message list to maintain alternating roles
2427 messages =
2428 [
2429 new UserMessageParam { Content = userQuery },
2430 new AssistantMessageParam
2431 {
2432 Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
2433 }
2434 ];
2435 }
2462 // pause_turn: add the paused response as an assistant message, then continue
2463 // Request and response blocks are separate types: copy each block's JSON unchanged
2464 messages.Add(new AssistantMessageParam
2465 {
2466 Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
2467 });
24362468
2437 // Reached max continuations: return the last response
2469 // If the tools ran in a container, send its ID back so its files are kept
2470 if (response.Container is not null)
2471 {
2472 container = response.Container.ID;
2473 }
2474 } while (++requestCount < maxRequests);
2475
2476 // Still paused after maxRequests requests: return the last response
24382477 return response;
24392478 }
2479
2480 var response = await HandleServerToolConversation(
2481 client,
2482 "Use the code execution tool to find the 1,000th prime number.",
2483 [new CodeExecutionTool20250825()]);
2484 Console.WriteLine(response.StopReason?.Raw());
24402485 ```
24412486
24422487 ```go Go
from line 2489
24442489 client anthropic.Client,
24452490 userQuery string,
24462491 tools []anthropic.ToolUnionParam,
2447 maxContinuations int,
2492 maxRequests int,
24482493 ) (*anthropic.Message, error) {
2449 messages := []anthropic.MessageParam{anthropic.NewUserMessage(anthropic.NewTextBlock(userQuery))}
2494 messages := []anthropic.MessageParam{
2495 anthropic.NewUserMessage(anthropic.NewTextBlock(userQuery)),
2496 }
2497 var container anthropic.MessageCreateParamsContainerUnion
24502498 var response *anthropic.Message
24512499 var err error
24522500
2453 for range maxContinuations {
2501 for range maxRequests {
24542502 response, err = client.Messages.New(context.TODO(), anthropic.MessageNewParams{
24552503 Model: anthropic.ModelClaudeOpus5_5,
24562504 MaxTokens: 4096,
24572505 Messages: messages,
24582506 Tools: tools,
2507 Container: container,
24592508 })
24602509 if err != nil {
24612510 return nil, err
24622511 }
24632512
2464 if response.StopReason != "pause_turn" {
2465 // Claude finished processing: return the final response
2513 if response.StopReason != anthropic.StopReasonPauseTurn {
2514 // Not paused: return the response
24662515 return response, nil
24672516 }
24682517
2469 // pause_turn: replace the full message list to maintain alternating roles
2470 var contentParams []anthropic.ContentBlockParamUnion
2471 for _, block := range response.Content {
2472 contentParams = append(contentParams, block.ToParam())
2518 // pause_turn: add the paused response as an assistant message, then continue
2519 messages = append(messages, response.ToParam())
2520
2521 // If the tools ran in a container, send its ID back so its files are kept
2522 if response.Container.ID != "" {
2523 container.OfString = anthropic.String(response.Container.ID)
24732524 }
2474 messages = []anthropic.MessageParam{
2475 anthropic.NewUserMessage(anthropic.NewTextBlock(userQuery)),
2476 anthropic.NewAssistantMessage(contentParams...),
2477 }
24782525 }
24792526
2480 // Reached max continuations: return the last response
2527 // Still paused after maxRequests requests: return the last response
24812528 return response, nil
24822529 }
2530
2531 func main() {
2532 client := anthropic.NewClient()
2533
2534 response, err := handleServerToolConversation(
2535 client,
2536 "Use the code execution tool to find the 1,000th prime number.",
2537 []anthropic.ToolUnionParam{
2538 {OfCodeExecutionTool20250825: &anthropic.CodeExecutionTool20250825Param{}},
2539 },
2540 5,
2541 )
2542 if err != nil {
2543 log.Fatal(err)
2544 }
2545 fmt.Println(response.StopReason)
2546 }
24832547 ```
24842548
24852549 ```java Java
2486 static Message handleServerToolConversation(
2550 Message handleServerToolConversation(
24872551 AnthropicClient client,
24882552 String userQuery,
2489 List<Tool> tools,
2490 int maxContinuations
2553 List<ToolUnion> tools,
2554 int maxRequests
24912555 ) {
2556 var params = MessageCreateParams.builder()
2557 .model(Model.CLAUDE_OPUS_5_5)
2558 .maxTokens(4096L)
2559 .tools(tools)
2560 .addUserMessage(userQuery);
24922561 Message response = null;
24932562
2494 for (int i = 0; i < maxContinuations; i++) {
2495 // Rebuild the params each iteration so messages aren't accumulated
2496 MessageCreateParams.Builder params = MessageCreateParams.builder()
2497 .model(Model.CLAUDE_OPUS_5_5)
2498 .maxTokens(4096L)
2499 .addUserMessage(userQuery);
2500 tools.forEach(params::addTool);
2501 if (response != null) {
2502 params.addMessage(response);
2503 }
2504
2563 for (int request = 0; request < maxRequests; request++) {
25052564 response = client.messages().create(params.build());
25062565
2507 if (!response.stopReason().map(StopReason.PAUSE_TURN::equals).orElse(false)) {
2508 // Claude finished processing: return the final response
2566 boolean paused = response.stopReason().filter(StopReason.PAUSE_TURN::equals).isPresent();
2567 if (!paused) {
2568 // Not paused: return the response
25092569 return response;
25102570 }
2511 // pause_turn: loop again and send the response back
2571
2572 // pause_turn: add the paused response as an assistant message, then continue
2573 params.addMessage(response);
2574
2575 // If the tools ran in a container, send its ID back so its files are kept
2576 response.container().ifPresent(container -> params.container(container.id()));
25122577 }
25132578
2514 // Reached max continuations: return the last response
2579 // Still paused after maxRequests requests: return the last response
25152580 return response;
25162581 }
2582
2583 void main() {
2584 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
2585
2586 Message response = handleServerToolConversation(
2587 client,
2588 "Use the code execution tool to find the 1,000th prime number.",
2589 List.of(ToolUnion.ofCodeExecutionTool20250825(CodeExecutionTool20250825.builder().build())),
2590 5
2591 );
2592 response.stopReason().ifPresent(IO::println);
2593 }
25172594 ```
25182595
25192596 ```php PHP
2597 $client = new Client();
2598
25202599 function handle_server_tool_conversation(
25212600 Client $client,
25222601 string $userQuery,
25232602 array $tools,
2524 int $maxContinuations = 5
2525 ) {
2603 int $maxRequests = 5,
2604 ): Message {
25262605 $messages = [['role' => 'user', 'content' => $userQuery]];
2527 $response = null;
2606 $containerId = null;
2607 $requestCount = 0;
25282608
2529 for ($i = 0; $i < $maxContinuations; $i++) {
2609 do {
25302610 $response = $client->messages->create(
25312611 maxTokens: 4096,
25322612 messages: $messages,
2533 model: 'claude-opus-5-5',
2613 model: Model::CLAUDE_OPUS_5_5,
25342614 tools: $tools,
2615 container: $containerId,
25352616 );
25362617
2537 if ($response->stopReason !== 'pause_turn') {
2538 // Claude finished processing: return the final response
2618 if ($response->stopReason !== StopReason::PAUSE_TURN->value) {
2619 // Not paused: return the response
25392620 return $response;
25402621 }
25412622
2542 // pause_turn: replace the full message list to maintain alternating roles
2543 $messages = [
2544 ['role' => 'user', 'content' => $userQuery],
2545 ['role' => 'assistant', 'content' => $response->content],
2546 ];
2547 }
2623 // pause_turn: add the paused response as an assistant message, then continue
2624 $messages[] = ['role' => 'assistant', 'content' => $response->content];
25482625
2549 // Reached max continuations: return the last response
2626 // If the tools ran in a container, send its ID back so its files are kept
2627 $containerId = $response->container->id ?? $containerId;
2628 } while (++$requestCount < $maxRequests);
2629
2630 // Still paused after $maxRequests requests: return the last response
25502631 return $response;
25512632 }
2633
2634 $response = handle_server_tool_conversation(
2635 $client,
2636 'Use the code execution tool to find the 1,000th prime number.',
2637 [new CodeExecutionTool20250825()],
2638 );
2639 echo $response->stopReason, PHP_EOL;
25522640 ```
25532641
25542642 ```ruby Ruby
2555 def handle_server_tool_conversation(client, user_query, tools, max_continuations: 5)
2643 client = Anthropic::Client.new
2644
2645 def handle_server_tool_conversation(client, user_query, tools, max_requests: 5)
25562646 messages = [{ role: "user", content: user_query }]
2647 container_id = nil
25572648 response = nil
25582649
2559 max_continuations.times do
2650 max_requests.times do
25602651 response = client.messages.create(
2561 model: "claude-opus-5-5",
2652 model: Anthropic::Model::CLAUDE_OPUS_5_5,
25622653 max_tokens: 4096,
2563 messages: messages,
2564 tools: tools
2654 messages:,
2655 tools:,
2656 container: container_id
25652657 )
25662658
2567 # Claude finished processing: return the final response
2659 # Not paused: return the response
25682660 return response unless response.stop_reason == :pause_turn
25692661
2570 # pause_turn: replace the full message list to maintain alternating roles
2571 messages = [
2572 { role: "user", content: user_query },
2573 { role: "assistant", content: response.content }
2574 ]
2662 # pause_turn: add the paused response as an assistant message, then continue
2663 messages << { role: "assistant", content: response.content }
2664
2665 # If the tools ran in a container, send its ID back so its files are kept
2666 container_id = response.container&.id || container_id
25752667 end
25762668
2577 # Reached max continuations: return the last response
2669 # Still paused after max_requests requests: return the last response
25782670 response
25792671 end
2672
2673 response = handle_server_tool_conversation(
2674 client,
2675 "Use the code execution tool to find the 1,000th prime number.",
2676 [Anthropic::CodeExecutionTool20250825.new]
2677 )
2678 puts response.stop_reason
25802679 ```
25812680</CodeGroup>
2681
2682The function returns the last response, which holds only the final part of the turn. To show the whole turn or to continue the conversation, keep the paused responses as well.
25822683
25832684## Stop reasons versus errors
25842685
No line in this hunk matches that.