Attach and invoke tools
Once you have tools, whether you wrote them yourself, pulled them from an MCP server, or picked them from a prebuilt package, you attach them to an agent and the agent decides when to call them. This page covers how tools load onto an agent and the two ways to invoke them.
Adding Tools to Agents
Section titled “Adding Tools to Agents”Pass tools to an agent at initialization or add them at runtime. Once loaded, the agent can call them in response to user requests:
from strands import Agentfrom strands.vended_tools import http_request, notebook
# Add tools to our agentagent = Agent(tools=[http_request, notebook])
# Agent will automatically determine when to use the notebook toolagent('Create a notebook named "ideas" and add three project ideas.')
print("\n\n") # Print new lines
# Agent will use the HTTP request tool when appropriateagent("Get https://example.com and summarize the response status.")const agent = new Agent({ tools: [fileEditor],})
// Agent will use the file_editor tool when appropriateawait agent.invoke('Show me the contents of a single file in this directory')We can see which tools are loaded in our agent:
Access agent.tool_names for a list of tool names, and agent.tool_registry.get_all_tools_config() for a JSON representation including descriptions and input parameters:
print(agent.tool_names)
print(agent.tool_registry.get_all_tools_config())Access the tools array directly:
// Access all toolsconsole.log(agent.tools)Loading Tools from Files
Section titled “Loading Tools from Files”Load tools from a file by passing its path at initialization:
agent = Agent(tools=["/path/to/my_tool.py"])Loading tools from a file path is available in the Python SDK.
Auto-loading and reloading tools
Section titled “Auto-loading and reloading tools”Tools placed in your current working directory ./tools/ can be automatically loaded at agent initialization, and automatically reloaded when modified. This helps when developing and debugging tools: modify the tool code and any agent using it reloads the latest version.
Automatic loading and reloading of tools in the ./tools/ directory is disabled by default. To enable this behavior, set load_tools_from_directory=True during Agent initialization:
from strands import Agent
agent = Agent(load_tools_from_directory=True)Automatic loading and reloading from a directory is available in the Python SDK.
Using Tools
Section titled “Using Tools”You can invoke tools in two ways.
Agents have context about tool calls and their results as part of conversation history. See Using State in Tools for more information.
Natural Language Invocation
Section titled “Natural Language Invocation”The most common way agents use tools is through natural language requests. The agent determines when and how to invoke tools based on the user’s input:
# Agent decides when to use tools based on the requestagent('Read the "ideas" notebook.')const agent = new Agent({ tools: [notebook],})
// Agent decides when to use tools based on the requestawait agent.invoke('Please read the default notebook')Direct Method Calls
Section titled “Direct Method Calls”Tools can be invoked programmatically in addition to natural language invocation.
Every tool added to an agent becomes a method accessible directly on the agent object:
# Directly invoke a tool as a methodresult = agent.tool.notebook(mode="read", name="ideas")When calling tools directly as methods, always use keyword arguments. Positional arguments are not supported:
# Positional arguments are not supported, this raises an errorresult = agent.tool.notebook("read", "ideas")If a tool name contains hyphens, you can invoke the tool using underscores instead:
# Directly invoke a tool named "read-all"result = agent.tool.read_all(path="/path/to/file.txt")Every tool added to an agent is accessible as a method on agent.tool. Call .invoke(input) for the result, or .stream(input) to consume intermediate events:
import { Agent } from '@strands-agents/sdk'import { notebook } from '@strands-agents/sdk/vended-tools/notebook'
const agent = new Agent({ tools: [notebook],})
// Call a tool by name. Returns a ToolResultBlock with `status`// ('success' | 'error') and `content` blocks.const result = await agent.tool.notebook!.invoke({ mode: 'read', name: 'default',})console.log(result.status, result.content)
// Stream intermediate events; the generator returns the final result.for await (const event of agent.tool.notebook!.stream({ mode: 'read', name: 'default',})) { console.log('progress:', event)}
// Skip recording the call in conversation history.await agent.tool.notebook!.invoke( { mode: 'read', name: 'default' }, { recordDirectToolCall: false })Note agent.tool (singular) is the direct-call accessor; agent.tools (plural) is the array of registered tools.
The accessor resolves names by exact match first, then with underscores substituted for hyphens, then case-insensitively. agent.tool.read_all resolves to a tool registered as read-all. Calling a name that doesn’t resolve throws ToolNotFoundError.
By default, direct calls are recorded in the agent’s message history. Pass { recordDirectToolCall: false } to skip recording. This is required when calling tools during an active agent invocation (otherwise ConcurrentInvocationError is thrown), and useful for side-effect tools whose output should stay out of conversation context.
When a model returns several tool requests at once, a tool executor controls whether they run concurrently (the default) or sequentially.