Vended Tools
Vended tools are pre-built tools included directly in the Strands Harness SDK for common agent tasks like file operations, shell commands, HTTP requests, and persistent notes.
They ship as part of the SDK package and are updated alongside it. See Versioning & Maintenance for how changes are communicated and what level of backwards compatibility they maintain.
Quick start
Section titled “Quick start”Each tool is imported from its own subpath under @strands-agents/sdk/vended-tools, with no additional packages required:
import { Agent } from '@strands-agents/sdk'import { bash } from '@strands-agents/sdk/vended-tools/bash'import { fileEditor } from '@strands-agents/sdk/vended-tools/file-editor'import { httpRequest } from '@strands-agents/sdk/vended-tools/http-request'import { notebook, makeNotebook } from '@strands-agents/sdk/vended-tools/notebook'
const agent = new Agent({ tools: [bash, fileEditor, httpRequest, notebook],})Available tools
Section titled “Available tools”| Tool | Description | Supported in |
|---|---|---|
| File Editor | View, create, and edit files | Python, TypeScript (Node.js) |
| HTTP Request | Make HTTP requests to external APIs | Python, TypeScript (Node.js 22+, browsers) |
| Notebook | Manage persistent text notebooks | Python, TypeScript (Node.js, browsers) |
| Bash | Execute shell commands with persistent sessions | Python, TypeScript (Node.js, Unix/Linux/macOS) |
| MCP Router | Connect to Model Context Protocol servers on a developer-set allowlist | Python |
| Sleep | Pause execution for a bounded, cancellable duration | Python, TypeScript (Node.js, browsers) |
| Handoff to User | Pause the agent loop and surface a message to the user | Python, TypeScript (Node.js, browsers) |
| Stop | Gracefully end the agent loop when the task is complete | Python, TypeScript (Node.js, browsers) |
| Web Fetch | Fetch a URL and return cleaned markdown for a model to read | Python, TypeScript (Node.js) |
File editor
Section titled “File editor”Lets your agent read and modify files on disk: useful for coding agents, config management, or any workflow where the agent inspects output and makes targeted edits.
Example:
import { Agent } from '@strands-agents/sdk'import { fileEditor } from '@strands-agents/sdk/vended-tools/file-editor'
const agent = new Agent({ tools: [fileEditor],})
// Create, view, and edit filesawait agent.invoke('Create a file /tmp/config.json with {"debug": false}')await agent.invoke('Replace "debug": false with "debug": true in /tmp/config.json')await agent.invoke('View lines 1-10 of /tmp/config.json')from strands import Agentfrom strands.vended_tools import file_editor
agent = Agent(tools=[file_editor])agent("Create a file at /tmp/hello.txt with the contents 'Hello, world!'")HTTP request
Section titled “HTTP request”Lets your agent call external APIs and fetch web content. Supports all HTTP methods, custom headers, and request bodies. Default timeout is 30 seconds.
Supported in: Python; Node.js 22+, modern browsers (TypeScript).
The Python tool delegates all networking to an httpx.AsyncClient. Use the make_http_request factory to supply a pre-configured client with authentication, timeouts, redirects, proxies, or other transport-level configuration.
Example:
import { Agent } from '@strands-agents/sdk'import { httpRequest } from '@strands-agents/sdk/vended-tools/http-request'
const agent = new Agent({ tools: [httpRequest],})
// Make API requestsawait agent.invoke('Get data from https://api.example.com/users')await agent.invoke('Post {"name": "John"} to https://api.example.com/users')from strands import Agentfrom strands.vended_tools import http_request
agent = Agent(tools=[http_request])agent("Get data from https://api.example.com/data")Custom configuration with a pre-configured client:
import httpxfrom strands import Agentfrom strands.vended_tools import make_http_request
client = httpx.AsyncClient( headers={"Authorization": "Bearer token"},)tool = make_http_request(client=client)agent = Agent(tools=[tool])Full API reference: TypeScript, Python
Notebook
Section titled “Notebook”A scratchpad the agent can read and write across invocations. The most effective use is giving the agent a notebook at the start of a task and instructing it to plan its work there. It can break the task into steps, check things off as it goes, and always have a clear picture of what’s left. Notebook state is part of the agent’s state, so it persists automatically with Session Management.
Supported in: Node.js, modern browsers (TypeScript); all platforms (Python).
Example - Task Management:
import { Agent } from '@strands-agents/sdk'import { notebook } from '@strands-agents/sdk/vended-tools/notebook'
const agent = new Agent({ tools: [notebook], systemPrompt: 'Before starting any multi-step task, create a notebook with a checklist of steps. ' + 'Check off each step as you complete it.',})
// The agent uses the notebook to plan and track its workawait agent.invoke('Write a project plan for building a personal budget tracker app')from strands import Agentfrom strands.vended_tools import notebook
agent = Agent(tools=[notebook])agent('Create a notebook called "tasks" with "# Daily Tasks" and add "- [ ] Review code" to it')Example - State Persistence:
import { Agent, SessionManager, FileStorage } from '@strands-agents/sdk'import { notebook } from '@strands-agents/sdk/vended-tools/notebook'
const session = new SessionManager({ sessionId: 'my-session', storage: { snapshot: new FileStorage('./sessions') },})
const agent = new Agent({ tools: [notebook], sessionManager: session })
// Notebooks are automatically persisted as part of the sessionawait agent.invoke('Create a notebook called "ideas" with "# Project Ideas"')await agent.invoke('Add "- Build a web scraper" to the ideas notebook')
// ...
// Later, a new agent with the same session restores notebooks automaticallyconst restoredAgent = new Agent({ tools: [notebook], sessionManager: session })await restoredAgent.invoke('Read the ideas notebook')from strands import Agentfrom strands.vended_tools import notebook
agent = Agent(tools=[notebook])agent('Create a notebook called "tasks" with "# Daily Tasks" and add "- [ ] Review code" to it')
# Read the notebook contents directly off agent state.notebooks = agent.state.get("notebooks") or {}print(notebooks.get("tasks"))Example - Custom configuration:
import { Agent } from '@strands-agents/sdk'import { makeNotebook } from '@strands-agents/sdk/vended-tools/notebook'
const notes = makeNotebook({ name: 'notes', maxNotebookSizeBytes: 64 * 1024, // 64 KiB})const agent = new Agent({ tools: [notes] })from strands import Agentfrom strands.vended_tools import make_notebook
notes = make_notebook( name="notes", max_notebook_size_bytes=64 * 1024, # 64 KiB)agent = Agent(tools=[notes])Bash / shell
Section titled “Bash / shell”Lets your agent run shell commands and act on the output. The two SDKs expose different tools here:
- TypeScript
bashspawns a persistentbashprocess on the host. Shell state (variables, working directory, exported functions) persists across invocations within the same session, so the agent can build up context incrementally. Sessions can be restarted to clear state. - Python
shell(and TypeScript’smakeShell) routes each command through the agent’s Sandbox and is stateless: every call runs in a fresh shell, so variables and the working directory do not carry over. The sandbox decides the interpreter (shlocally and in Docker, the remote login shell over SSH), so use portable POSIX syntax.
Supported in: Node.js on Unix/Linux/macOS (TypeScript), all platforms (Python).
Example - File Operations:
import { Agent } from '@strands-agents/sdk'import { bash } from '@strands-agents/sdk/vended-tools/bash'
const agent = new Agent({ tools: [bash],})
// List files and create a new fileawait agent.invoke('List all files in the current directory')await agent.invoke('Create a new file called notes.txt with "Hello World"')from strands import Agentfrom strands.vended_tools import shell
agent = Agent(tools=[shell])agent("List all Python files in the current directory and count them")Example - Session Persistence (TypeScript):
import { Agent } from '@strands-agents/sdk'import { bash } from '@strands-agents/sdk/vended-tools/bash'
const agent = new Agent({ tools: [bash],})
// Variables persist across invocations within the same sessionawait agent.invoke('Run: export MY_VAR="hello"')await agent.invoke('Run: echo $MY_VAR') // Will show "hello"
// Restart session to clear stateawait agent.invoke('Restart the bash session')await agent.invoke('Run: echo $MY_VAR') // Variable will be emptyFull API reference: shell, bash (TypeScript only)
Pauses the agent for a bounded number of seconds. Cancelling the enclosing invocation aborts the sleep immediately rather than waiting for the full duration, so a long timer never ties up a session the caller has moved on from.
Supported in: Node.js, modern browsers (TypeScript); all platforms (Python).
The maximum duration is configurable at construction (default: 60 seconds) and
cannot be raised by the model. Negative, NaN, infinite, non-numeric, and
boolean durations are rejected at the tool boundary.
Example:
import { Agent } from '@strands-agents/sdk'import { sleep } from '@strands-agents/sdk/vended-tools/sleep'
const agent = new Agent({ tools: [sleep],})await agent.invoke('Pause for two seconds, then continue.')from strands import Agentfrom strands.vended_tools import sleep
agent = Agent(tools=[sleep])agent("Pause for two seconds, then continue.")Custom maximum:
import { Agent } from '@strands-agents/sdk'import { makeSleep } from '@strands-agents/sdk/vended-tools/sleep'
const shortSleep = makeSleep({ maxDuration: 5 })const agent = new Agent({ tools: [shortSleep] })from strands import Agentfrom strands.vended_tools import make_sleep
short_sleep = make_sleep(max_duration=5)agent = Agent(tools=[short_sleep])Handoff to User
Section titled “Handoff to User”Lets the model pause the agent loop and surface a message to the user for human-in-the-loop input. Use this when the agent needs explicit confirmation, additional information, or user approval before proceeding.
Supported in: Node.js, modern browsers (TypeScript); all platforms (Python).
The loop halts with a stop_reason / stopReason of "interrupt" and the message is available
on the interrupt’s reason field in AgentResult.interrupts. Resume the agent
by passing back an interruptResponse content block with the interrupt ID and
the user’s reply; the tool then returns that reply as its result and the model
continues. To recognize a handoff interrupt, match its name against the exported
HANDOFF_INTERRUPT_NAME constant.
Example:
import { Agent, InterruptResponseContent } from '@strands-agents/sdk'import { handoffToUser, HANDOFF_INTERRUPT_NAME } from '@strands-agents/sdk/vended-tools/handoff-to-user'
const agent = new Agent({ tools: [handoffToUser], systemPrompt: 'Before deleting any files, call handoff_to_user to confirm with the user.',})
let result = await agent.invoke('Delete all .tmp files in /workspace.')const interrupt = result.interrupts?.find((i) => i.name === HANDOFF_INTERRUPT_NAME)if (interrupt) { console.log(interrupt.reason) result = await agent.invoke([ new InterruptResponseContent({ interruptId: interrupt.id, response: 'confirmed' }), ])}from strands import Agentfrom strands.vended_tools.handoff_to_user import HANDOFF_INTERRUPT_NAME, handoff_to_user
agent = Agent( tools=[handoff_to_user], system_prompt=( "Before deleting any files, call handoff_to_user to confirm with the user." ),)
result = agent("Delete all .tmp files in /workspace.")interrupt = next(i for i in (result.interrupts or []) if i.name == HANDOFF_INTERRUPT_NAME)print(interrupt.reason)
resumed = agent([ { "interruptResponse": { "interruptId": interrupt.id, "response": "confirmed", } }])Stop (experimental)
Section titled “Stop (experimental)”This tool is experimental and subject to change in future revisions without notice.
Lets the model gracefully end the agent loop with an optional final message. The default loop already terminates when the model returns without any tool call; the stop tool is useful when you want an explicit “I am done” affordance, when a workflow enforces that termination is a deliberate model decision, or when a sub-agent needs to signal completion back to a coordinator via the loop’s last assistant message.
Supported in: Node.js, modern browsers (TypeScript); all platforms (Python).
This is a cooperative stop, not an abort. Any other tools the model requested in the same turn still run to completion; the loop halts after that batch without calling the model again. The final message defaults to a 4096-character cap; pass max_message_length / maxMessageLength to make_stop / makeStop when a longer summary is legitimate.
The two SDKs shim onto different loop-termination primitives, which produces a small difference in the final AgentResult. TypeScript halts via AfterToolsEvent.endTurn and returns stopReason: "endTurn" with the stop text as the last assistant message. Python halts via invocation_state["request_state"]["stop_event_loop"] and returns stop_reason: "tool_use" with the model’s tool-use message as the final message; the stop text lives in history as the tool result, not as a new assistant turn.
Example:
import { Agent } from '@strands-agents/sdk'import { stop } from '@strands-agents/sdk/experimental/vended-tools/stop'
const agent = new Agent({ tools: [stop], systemPrompt: 'Complete the task. Call stop with a short summary when you are done.',})await agent.invoke('Summarize the changes in ./CHANGELOG.md')from strands import Agentfrom strands.experimental.tools import stop
agent = Agent( tools=[stop], system_prompt="Complete the task. Call stop with a short summary when you are done.",)result = agent("Summarize the changes in ./CHANGELOG.md")Web fetch
Section titled “Web fetch”Fetches an HTTP(S) URL and returns its content. Two modes are available,
configured at construction time via make_web_fetch / makeWebFetch:
agentic(default): HTML is converted to markdown and passed to an analyst agent that answers aprompt, so the full page never enters the main agent’s context. Use when targeted answers are needed about potentially large pages.markdown: HTML is converted to clean markdown with scripts, styles, and noise stripped. Use when the agent needs full pages for reasoning.
The max_bytes / maxBytes parameter caps the HTTP response size (default 5 MiB);
max_content_chars / maxContentChars caps the extracted content delivered to the model or
analyst (default 50,000 characters). For mode='agentic' / mode: 'agentic',
the factory also accepts a model for the analyst; the agent’s own model is
used when none is supplied.
The Python tool delegates all networking to an httpx.AsyncClient. Use the
make_web_fetch factory to supply a pre-configured client with custom
timeouts, redirects, proxies, or caching.
Supported in: Node.js (TypeScript); Python (all platforms).
Example:
import { Agent } from '@strands-agents/sdk'import { webFetch } from '@strands-agents/sdk/vended-tools/web-fetch'
const agent = new Agent({ tools: [webFetch] })await agent.invoke('Summarize https://example.com/blog/post')Reading the full page as markdown:
import { Agent } from '@strands-agents/sdk'import { makeWebFetch } from '@strands-agents/sdk/vended-tools/web-fetch'
const webFetch = makeWebFetch({ mode: 'markdown' })const agent = new Agent({ tools: [webFetch] })await agent.invoke('Read https://example.com/docs and explain the architecture')Tighter response cap with a dedicated analyst model:
import { Agent } from '@strands-agents/sdk'import { makeWebFetch } from '@strands-agents/sdk/vended-tools/web-fetch'import { BedrockModel } from '@strands-agents/sdk/models/bedrock'
const webFetch = makeWebFetch({ mode: 'agentic', maxBytes: 1 * 1024 * 1024, maxContentChars: 25_000, model: new BedrockModel({ modelId: 'us.amazon.nova-micro-v1:0' }),})const agent = new Agent({ tools: [webFetch] })from strands import Agentfrom strands.vended_tools import web_fetch
agent = Agent(tools=[web_fetch])agent("What is the pricing for the enterprise plan at https://example.com/pricing")Reading the full page as markdown:
from strands import Agentfrom strands.vended_tools import make_web_fetch
web_fetch = make_web_fetch(mode="markdown")agent = Agent(tools=[web_fetch])agent("Read https://example.com/docs and then explain the architecture")Tighter response cap with a dedicated analyst model and custom transport:
import httpxfrom strands import Agentfrom strands.models import BedrockModelfrom strands.vended_tools import make_web_fetch
web_fetch = make_web_fetch( mode="agentic", client=httpx.AsyncClient(timeout=10.0), max_bytes=1 * 1024 * 1024, max_content_chars=25_000, model=BedrockModel(model_id="us.amazon.nova-micro-v1:0"),)agent = Agent(tools=[web_fetch])MCP Router
Section titled “MCP Router”Lets your agent connect to Model Context Protocol servers at runtime, list the tools they expose, invoke one, and disconnect. The factory takes a developer-set allowlist of server configurations; the model can only initiate connections to servers on that list.
The tool exposes five commands: connect (opens a named connection to an allowlisted server using a connection_id), list_connections (returns all open connection IDs for the current agent), list_tools (returns the tools the server exposes), call_tool (invokes a tool by name), and disconnect (closes a connection).
Connections are scoped per agent and persist across invocations on the same agent instance. A connection is closed when the model calls disconnect explicitly, or when the agent is garbage collected. The connection remains open otherwise.
Supported in: all platforms (Python).
Example:
from strands import Agentfrom strands.vended_tools import make_mcp_router
mcp_router = make_mcp_router( servers={ "files": {"command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]}, "my-api": {"url": "https://mcp.example.com/mcp"}, }, max_connections=5,)agent = Agent(tools=[mcp_router])agent( "Connect to 'files', list its tools, " "call the read_file tool on /tmp/hello.txt, then disconnect.")Using multiple tools together
Section titled “Using multiple tools together”Combine vended tools in one agent to cover a multi-step workflow:
import { Agent } from '@strands-agents/sdk'import { bash } from '@strands-agents/sdk/vended-tools/bash'import { fileEditor } from '@strands-agents/sdk/vended-tools/file-editor'import { notebook } from '@strands-agents/sdk/vended-tools/notebook'
const agent = new Agent({ tools: [bash, fileEditor, notebook], systemPrompt: [ 'You are a software development assistant.', 'When given a feature to implement:', '1. Use the notebook tool to create a plan with a checklist of steps', '2. Work through each step, checking them off as you go', '3. Use the bash tool to run tests and verify your changes', ].join('\n'),})
// Agent plans the work, implements it, and tracks progressawait agent.invoke( 'Add input validation to the createUser function in src/users.ts. ' + 'It should reject empty names and invalid email formats.')Versioning & maintenance
Section titled “Versioning & maintenance”Vended tools ship as part of the SDK and are updated alongside it. Report bugs and feature requests in the GitHub repository.
Tool names are stable and will not change. In minor versions, a tool’s description, spec, or parameters may be updated to improve effectiveness. These changes are noted in SDK release notes. Pin your SDK version and test after upgrades if your workflows depend on specific tool behavior.
See also
Section titled “See also”- Custom Tools: build your own tools
- Community Tools Package: Python tools package with 30+ tools
- Session Management: persist agent state including notebooks
- Interrupts: implement approval workflows for sensitive operations
- Hooks: intercept and customize tool execution