Guide12 steps

Build your first agent with the Claude Agent SDK (TypeScript, October 2026)

Install @anthropic-ai/claude-agent-sdk, call query(), lock down tools and permission modes, add a custom MCP tool and a safety hook, and cap spend. Code type-checked against v0.3.293.

A glass work card handed to one AI agent bubble on a coral gradient, titled Claude Agent SDK

In 20 seconds

  1. The Claude Agent SDK is Claude Code's agent loop as a library: npm package @anthropic-ai/claude-agent-sdk (0.3.293) or PyPI claude-agent-sdk (0.2.164), authenticated with an Anthropic API key or a cloud provider.
  2. query() streams the agent's work; tools, allowedTools, permissionMode and hooks decide what it can touch. Set permissionMode explicitly, because the default changed in v0.3.286.
  3. Custom tools run in-process as an MCP server; model, maxTurns and maxBudgetUsd control cost. We type-checked the TypeScript code in this guide but did not run it against the API.
Steps

Update, October 29, 2026: Cursor released its own "Agent SDK" on October 20, 2026. Despite the name, it's a framework for event-driven team bots with Cursor hosting, not a library like this one. See how Cursor's Agent SDK compares with the Claude Agent SDK and OpenAI's Agents SDK.

The Claude Agent SDK is Anthropic's library for building agents on the same loop, built-in tools, permissions and hooks that power Claude Code. According to Anthropic's docs, you write a prompt and some configuration, and the SDK runs the model, executes tools such as Read, Edit and Bash, and streams back what happened. This guide takes you from install to a small, locked-down agent with a custom tool, a safety hook and a spending cap.

How we checked this code. On October 8, 2026, we installed @anthropic-ai/claude-agent-sdk 0.3.293 on Node.js 22 and type-checked the example code in this guide with TypeScript 7.0.2 in strict mode. The types catch mistakes: an invalid permission mode and a misspelled result field both failed the check. The code was type-checked only and never run against the Claude API. Descriptions of runtime behavior below come from Anthropic's documentation and the SDK's type definitions, not from our own runs. The source and lockfile are in our code examples folder (code-examples/D6-agent-sdk-example/).

Last verified: October 8, 2026

What the Agent SDK is (and isn't)

Anthropic's docs describe it as a way to "build production AI agents with Claude Code as a library." Practically:

  • It runs the Claude Code binary under the hood. Both the TypeScript and Python packages bundle a native binary, so you usually don't need a separate Claude Code install. Version 0.3.293's package.json pins Claude Code 2.1.293.
  • It is not the plain Claude API client (@anthropic-ai/sdk), where you write the tool loop yourself, and not Anthropic's hosted Managed Agents product. Use the Agent SDK when you want Claude Code's tools and loop inside a process you operate.

The packages:

LanguagePackageVersion (Oct 8, 2026)
TypeScript@anthropic-ai/claude-agent-sdk (npm)0.3.293, published October 7, 2026 (the version this guide was type-checked against; 0.3.295 was published October 8)
Pythonclaude-agent-sdk (PyPI)0.2.165 (published October 8)

Both release often (several npm versions shipped in the first week of October 2026 alone), so pin versions in production. Last verified: October 9, 2026.

Prerequisites

  • Node.js 18+ (the docs' minimum) or Python 3.10+. We type-checked this guide on Node 22.
  • An Anthropic API key from the Claude Console, or credentials for one of the supported cloud providers.

Step 1: Install

BASH
mkdir my-agent && cd my-agent
npm init -y
npm pkg set type=module
npm install @anthropic-ai/claude-agent-sdk
npm install --save-dev tsx

"type": "module" allows top-level await; tsx runs TypeScript files directly. The SDK installs its platform binary through npm optional dependencies, so don't use --omit=optional, or you'll get no binary.

The SDK also lists zod, @anthropic-ai/sdk and @modelcontextprotocol/sdk (v1, ^1.29.0) as peer dependencies; recent npm versions install them automatically. Note that the Agent SDK uses the v1 MCP package, while our MCP server guide uses the newer v2 packages. They can coexist.

Python: pip install claude-agent-sdk (or uv add claude-agent-sdk).

Step 2: Authenticate

BASH
export ANTHROPIC_API_KEY=your-api-key

The SDK reads the key from the process environment and does not load .env files by itself. Cloud alternatives are switched on with environment variables: CLAUDE_CODE_USE_BEDROCK=1 (Amazon Bedrock), CLAUDE_CODE_USE_VERTEX=1 (Google Cloud's Agent Platform), CLAUDE_CODE_USE_FOUNDRY=1 (Microsoft Foundry), or CLAUDE_CODE_USE_ANTHROPIC_AWS=1 with ANTHROPIC_AWS_WORKSPACE_ID (Claude Platform on AWS), each with that provider's credentials.

One policy point: Anthropic says that, unless previously approved, third-party developers may not offer claude.ai login or claude.ai rate limits in products built on the Agent SDK. Ship with API-key or cloud-provider auth.

Step 3: A minimal agent with query()

This is the shape of Anthropic's quickstart. Save as agent.ts:

TYPESCRIPT · agent.ts
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Review utils.py for bugs that would cause crashes. Fix any issues you find.",
  options: {
    allowedTools: ["Read", "Edit", "Glob"], // auto-approve these tools
    permissionMode: "acceptEdits",          // auto-approve file edits
  },
})) {
  if (message.type === "assistant") {
    for (const block of message.message.content) {
      if (block.type === "text") console.log(block.text);
      else if (block.type === "tool_use") console.log(`Tool: ${block.name}`);
    }
  } else if (message.type === "result") {
    console.log(`Done: ${message.subtype}`);
  }
}

Anthropic's quickstart runs it with npx tsx agent.ts. Per the docs, query() returns an async iterator. Each item is a message: system setup, the model's text, tool calls, tool results, and finally a result message with a subtype such as success. The docs also say that by default the agent can work on files in the current directory and its subdirectories.

Step 4: Decide what the agent can touch

This is the part to get right. Three options do different jobs:

OptionLayerEffect
tools: ["Read", "Grep"]AvailabilityOnly these built-ins are visible to Claude. MCP tools are unaffected.
allowedTools: [...]PermissionListed tools run without asking. Unlisted tools still exist and go through the permission flow.
disallowedTools: ["Bash"]BothA bare name removes the tool entirely; a scoped rule like "Bash(rm *)" denies matching calls.

The common mistake: thinking allowedTools is an allowlist. It isn't. It pre-approves. The docs warn that allowedTools "does not constrain bypassPermissions": with allowedTools: ["Read"] and permissionMode: "bypassPermissions", every tool, including Bash, is approved.

Permission modes (PermissionMode type in 0.3.293):

ModeWhat it does
defaultNo automatic approvals beyond allow rules; anything else goes to your canUseTool callback
dontAskAnything that would prompt is denied; only pre-approved and no-approval-needed calls run
acceptEditsAuto-approves file edits and filesystem commands (mkdir, rm, mv…) inside the working directory
planExplore and plan; edits are never auto-approved
autoA model classifier approves or blocks actions such as shell commands
bypassPermissionsApproves almost everything. The docs say to use it only "in controlled environments where you trust all possible operations"

Set permissionMode explicitly. Per Anthropic's docs, before TypeScript SDK v0.3.286 leaving it out meant default; now the starting mode comes from your settings files and otherwise from Claude Code's built-in default, "which can be auto mode." If your app assumes prompts will reach your callback, pass default.

For a headless, read-only agent, the docs recommend pairing allowedTools with dontAsk. Even then, some calls that need no approval in default mode, such as file reads inside the working directory, still run.

Step 5: Add a custom tool (in-process MCP server)

Custom tools are defined with tool() and served by createSdkMcpServer(), an MCP server that runs inside your process, not as a separate program. The name Claude sees is mcp__<server key>__<tool name>:

TYPESCRIPT
import { tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";

const countTodos = tool(
  "count_todos",
  "Count TODO and FIXME markers in a block of source code.",
  { source: z.string().describe("Source code to scan") },
  async ({ source }) => {
    const todos = (source.match(/\bTODO\b/g) ?? []).length;
    const fixmes = (source.match(/\bFIXME\b/g) ?? []).length;
    return {
      content: [{ type: "text", text: `TODO: ${todos}, FIXME: ${fixmes}` }],
      structuredContent: { todos, fixmes },
    };
  },
  { annotations: { readOnlyHint: true } },
);

const repoTools = createSdkMcpServer({ name: "repo-tools", version: "1.0.0", tools: [countTodos] });
// later: options.mcpServers = { "repo-tools": repoTools }
//        options.allowedTools includes "mcp__repo-tools__count_todos"

Notes from the docs: the schema is a Zod shape and the handler's arguments are typed from it; a thrown error doesn't stop the agent, it comes back to Claude as an error result (return isError: true to write a better message); readOnlyHint: true lets Claude run the tool in parallel with other read-only calls, but it's a hint, not enforcement. Tool search is on by default, so Claude loads full tool schemas on demand. If you'd rather run a standalone MCP server, see our TypeScript MCP server guide; the mcpServers option also accepts stdio and HTTP servers. For when a tool, resource or prompt is the right choice, see MCP resources vs tools vs prompts.

Step 6: Add a safety hook

Hooks are callbacks that run at points in the loop. Anthropic's permissions docs say hooks run before every other permission check, and that a hook deny applies even in bypassPermissions mode, which makes PreToolUse the right place for rules that must never be skipped:

TYPESCRIPT
import type { HookCallback, PreToolUseHookInput } from "@anthropic-ai/claude-agent-sdk";

const blockSecrets: HookCallback = async (input) => {
  const pre = input as PreToolUseHookInput;
  const toolInput = pre.tool_input as Record<string, unknown>;
  const path = String(toolInput?.file_path ?? toolInput?.path ?? "");
  if (/(^|\/)\.env(\.|$)|id_rsa|\.pem$/.test(path)) {
    return {
      hookSpecificOutput: {
        hookEventName: pre.hook_event_name,
        permissionDecision: "deny",
        permissionDecisionReason: `Reading ${path} is blocked by policy`,
      },
    };
  }
  return {}; // no opinion: continue normal permission checks
};
// options.hooks = { PreToolUse: [{ matcher: "Read|Grep", hooks: [blockSecrets] }] }

Matchers filter on tool names only, so check paths inside the callback. Per the docs, a hook returning allow does not skip deny or ask rules. The TypeScript SDK supports many more events (PostToolUse, Stop, SessionStart, SubagentStop and others); the Python SDK supports fewer.

Step 7: Choose a model and cap the cost

  • model picks the model by API ID. Anthropic's models page on October 8, 2026 lists claude-opus-5-5 ($4/$20 per million input/output tokens), claude-sonnet-5-5 ($2/$10), claude-haiku-5-5 (listed "from" $0.10/$0.50) and claude-fable-5-1 ($10/$50). Our Claude model guide covers which to use when; agents make many calls per task, so the cheaper tiers add up differently than in chat.
  • fallbackModel names models to try if the primary is overloaded.
  • effort (low to max) trades depth of reasoning against cost and latency on models that support it.
  • maxTurns caps round-trips.
  • maxBudgetUsd, per the SDK's types, stops the query with an error_max_budget_usd result once the SDK's estimated spend passes your limit.
  • The result message carries total_cost_usd and per-model modelUsage. The SDK's own type docs call the cost "an estimate, not a billing statement." Check the Console for real billing.

The complete example

Our full example combines the pieces. It configures a read-only reviewer that sees only Read, Glob and Grep plus the custom tool, uses dontAsk mode, has a hook set to deny reads of secret files, and is capped at 20 turns or an estimated $0.50. This is abridged from src/agent.ts, the file we type-checked. We did not run it:

TYPESCRIPT
import { query, tool, createSdkMcpServer, type HookCallback, type PreToolUseHookInput } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";

// countTodos, repoTools and blockSecrets as defined in Steps 5 and 6

for await (const message of query({
  prompt:
    "Review the TypeScript files in ./src. Summarize what they do, " +
    "use count_todos on each file, and list the three most important fixes.",
  options: {
    model: "claude-sonnet-5-5",
    tools: ["Read", "Glob", "Grep"],
    allowedTools: ["Read", "Glob", "Grep", "mcp__repo-tools__count_todos"],
    permissionMode: "dontAsk",
    mcpServers: { "repo-tools": repoTools },
    hooks: { PreToolUse: [{ matcher: "Read|Grep", hooks: [blockSecrets] }] },
    maxTurns: 20,
    maxBudgetUsd: 0.5,
  },
})) {
  if (message.type === "assistant") {
    for (const block of message.message.content) {
      if (block.type === "text") console.log(block.text);
      else if (block.type === "tool_use") console.log(`[tool] ${block.name}`);
    }
  } else if (message.type === "result") {
    console.log(`\nResult: ${message.subtype}`);
    console.log(`Turns: ${message.num_turns}, estimated cost: $${message.total_cost_usd.toFixed(4)}`);
    if (message.subtype === "success") console.log(message.result);
  }
}

To run it yourself: set ANTHROPIC_API_KEY, then npx tsx src/agent.ts. We haven't, so we can't tell you what it prints.

Troubleshooting

  • Not logged in / Invalid API key: the key isn't in the environment of the process running the agent. Remember .env isn't loaded automatically.
  • Binary not found: you installed with optional dependencies skipped. Reinstall without --omit=optional, or install Claude Code natively and set pathToClaudeCodeExecutable.
  • Tool calls denied unexpectedly: in dontAsk mode, anything not pre-approved is denied. Check allowedTools spelling, including the full mcp__server__tool name. The docs say unanchored globs like "mcp__*" in allowedTools are ignored with a startup warning.
  • Your canUseTool callback never fires: an allow rule or mode already approved the call. Per the docs, the TypeScript SDK emits a CLAUDE_SDK_CAN_USE_TOOL_SHADOWED process warning when bypassPermissions or bare allowedTools entries would shadow the callback. Use a PreToolUse hook for checks that must always run.
  • Bypass mode refuses to start: per the docs, on Linux and macOS Claude Code won't start in bypassPermissions as root or under sudo outside a recognized sandbox.

Security checklist

  • Start in dontAsk or default; reach for acceptEdits only in a disposable directory, and bypassPermissions only in a sandbox. Per the docs, subagents run in the parent's permission mode unless you set one on the subagent and the parent is in default, dontAsk or plan; a subagent never gets bypassPermissions unless the parent has it.
  • Remove tools you don't need (tools or bare-name disallowedTools) rather than relying on prompts to discourage them.
  • Put non-negotiable rules in PreToolUse hooks.
  • Treat everything the agent reads (web pages, issues, files from others) as potentially hostile input; that's how prompt injection reaches tools. Our case against unattended agents covers the failure modes.
  • Cap spend with maxBudgetUsd and maxTurns, and log results.

Read next

Comments (0)

More on Anthropic

View all
Products · ExplainerDoes Claude train on your data? Yes on Free, Pro and Max if Model Improvement is on; no by default on Team, Enterprise and the APIDoes Claude train on your data? On Free, Pro and Max, Anthropic trains on your chats and Claude Code sessions when the Model Improvement setting is on, and keeps that data up to five years. Team, Enterprise and the API aren't used for training by default. Every plan, the setting, the exceptions and how long data is kept.·8 min read
Industry · NewsAnthropic government discount: 40% off Claude Enterprise, Claude for Government and the API through GSA's OneGovAnthropic's government discount, announced October 27, 2026, gives agencies 40% off Claude Enterprise, Claude for Government and the Claude API through GSA's OneGov program, including state, local, tribal and territorial governments. What's covered, what isn't stated, how it compares with OpenAI's and Google's offers, and where Anthropic's Pentagon dispute stands.·6 min read
Industry · NewsAnthropic Mithril acquisition: Anthropic buys a one-person muscular dystrophy startup and starts its own drug programsThe Anthropic Mithril acquisition, disclosed on October 27, 2026, brings a one-person rare-disease startup in house as Anthropic starts drug discovery of its own. What Mithril is, what Anthropic's 'early progress' post claims from six drug-development partners, and what's still undisclosed.·6 min read
Policy · NewsAnthropic and Stanford professors' books: what the Stanford Daily reported about pirated copies, and what the lawsuits allegeAnthropic and Stanford professors' books: on October 27, 2026, the Stanford Daily reported that pirated copies of work by more than 10 Stanford professors were used to train Claude, naming six. How that fits the $1.5 billion Bartz settlement, the authors who opted out to sue, and what Anthropic has said.·7 min read
The Week in AI · every Friday

New guides and explainers, every Friday.

The week’s biggest stories in AI and tech, what they mean, and what to read next.

Free. One email a week. Unsubscribe in one click.