Part of the Build Your Own Coding Agent tutorial. One issue = one chapter (chapters/05-tools.md) plus its examples/05-tools/ samples.
Tools are how your agent reaches outside the model: reading files, calling APIs, running queries. This chapter covers the core tool-use protocol of the Messages API - you declare tools, the model decides when to call one and returns a tool_use block, your code executes it, and you feed a tool_result block back so the model can continue. The model never runs your code; it only emits structured requests and reads structured results, and you own the loop in between. Getting this single round-trip right is the foundation for every multi-tool workflow in the chapters that follow.
Goal (1 sentence): Master the core tool-use round-trip: declare a tool, detect a tool_use block, execute it, and return a tool_result.
After this chapter you can
- Define a tool with
name, description, and a JSON Schema input_schema, then detect stop_reason: "tool_use", extract the block, and dispatch to a typed handler.
- Close the loop by returning a
tool_result block that echoes the tool_use_id back to the model, including error results with is_error: true so the model can recover.
- Write descriptions and schemas that make the model pick the right tool ("call this when..." phrasing, per-property descriptions,
enum for fixed value sets), and steer tool selection with tool_choice (auto, any, tool, none) and disable_parallel_tool_use.
What to cover (ONE paragraph, not a list)
Introduce the tool-use contract: a tool has name, description, and an input_schema (JSON Schema with type, properties, required, and enum for fixed value sets). When the model decides to call a tool it returns a tool_use content block with id, name, and input (already a parsed object via the SDK - never raw-string-match the serialized JSON); your code reads response.content for text and tool_use blocks, checks stop_reason: "tool_use", appends the assistant turn verbatim, dispatches block.name to a handler, and sends back a user turn whose content is one or more tool_result blocks, each echoing tool_use_id exactly - every tool_use in a turn needs a matching tool_result. Cover argument validation and error reporting via is_error: true and an informative message so the model can recover or retry rather than throwing, then close with writing effective tool descriptions ("call this when..." phrasing, per-property descriptions, enum for disambiguation) and the tool_choice modes that steer or force a specific tool. Use Anthropic.Tool, Anthropic.ToolUseBlock, and Anthropic.ToolResultBlockParam SDK types throughout - not hand-rolled interfaces.
Going deeper (optional asides - keep OFF the main line)
Out of scope (defer - do NOT preview)
- Multi-tool workflows and parallel tool calls beyond a single round-trip (later chapters).
Code samples - examples/05-tools/
Must-keep for a beginner (floor - never cut for brevity)
- The run command for the first sample.
- "Never hardcode your key; it comes from the environment" (once, in prose).
- Anything a beginner cannot infer from the code (e.g. Bun auto-loads
.env, no loader).
- The one genuinely non-obvious gotcha:
block.input arrives as a parsed object from the SDK - never raw-string-match the serialized JSON.
Friendliness floor (never cut - terse is not friendly)
- The chapter addresses the reader as "you", never "the user" or "one".
- The intro AND at least one section open with a warm, second-person sentence.
Key APIs (flat list, reference only - NOT a coverage checklist)
client.messages.create, tools, name, description, input_schema, tool_use (id, name, input), stop_reason: "tool_use", tool_result (tool_use_id, content, is_error), tool_choice, disable_parallel_tool_use, Anthropic.Tool, Anthropic.ToolUseBlock, Anthropic.ToolResultBlockParam
Prerequisites
Chapters 1-2 (and Chapter 4 helps). Standalone; needs ANTHROPIC_API_KEY.
Definition of done
Part of the Build Your Own Coding Agent tutorial. One issue = one chapter (
chapters/05-tools.md) plus itsexamples/05-tools/samples.Tools are how your agent reaches outside the model: reading files, calling APIs, running queries. This chapter covers the core tool-use protocol of the Messages API - you declare tools, the model decides when to call one and returns a
tool_useblock, your code executes it, and you feed atool_resultblock back so the model can continue. The model never runs your code; it only emits structured requests and reads structured results, and you own the loop in between. Getting this single round-trip right is the foundation for every multi-tool workflow in the chapters that follow.Goal (1 sentence): Master the core tool-use round-trip: declare a tool, detect a
tool_useblock, execute it, and return atool_result.After this chapter you can
name,description, and a JSON Schemainput_schema, then detectstop_reason: "tool_use", extract the block, and dispatch to a typed handler.tool_resultblock that echoes thetool_use_idback to the model, including error results withis_error: trueso the model can recover.enumfor fixed value sets), and steer tool selection withtool_choice(auto,any,tool,none) anddisable_parallel_tool_use.What to cover (ONE paragraph, not a list)
Introduce the tool-use contract: a tool has
name,description, and aninput_schema(JSON Schema withtype,properties,required, andenumfor fixed value sets). When the model decides to call a tool it returns atool_usecontent block withid,name, andinput(already a parsed object via the SDK - never raw-string-match the serialized JSON); your code readsresponse.contentfortextandtool_useblocks, checksstop_reason: "tool_use", appends the assistant turn verbatim, dispatchesblock.nameto a handler, and sends back a user turn whosecontentis one or moretool_resultblocks, each echoingtool_use_idexactly - everytool_usein a turn needs a matchingtool_result. Cover argument validation and error reporting viais_error: trueand an informative message so the model can recover or retry rather than throwing, then close with writing effective tool descriptions ("call this when..." phrasing, per-property descriptions,enumfor disambiguation) and thetool_choicemodes that steer or force a specific tool. UseAnthropic.Tool,Anthropic.ToolUseBlock, andAnthropic.ToolResultBlockParamSDK types throughout - not hand-rolled interfaces.Going deeper (optional asides - keep OFF the main line)
Out of scope (defer - do NOT preview)
Code samples - examples/05-tools/
define-tool.ts- declare aget_weathertool and inspect the returnedtool_useblock.single-tool-loop.ts- full create ->tool_use-> execute ->tool_result-> answer.dispatch-handlers.ts- mapblock.nameto typed handlers, parseblock.input.tool-errors.ts- validate args and returnis_error: trueresults.tool-choice.ts- compareauto,any,{ type: "tool", name },disable_parallel_tool_use.Must-keep for a beginner (floor - never cut for brevity)
.env, no loader).block.inputarrives as a parsed object from the SDK - never raw-string-match the serialized JSON.Friendliness floor (never cut - terse is not friendly)
Key APIs (flat list, reference only - NOT a coverage checklist)
client.messages.create,tools,name,description,input_schema,tool_use(id,name,input),stop_reason: "tool_use",tool_result(tool_use_id,content,is_error),tool_choice,disable_parallel_tool_use,Anthropic.Tool,Anthropic.ToolUseBlock,Anthropic.ToolResultBlockParamPrerequisites
Chapters 1-2 (and Chapter 4 helps). Standalone; needs
ANTHROPIC_API_KEY.Definition of done
chapters/05-tools.md, <=120 lines, <=4 main-line H2s plus an optional "What's next" closer (pastewc -lANDgrep -c '^## 'in the PR).bun run, imported via<<< @/examples/05-tools/file.ts, <=35 lines, comment:code <=0.30.@anthropic-ai/sdksurface, verified against current docs; ASCII punctuation only.README.mdand the.vitepress/config.tssidebar;bun x vitepress buildpasses.