build-a-tool-using-agent changedagents-and-tools/tool-use/build-a-tool-using-agent
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+61added
Lines−61removed
From line
68
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits14to this page, all time
The whole hunk
from line 68, old and new numbered
/
from line 68
6868 }
6969 ]
7070
71 # Send the user's request along with the tool definition. Claude decides
71 # Send the user's request along with the tool definition. Claude determines
7272 # whether to call the tool based on the request and the tool description.
7373 response = client.messages.create(
7474 model="claude-opus-5-5",
from line 87
8787 # and the content array contains a tool_use block alongside any text.
8888 print(f"stop_reason: {response.stop_reason}")
8989
90 # Find the tool_use block. A response may contain text blocks before the
90 # Find the tool_use block. A response might contain text blocks before the
9191 # tool_use block, so scan the content array rather than assuming position.
9292 tool_use = next(block for block in response.content if block.type == "tool_use")
9393 print(f"Tool: {tool_use.name}")
9494 print(f"Input: {tool_use.input}")
9595
96 # Execute the tool. In a real system this would call your calendar API.
96 # Run the tool. In a real system this would call your calendar API.
9797 # Here the result is hardcoded to keep the example self-contained.
9898 result = {"event_id": "evt_123", "status": "created"}
9999
100100 # Send the result back. The tool_result block goes in a user message and
101 # its tool_use_id must match the id from the tool_use block above. The
101 # its tool_use_id must match the ID from the earlier tool_use block. The
102102 # assistant's previous response is included so Claude has the full history.
103103 followup = client.messages.create(
104104 model="claude-opus-5-5",
from line 124
124124 ],
125125 )
126126
127 # With the tool result in hand, Claude produces a final natural-language
127 # With the tool result, Claude produces a final natural-language
128128 # answer and stop_reason becomes "end_turn".
129129 print(f"stop_reason: {followup.stop_reason}")
130130 final_text = next(block for block in followup.content if block.type == "text")
from line 170
170170 }
171171 ];
172172
173 // Send the user's request along with the tool definition. Claude decides
173 // Send the user's request along with the tool definition. Claude determines
174174 // whether to call the tool based on the request and the tool description.
175175 const response = await client.messages.create({
176176 model: "claude-opus-5-5",
from line 190
190190 // and the content array contains a tool_use block alongside any text.
191191 console.log(`stop_reason: ${response.stop_reason}`);
192192
193 // Find the tool_use block. A response may contain text blocks before the
193 // Find the tool_use block. A response might contain text blocks before the
194194 // tool_use block, so scan the content array rather than assuming position.
195195 const toolUse = response.content.find((block) => block.type === "tool_use")!;
196196 console.log(`Tool: ${toolUse.name}`);
197197 console.log(`Input: ${JSON.stringify(toolUse.input)}`);
198198
199 // Execute the tool. In a real system this would call your calendar API.
199 // Run the tool. In a real system this would call your calendar API.
200200 // Here the result is hardcoded to keep the example self-contained.
201201 const result = { event_id: "evt_123", status: "created" };
202202
203203 // Send the result back. The tool_result block goes in a user message and
204 // its tool_use_id must match the id from the tool_use block above. The
204 // its tool_use_id must match the ID from the earlier tool_use block. The
205205 // assistant's previous response is included so Claude has the full history.
206206 const followup = await client.messages.create({
207207 model: "claude-opus-5-5",
from line 228
228228 ]
229229 });
230230
231 // With the tool result in hand, Claude produces a final natural-language
231 // With the tool result, Claude produces a final natural-language
232232 // answer and stop_reason becomes "end_turn".
233233 console.log(`stop_reason: ${followup.stop_reason}`);
234234 for (const block of followup.content) {
from line 289
289289 }),
290290 ];
291291
292 // Ask for at most one tool call per turn so the single-turn flow below
293 // stays predictable.
292 // Ask for at most one tool call in each turn so the single-turn flow
293 // that follows stays predictable.
294294 var toolChoice = new ToolChoice(new ToolChoiceAuto { DisableParallelToolUse = true });
295295
296296 const string userPrompt =
297297 "Schedule a 30-minute sync with [email protected] and [email protected] on Monday, March 30, 2026 at 10am.";
298298
299 // Send the user's request along with the tool definition. Claude decides
299 // Send the user's request along with the tool definition. Claude determines
300300 // whether to call the tool based on the request and the tool description.
301301 var response = await client.Messages.Create(new MessageCreateParams
302302 {
from line 311
311311 // and the content array contains a tool_use block alongside any text.
312312 Console.WriteLine($"stop_reason: {response.StopReason?.Raw()}");
313313
314 // Find the tool_use block. A response may contain text blocks before the
314 // Find the tool_use block. A response might contain text blocks before the
315315 // tool_use block, so scan the content array rather than assuming position.
316316 ToolUseBlock? toolUse = null;
317317 foreach (var block in response.Content)
from line 325
325325 Console.WriteLine($"Tool: {toolUse!.Name}");
326326 Console.WriteLine($"Input: {JsonSerializer.Serialize(toolUse.Input)}");
327327
328 // Execute the tool. In a real system this would call your calendar API.
328 // Run the tool. In a real system this would call your calendar API.
329329 // Here the result is hardcoded to keep the example self-contained.
330330 var result = """{"event_id": "evt_123", "status": "created"}""";
331331
332332 // Send the result back. The tool_result block goes in a user message and
333 // its tool_use_id must match the id from the tool_use block above. The
333 // its tool_use_id must match the ID from the earlier tool_use block. The
334334 // assistant's previous response is included so Claude has the full history.
335335 List<ContentBlockParam> toolResults =
336336 [
from line 355
355355 ],
356356 });
357357
358 // With the tool result in hand, Claude produces a final natural-language
358 // With the tool result, Claude produces a final natural-language
359359 // answer and stop_reason becomes "end_turn".
360360 Console.WriteLine($"stop_reason: {followup.StopReason?.Raw()}");
361361 foreach (var block in followup.Content)
from line 415
415415 }},
416416 }
417417
418 // Ask for at most one tool call per turn so the single-turn flow below
419 // stays predictable.
418 // Ask for at most one tool call in each turn so the single-turn flow
419 // that follows stays predictable.
420420 toolChoice := anthropic.ToolChoiceUnionParam{
421421 OfAuto: &anthropic.ToolChoiceAutoParam{DisableParallelToolUse: anthropic.Bool(true)},
422422 }
from line 425
425425 "Schedule a 30-minute sync with [email protected] and [email protected] on Monday, March 30, 2026 at 10am.",
426426 ))
427427
428 // Send the user's request along with the tool definition. Claude decides
428 // Send the user's request along with the tool definition. Claude determines
429429 // whether to call the tool based on the request and the tool description.
430430 response, err := client.Messages.New(ctx, anthropic.MessageNewParams{
431431 Model: anthropic.ModelClaudeOpus5_5,
from line 442
442442 // and the content array contains a tool_use block alongside any text.
443443 fmt.Printf("stop_reason: %s\n", response.StopReason)
444444
445 // Find the tool_use block. A response may contain text blocks before the
445 // Find the tool_use block. A response might contain text blocks before the
446446 // tool_use block, so scan the content array rather than assuming position.
447447 var toolUse anthropic.ContentBlockUnion
448448 for _, block := range response.Content {
from line 454
454454 fmt.Printf("Tool: %s\n", toolUse.Name)
455455 fmt.Printf("Input: %s\n", string(toolUse.Input))
456456
457 // Execute the tool. In a real system this would call your calendar API.
457 // Run the tool. In a real system this would call your calendar API.
458458 // Here the result is hardcoded to keep the example self-contained.
459459 result := `{"event_id": "evt_123", "status": "created"}`
460460
461461 // Send the result back. The tool_result block goes in a user message and
462 // its tool_use_id must match the id from the tool_use block above. The
462 // its tool_use_id must match the ID from the earlier tool_use block. The
463463 // assistant's previous response is included so Claude has the full history.
464464 var assistantContent []anthropic.ContentBlockParamUnion
465465 for _, block := range response.Content {
from line 481
481481 log.Fatal(err)
482482 }
483483
484 // With the tool result in hand, Claude produces a final natural-language
484 // With the tool result, Claude produces a final natural-language
485485 // answer and stop_reason becomes "end_turn".
486486 fmt.Printf("stop_reason: %s\n", followup.StopReason)
487487 for _, block := range followup.Content {
from line 542
542542 .build())
543543 .build();
544544
545 // Ask for at most one tool call per turn so the single-turn flow below
546 // stays predictable.
545 // Ask for at most one tool call in each turn so the single-turn flow
546 // that follows stays predictable.
547547 ToolChoiceAuto toolChoice = ToolChoiceAuto.builder()
548548 .disableParallelToolUse(true)
549549 .build();
from line 551
551551 String userPrompt =
552552 "Schedule a 30-minute sync with [email protected] and [email protected] on Monday, March 30, 2026 at 10am.";
553553
554 // Send the user's request along with the tool definition. Claude decides
554 // Send the user's request along with the tool definition. Claude determines
555555 // whether to call the tool based on the request and the tool description.
556556 Message response = client.messages().create(MessageCreateParams.builder()
557557 .model(Model.CLAUDE_OPUS_5_5)
from line 565
565565 // and the content array contains a tool_use block alongside any text.
566566 IO.println("stop_reason: " + response.stopReason().orElse(null));
567567
568 // Find the tool_use block. A response may contain text blocks before the
568 // Find the tool_use block. A response might contain text blocks before the
569569 // tool_use block, so scan the content array rather than assuming position.
570570 ToolUseBlock toolUse = response.content().stream()
571571 .flatMap(block -> block.toolUse().stream())
from line 574
574574 IO.println("Tool: " + toolUse.name());
575575 IO.println("Input: " + toolUse._input());
576576
577 // Execute the tool. In a real system this would call your calendar API.
577 // Run the tool. In a real system this would call your calendar API.
578578 // Here the result is hardcoded to keep the example self-contained.
579579 String result = "{\"event_id\": \"evt_123\", \"status\": \"created\"}";
580580
581581 // Send the result back. The tool_result block goes in a user message and
582 // its tool_use_id must match the id from the tool_use block above. The
582 // its tool_use_id must match the ID from the earlier tool_use block. The
583583 // assistant's previous response is included so Claude has the full history.
584584 Message followup = client.messages().create(MessageCreateParams.builder()
585585 .model(Model.CLAUDE_OPUS_5_5)
from line 595
595595 .build())))
596596 .build());
597597
598 // With the tool result in hand, Claude produces a final natural-language
598 // With the tool result, Claude produces a final natural-language
599599 // answer and stop_reason becomes "end_turn".
600600 IO.println("stop_reason: " + followup.stopReason().orElse(null));
601601 followup.content().stream()
from line 651
651651 'content' => 'Schedule a 30-minute sync with [email protected] and [email protected] on Monday, March 30, 2026 at 10am.',
652652 ];
653653
654 // Ask for at most one tool call per turn so the single-turn flow below
655 // stays predictable.
654 // Ask for at most one tool call in each turn so the single-turn flow
655 // that follows stays predictable.
656656 $toolChoice = ToolChoiceAuto::with(disableParallelToolUse: true);
657657
658 // Send the user's request along with the tool definition. Claude decides
658 // Send the user's request along with the tool definition. Claude determines
659659 // whether to call the tool based on the request and the tool description.
660660 $response = $client->messages->create(
661661 model: 'claude-opus-5-5',
from line 669
669669 // and the content array contains a tool_use block alongside any text.
670670 printf("stop_reason: %s\n", $response->stopReason);
671671
672 // Find the tool_use block. A response may contain text blocks before the
672 // Find the tool_use block. A response might contain text blocks before the
673673 // tool_use block, so scan the content array rather than assuming position.
674674 $toolUse = null;
675675 foreach ($response->content as $block) {
from line 681
681681 printf("Tool: %s\n", $toolUse->name);
682682 printf("Input: %s\n", json_encode($toolUse->input));
683683
684 // Execute the tool. In a real system this would call your calendar API.
684 // Run the tool. In a real system this would call your calendar API.
685685 // Here the result is hardcoded to keep the example self-contained.
686686 $result = ['event_id' => 'evt_123', 'status' => 'created'];
687687
688688 // Send the result back. The tool_result block goes in a user message and
689 // its tool_use_id must match the id from the tool_use block above. The
689 // its tool_use_id must match the ID from the earlier tool_use block. The
690690 // assistant's previous response is included so Claude has the full history.
691691 $followup = $client->messages->create(
692692 model: 'claude-opus-5-5',
from line 709
709709 ],
710710 );
711711
712 // With the tool result in hand, Claude produces a final natural-language
712 // With the tool result, Claude produces a final natural-language
713713 // answer and stop_reason becomes "end_turn".
714714 printf("stop_reason: %s\n", $followup->stopReason);
715715 foreach ($followup->content as $block) {
from line 763
763763 content: "Schedule a 30-minute sync with [email protected] and [email protected] on Monday, March 30, 2026 at 10am."
764764 }
765765
766 # Ask for at most one tool call per turn so the single-turn flow below
767 # stays predictable.
766 # Ask for at most one tool call in each turn so the single-turn flow
767 # that follows stays predictable.
768768 tool_choice = {type: "auto", disable_parallel_tool_use: true}
769769
770 # Send the user's request along with the tool definition. Claude decides
770 # Send the user's request along with the tool definition. Claude determines
771771 # whether to call the tool based on the request and the tool description.
772772 response = client.messages.create(
773773 model: Anthropic::Model::CLAUDE_OPUS_5_5,
from line 781
781781 # and the content array contains a tool_use block alongside any text.
782782 puts "stop_reason: #{response.stop_reason}"
783783
784 # Find the tool_use block. A response may contain text blocks before the
784 # Find the tool_use block. A response might contain text blocks before the
785785 # tool_use block, so scan the content array rather than assuming position.
786786 tool_use = response.content.find { |block| block.type == :tool_use }
787787 puts "Tool: #{tool_use.name}"
788788 puts "Input: #{tool_use.input}"
789789
790 # Execute the tool. In a real system this would call your calendar API.
790 # Run the tool. In a real system this would call your calendar API.
791791 # Here the result is hardcoded to keep the example self-contained.
792792 result = {event_id: "evt_123", status: "created"}
793793
794794 # Send the result back. The tool_result block goes in a user message and
795 # its tool_use_id must match the id from the tool_use block above. The
795 # its tool_use_id must match the ID from the earlier tool_use block. The
796796 # assistant's previous response is included so Claude has the full history.
797797 followup = client.messages.create(
798798 model: Anthropic::Model::CLAUDE_OPUS_5_5,
from line 815
815815 ]
816816 )
817817
818 # With the tool result in hand, Claude produces a final natural-language
818 # With the tool result, Claude produces a final natural-language
819819 # answer and stop_reason becomes "end_turn".
820820 puts "stop_reason: #{followup.stop_reason}"
821821 followup.content.each do |block|
from line 3327
33273327 </CodeGroupItem>
33283328
33293329 ```python Python
3330 # Ring 5: The Tool Runner SDK abstraction.
3330 # Ring 5: The tool runner SDK abstraction.
33313331
33323332 import json
33333333
from line 3389
33893389 ```
33903390
33913391 ```typescript TypeScript
3392 // Ring 5: The Tool Runner SDK abstraction.
3392 // Ring 5: The tool runner SDK abstraction.
33933393
33943394 import Anthropic from "@anthropic-ai/sdk";
33953395 import { betaZodTool } from "@anthropic-ai/sdk/helpers/beta/zod";
from line 3458
34583458 ```
34593459
34603460 ```csharp C#
3461 // Ring 5: The Tool Runner SDK abstraction.
3461 // Ring 5: The tool runner SDK abstraction.
34623462
34633463 using System;
34643464 using System.Collections.Generic;
from line 3577
35773577 ```
35783578
35793579 ```go Go
3580 // Ring 5: The Tool Runner SDK abstraction.
3580 // Ring 5: The tool runner SDK abstraction.
35813581
35823582 package main
35833583
from line 3682
36823682 ```
36833683
36843684 ```java Java
3685 // Ring 5: The Tool Runner SDK abstraction.
3685 // Ring 5: The tool runner SDK abstraction.
36863686
36873687 import com.anthropic.client.AnthropicClient;
36883688 import com.anthropic.client.okhttp.AnthropicOkHttpClient;
from line 3738
37383738 // The runner calls the API, runs requested tools, and feeds results back
37393739 // until Claude produces a final answer.
37403740 BetaToolRunner runner = client.beta()
3741 .messages()
3742 .toolRunner(MessageCreateParams.builder()
3743 .model(Model.CLAUDE_OPUS_5_5)
3744 .maxTokens(1024)
3745 .addBeta("structured-outputs-2025-11-13")
3746 .addUserMessage("Check what I have on Monday, March 30, 2026, then schedule a one-hour planning session that day that avoids any conflicts.")
3747 .addTool(CreateCalendarEvent.class)
3748 .addTool(ListCalendarEvents.class)
3749 .build());
3741 .messages()
3742 .toolRunner(MessageCreateParams.builder()
3743 .model(Model.CLAUDE_OPUS_5_5)
3744 .maxTokens(1024)
3745 .addBeta("structured-outputs-2025-11-13")
3746 .addUserMessage("Check what I have on Monday, March 30, 2026, then schedule a one-hour planning session that day that avoids any conflicts.")
3747 .addTool(CreateCalendarEvent.class)
3748 .addTool(ListCalendarEvents.class)
3749 .build());
37503750
37513751 BetaMessage finalMessage = null;
37523752 for (BetaMessage message : runner) {
from line 3762
37623762 ```php PHP
37633763 <?php
37643764
3765 // Ring 5: The Tool Runner SDK abstraction.
3765 // Ring 5: The tool runner SDK abstraction.
37663766
37673767 use Anthropic\Client;
37683768 use Anthropic\Lib\Tools\BetaRunnableTool;
from line 3856
38563856 ```
38573857
38583858 ```ruby Ruby
3859 # Ring 5: The Tool Runner SDK abstraction.
3859 # Ring 5: The tool runner SDK abstraction.
38603860
38613861 require "anthropic"
38623862
No line in this hunk matches that.