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

  1. query() runs a full agent with built-in tools in your app.
  2. Pre-approve tools with allowedTools, restrict them with tools, and cap spend with maxBudgetUsd.
  3. Define agents for subtasks; each runs in a fresh context.

Run An Agent

    Install And Sign In

    Install 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 Loop

    query() 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 Result

    The 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 Tools

    Listed tools run without a prompt. acceptEdits also approves file edits.

    options: {
      allowedTools: ['Read', 'Edit', 'Glob'],
      permissionMode: 'acceptEdits',
    }
    Restrict Tools

    The tools list is what the agent can see at all. Anything missing is gone.

    options: {
      tools: ['Read', 'Grep', 'Glob'], // read-only
    }
    Cap Spend

    The run stops when the estimated cost reaches the cap, subagents included.

    options: {
      maxBudgetUsd: 5,
    }
    // ends with error_max_budget_usd

Custom Tools

    Define A Tool

    A 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 Server

    Wrap 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 Name

    The name follows mcp__server__tool, so list it in allowedTools.

    allowedTools: ['mcp__units__to_fahrenheit']

Subagents

    Define One

    Each 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 Tool

    Claude delegates through the Agent tool, so it must be allowed.

    allowedTools: ['Read', 'Grep', 'Glob', 'Agent']
    Call It By Name

    Naming the subagent in the prompt guarantees Claude uses it.

    prompt: 'Use the code-reviewer agent on src/auth.ts'

Tips

  1. Write each subagent description as a clear 'use this when...' sentence, because Claude uses it to decide when to delegate.
  2. Give a subagent only the tools it needs, such as Read and Grep for a reviewer, so it cannot change files by accident.

Warnings

  1. Subagents do not see the parent conversation. Put file paths and decisions directly in the prompt you pass them.
  2. Each subagent makes its own API calls, so cost can grow quickly. Set maxBudgetUsd and limit how many can run at once.

In Practice

FAQ