Introduction: From Thinking to Acting

In the previous lesson, you learned how to configure your agent's fundamental behavior using an options object — selecting models, shaping personality through system prompts, and limiting reasoning cycles. These settings control how the agent thinks and communicates, but they don't give the agent the ability to act on your environment. This is where tools come in — they transform your agent from a conversational assistant into an active participant that can search the web, read and write files, and execute commands. In this lesson, you'll learn how to enable built-in tools, understand the new message types that represent tool usage, and configure permissions that control how the agent executes these actions.

Discovering Built-in Tools

The Claude Agent SDK provides multiple built-in tools that give your agent diverse capabilities — from web search and file manipulation to task management and Jupyter notebook editing. While this comprehensive toolkit enables sophisticated workflows, this lesson focuses on five foundational tools that cover the most common use cases: searching the web, reading files, writing files, and executing commands. Understanding these core tools will give you a solid foundation for building practical agents, and you can explore the additional tools as your needs grow.

The SDK includes the following built-in tools:

  • Task — Create a sub-task or subagent with a description/prompt
  • Bash — Execute a shell command in the working directory
  • Edit — Modify an existing file by replacing strings
  • Read — Read contents of a file (text or image)
  • Write — Write new content to a file
  • Glob — Find files matching a glob pattern
  • Grep — Search within files for patterns (regex, filters, etc.)
  • NotebookEdit — Edit a Jupyter notebook cell (code or markdown)
  • WebFetch — Fetch a URL and run a prompt on the fetched content
  • WebSearch — Perform a web search query and return results
  • TodoWrite — Write a set of to-do items and get statistics
  • — Retrieve output/status of a background shell command
WebSearch: Finding Information on the Internet

WebSearch allows the agent to search the internet for current information. When the agent uses this tool, it submits a search query and receives a list of relevant web pages with titles, URLs, and brief descriptions. This tool is essential for tasks that require up-to-date information that wasn't in the model's training data, such as finding recent documentation, checking current events, or discovering resources.

WebFetch: Retrieving Content from URLs

WebFetch retrieves the full content from specific URLs. While WebSearch finds relevant pages, WebFetch actually reads the content from those pages so the agent can analyze, summarize, or extract information. This tool is automatically enabled when you enable WebSearch, since searching without the ability to read results would be incomplete. The agent can optionally provide a prompt parameter to focus on specific information within the fetched content.

Bash: Executing Shell Commands

Bash executes shell commands in your terminal. This tool gives the agent the ability to run any command you could run yourself — checking if directories exist, creating folders, running tests, starting servers, or executing scripts. The agent provides both the command to execute and a description of what it's trying to accomplish, which helps you understand the agent's reasoning when reviewing tool usage.

Read: Accessing Files from Your Filesystem

Read accesses files from your filesystem. The agent can read the contents of any file within its working directory, which is useful for analyzing code, reviewing configuration files, or understanding project structure. This tool respects the working directory you configure, preventing the agent from accessing files outside your intended scope.

Write: Creating and Modifying Files

Write creates or modifies files on your filesystem. The agent can write new files or overwrite existing ones, which is essential for tasks like generating code, creating documentation, or saving analysis results. Like the Read tool, Write operations are scoped to the configured working directory for safety. These five tools work together to enable complex workflows where the agent can search for information, read existing files, and create new content, all in response to a single prompt.

Enabling Tools with allowedTools

To give your agent access to tools, you use the allowedTools parameter in your options object. This parameter accepts an array of tool names as strings, and only the tools you explicitly list will be available to the agent during that query. This explicit allowlist approach gives you fine-grained control over what actions the agent can perform, which is important for security and cost management.

The code creates a configuration that enables all five built-in tools. The agent can now search the web, fetch content from URLs, execute bash commands, read files, and write files. Note that even though WebFetch is automatically enabled when you enable WebSearch, it's good practice to list it explicitly in your allowedTools array to make your configuration clear and self-documenting. The Options type from the SDK ensures your configuration matches what the agent runtime expects.

You don't have to enable all tools for every task — if you're building a simple documentation search agent, you might only enable WebSearch and WebFetch, while a code analysis tool might enable Read and Bash but exclude Write to prevent modifications.

Configuring Permission Mode

Every tool call needs permission before the agent can use it. The SDK gives you two ways to grant that permission:

  1. allowedTools – which tools the agent is allowed to call.
  2. permissionMode – extra rules that can relax or tighten permissions for certain kinds of tools.

In this lesson, we'll focus on one of them: acceptEdits.

With permissionMode: "acceptEdits", the SDK automatically approves any tool that edits files (such as Write and Edit), even if those tools are not explicitly listed in allowedTools. This is why, in practice, you may see Claude successfully edit files after turning on acceptEdits even when Write or Edit are missing from the allow list.

Other modes exist (default, , ), but for this course, we'll stick with as our main example.

Setting the Working Directory

Before we let the agent edit files or run commands, we need to tell it where in our project it should work. That's what the cwd (current working directory) option does.

When you call query() with the Claude Agent SDK, it starts a Claude Code process that actually runs tools like Bash, Read, and Write.

  • By default, that process uses the current working directory of your Node.js process (the folder you run node ... from), not necessarily the folder where your script file lives.
  • The cwd option lets you override this and say, "Always start here."

From the cwd folder:

  • Bash commands run as if you had cd'd into cwd.
  • File tools resolve relative paths (like project/my_file.md) starting from cwd.

The model still decides which paths to use. If it picks an absolute path such as /project/my_file.md, that path starts at the filesystem root and ignores cwd — which is why you might see a first attempt fail from /... and then a second attempt succeed once it finds the file under your actual project directory.

To make sure the working directory always follows the script (even if you move the file to another folder), you can set based on the script's location. In TypeScript ES modules, this requires a bit of helper code since there's no built-in variable:

New Message Block Types for Tool Use

When you enable tools, the streaming messages you receive from query() include new block types that represent tool usage. You're already familiar with text blocks inside assistant messages — these contain the agent's text responses. Now you'll also encounter two new block types that use TypeScript's discriminated union pattern:

  • Tool use blocks — Appear in assistant message content when the agent decides to call a tool. These blocks have type: "tool_use" and represent the agent's intention to use a tool — they contain the tool name and the input parameters the agent wants to pass to that tool. The block doesn't contain the result of the tool execution; it only shows what the agent is trying to do. Each tool use block has three key properties: name (the tool being called), input (an object of parameters), and id (a unique identifier for this specific tool call).

  • Tool result blocks — Appear in user message content after a tool executes. These blocks have type: "tool_result" and contain the output from the tool execution — the search results from WebSearch, the file contents from Read, the command output from Bash, or a success confirmation from Write. The block includes the tool call ID (linking it back to the corresponding tool use block), the content (the actual result), and metadata about whether the execution succeeded or failed.

TypeScript uses the type property as a discriminator to distinguish between different block types. By checking block.type === "tool_use" or block.type === "tool_result", TypeScript can narrow the type and give you access to the specific properties of each block type. The streaming pattern creates a natural conversation flow where the agent sends a tool request, the system executes it and returns results, then the agent analyzes those results and potentially calls more tools until the task is complete.

Inspecting Tool Calls in Assistant Messages

To observe which tools your agent is using, you need to check for tool use blocks within the assistant message content. Each assistant message can contain multiple blocks — some might be text blocks with explanatory text, and others might be tool use blocks representing tool calls. By iterating through the content blocks and checking their type property, you can see exactly when and how the agent decides to use tools.

The code uses a switch statement to handle different message types. When it encounters an assistant message (message.type === "assistant"), it iterates through the content blocks in message.message.content. For text blocks (block.type === "text"), it prints the agent's text response with a speech bubble emoji. For tool use blocks (block.type === "tool_use"), it prints the tool name and shows a preview of the input parameters. The block.input is an object where keys are parameter names and values are the arguments the agent wants to pass to the tool. For example, a WebSearch tool call might have {query: "Claude Agent SDK documentation"}, while a Write tool call might have . The code truncates long values to 30 characters to keep the output readable, since tool inputs can contain large amounts of text. TypeScript's discriminated union pattern ensures type safety — once you check , TypeScript knows that and are available. Now let's see how to capture the results that come back from these tool executions.

Reading Tool Results from User Messages

After the agent calls a tool, the system executes that tool and returns the result in a user message containing a tool result block. To see what happened during tool execution, you need to check for these blocks in user messages. The result block contains the tool's output, which could be search results, file contents, command output, or a simple success confirmation.

The code adds a case for user messages (message.type === "user"), then iterates through the content blocks in message.message.content looking for tool result blocks. When it finds one (block.type === "tool_result"), it prints a checkmark emoji to indicate a tool result. The attribute contains the actual output from the tool execution, which can be either a string or an array of content objects. Some tools return substantial output (like WebSearch returning a list of search results or Read returning file contents), while others return minimal or no output (like Bash commands that succeed silently or Write operations that just confirm success). The code handles both string content and array content by checking the type and extracting text appropriately. For array content, it maps over the array to extract text from content objects that have . The code shows a preview of non-empty content or displays "(completed successfully)" for operations that finished without producing output. With both tool calls and results visible, you can now trace the complete workflow of your agent's actions.

Observing the Agent's First Tool Call

When you run the complete code with tool configuration, the agent begins by explaining its plan and then makes its first tool call to search for information. The streaming output shows each step of the agent's work, giving you visibility into its decision-making process.

The output shows the agent first explaining its plan in a text response, then calling WebSearch to find information about the Claude Agent SDK. After receiving search results containing links and descriptions, the agent can evaluate what it found and decide on the next action. Notice how the tool call shows a preview of the query parameter, and the tool result shows a preview of the search results returned. This pattern of explanation, action, and result continues throughout the agent's workflow.

Writing the Summary File

With the information gathered from the search, the agent uses the Write tool to save the summary to the specified file path. Because we configured permissionMode: "acceptEdits", the Write tool is automatically approved even though we didn't explicitly list it in allowedTools.

The Write tool call includes two parameters: the file path where the content should be saved, and the actual content to write (shown truncated in the output). The tool result confirms that the file was created successfully at the specified location. Notice that the agent didn't need to check if the directory exists or create it first — the Write tool handles directory creation automatically when needed. This completes the core task the agent was asked to perform — searching for information and saving a summary. Now the agent provides a final response summarizing what it accomplished.

Completing the Task

After successfully writing the file, the agent provides a final text response that summarizes what it accomplished and offers to help further.

The agent's final response explains what it accomplished, provides details about what's included in the summary, and offers to continue helping if needed. This complete workflow demonstrates how tool-enabled agents work — they think, act, observe results, adapt their strategy, and continue until the task is complete. The agent used two different tool calls across two different tools (WebSearch and Write) to accomplish a task that would have been impossible with text generation alone.

Summary and Hands-On Practices

You've now learned how to transform your agent from a text responder into an active assistant that can search the web, read and write files, and execute commands. By configuring allowedTools, permissionMode, and cwd in your options object, and by checking the type property of message blocks to identify tool use and tool result blocks, you can build and observe agents that accomplish real tasks through intelligent tool use. In the practice exercises ahead, you'll build your own tool-enabled agents that combine multiple tools to solve complex problems.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal