Agents With The Agent SDK
Run a full agent with built-in tools in your own app, then add custom tools and subagents.
TL;DR
query()runs a full agent with built-in tools in your app.- Pre-approve tools with
allowedTools, restrict them withtools, and cap spend withmaxBudgetUsd. - Define
agentsfor subtasks; each runs in a fresh context.
Run An Agent
Install And Sign InInstall the package and set your API key in the environment.
// npm install @anthropic-ai/claude-agent-sdk
// export ANTHROPIC_API_KEY=your-key
import { query } from '@anthropic-ai/claude-agent-sdk';Start The Loopquery() returns a stream of messages as the agent works.
for await (const message of query({
prompt: 'Find bugs in utils.py and fix them.',
options: { allowedTools: ['Read', 'Edit', 'Glob'] },
})) {
// each message is one step of the loop
}Read The ResultThe last message has type result. Check it succeeded, then read the text.
if (message.type === 'result' &&
message.subtype === 'success') {
console.log(message.result);
}Set Its Limits
Pre-Approve ToolsListed tools run without a prompt. acceptEdits also approves file edits.
options: {
allowedTools: ['Read', 'Edit', 'Glob'],
permissionMode: 'acceptEdits',
}Restrict ToolsThe tools list is what the agent can see at all. Anything missing is gone.
options: {
tools: ['Read', 'Grep', 'Glob'], // read-only
}Cap SpendThe run stops when the estimated cost reaches the cap, subagents included.
options: {
maxBudgetUsd: 5,
}
// ends with error_max_budget_usdCustom Tools
Define A ToolA name, a description, a Zod schema, and a handler that returns content.
const toFahrenheit = tool(
'to_fahrenheit',
'Convert Celsius to Fahrenheit',
{ celsius: z.number() },
async ({ celsius }) => {
const text = `${celsius * 9 / 5 + 32}F`;
return { content: [{ type: 'text', text }] };
},
);Register A ServerWrap your tools in an in-process server and pass it in mcpServers.
const units = createSdkMcpServer({
name: 'units',
version: '1.0.0',
tools: [toFahrenheit],
});
// options: { mcpServers: { units } }Allow By Full NameThe name follows mcp__server__tool, so list it in allowedTools.
allowedTools: ['mcp__units__to_fahrenheit']Subagents
Define OneEach subagent gets a description, a prompt, and optionally tools and a model.
agents: {
'code-reviewer': {
description: 'Finds crash bugs. Use for reviews.',
prompt: 'List each bug with a one-line fix.',
tools: ['Read', 'Grep', 'Glob'],
model: 'sonnet',
},
}Allow The Agent ToolClaude delegates through the Agent tool, so it must be allowed.
allowedTools: ['Read', 'Grep', 'Glob', 'Agent']Call It By NameNaming the subagent in the prompt guarantees Claude uses it.
prompt: 'Use the code-reviewer agent on src/auth.ts'Tips
- Write each subagent
descriptionas a clear 'use this when...' sentence, because Claude uses it to decide when to delegate. - Give a subagent only the tools it needs, such as
ReadandGrepfor a reviewer, so it cannot change files by accident.
Warnings
- Subagents do not see the parent conversation. Put file paths and decisions directly in the
promptyou pass them. - Each subagent makes its own API calls, so cost can grow quickly. Set
maxBudgetUsdand limit how many can run at once.
In Practice
Ask the main agent to delegate a code review to a read-only subagent, with a spending cap, and print the final report.
- Allow the Agent tool plus read-only file tools.
- Define a code-reviewer subagent that cannot edit or run commands.
- Name the subagent in the prompt so Claude delegates to it.
- Cap spend and print only the successful final result.
import { query } from '@anthropic-ai/claude-agent-sdk';
for await (const message of query({
prompt: 'Use the code-reviewer agent to check src/utils.ts for crashes.',
options: {
allowedTools: ['Read', 'Grep', 'Glob', 'Agent'],
maxBudgetUsd: 2,
agents: {
'code-reviewer': {
description: 'Finds bugs that could crash the program. Use for code reviews.',
prompt: 'You review code. List each bug with its line and a one-line fix. Do not edit files.',
tools: ['Read', 'Grep', 'Glob'],
model: 'sonnet',
},
},
},
})) {
if (message.type === 'result' && message.subtype === 'success') {
console.log(message.result);
}
}FAQ
The Messages API gives you one model call, and you write the loop and the tools yourself. The Agent SDK runs the whole loop for you with built-in tools for files, shell commands, and search. You host it in your own process. A hosted option, Managed Agents, runs the loop on Anthropic's side instead.
It reads ANTHROPIC_API_KEY from the environment of the process that runs your agent. It does not load .env files, so load them yourself. Cloud providers such as Amazon Bedrock, Google Cloud, and Microsoft Foundry work through their own environment variables.
Use one when a subtask would flood the main conversation, such as reading dozens of files, or when independent tasks can run in parallel. The subagent keeps the mess to itself and returns a short summary.
Yes. By default nesting can go three layers deep with up to 20 subagents running at once. Lower these with the CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH and CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS environment variables.