SuperAPI AI Directory

agent-sdk-quickstart

Agents & models

View repository

Updated 10-15 23:49

About this skill

Claude Agent SDK — Quickstart

The Claude Agent SDK is Anthropic's framework for building agents. It handles the tool-use loop, context compaction, sub-agent spawning, and MCP integration so you don't reinvent them.

When to Use

  • Starting a new agent project
  • Migrating from hand-rolled messages.create loops
  • Need sub-agent orchestration, compaction, or skills out-of-box
  • Building CLI tools, automation, or backend agents

SDK vs Direct API vs Managed Agents

Approach Best for Tradeoff
Direct messages.create Simple one-shot calls You manage everything
Agent SDK (client-side) Custom agents with full control You run the loop, manage state
Managed Agents API (/v1/agents) Production agents at scale Anthropic runs the loop server-side

Use the SDK when you need more control than Managed Agents but don't want to rewrite the tool loop.

Install

TypeScript:

npm i @anthropic-ai/claude-agent-sdk

Python:

pip install claude-agent-sdk

Minimal Agent — TypeScript

import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "What files are in the current directory?",
  options: {
    model: "claude-sonnet-4-6",
    permissionMode: "default",
  },
})) {
  if (message.type === "assistant") {
    for (const block of message.message.content) {
      if (block.type === "text") process.stdout.write(block.text);
    }
  }
}

Under the hood: the SDK connects to Claude, provides default tools (file read, bash, web fetch), runs the tool-use loop, and streams results back.

Minimal Agent — Python

import asyncio
from claude_agent_sdk import query

async def main():
    async for msg in query(
        prompt="What files are here?",
        options={"model": "claude-sonnet-4-6"},
    ):
        if msg.type == "assistant":
            for block in msg.message.content:
                if block.type == "text":
                    print(block.text, end="")

asyncio.run(main())

Adding Custom Tools

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

const getWeather = tool({
  name: "get_weather",
  description: "Get current weather for a city.",
  inputSchema: z.object({ city: z.string() }),
  handler: async ({ city }) => ({
    content: [{ type: "text", text: `Weather in ${city}: sunny, 72°F` }],
  }),
});

for await (const message of query({
  prompt: "What's the weather in SF?",
  options: {
    model: "claude-sonnet-4-6",
    tools: [getWeather],
  },
})) { /* ... */ }

Tools are plain objects with a name, description, schema, and async handler. No magic.

Permission Modes

options: {
  permissionMode: "default",        // prompt user for risky actions
  // or "acceptEdits"                // auto-approve edits, prompt for bash
  // or "bypassPermissions"          // YOLO (dev only)
  // or "plan"                       // read-only, no writes
}

Use plan for dry-runs, default for interactive tools, acceptEdits only when you trust the agent.

Hooks

Intercept tool calls before/after execution:

options: {
  hooks: {
    PreToolUse: async ({ toolName, input }) => {
      console.log(`About to run ${toolName}`);
      if (toolName === "bash" && input.command.includes("rm -rf")) {
        return { decision: "block", reason: "Blocked destructive command" };
      }
    },
    PostToolUse: async ({ toolName, output }) => {
      await audit.log({ toolName, output });
    },
  },
}

Hooks run on your machine and can block, modify, or observe every tool call.

Connecting to MCP Servers

options: {
  mcpServers: {
    github: { command: "npx", args: ["-y", "@modelcontextprotocol/server-github"] },
  },
}

MCP tools appear alongside built-in tools. See the mcp-client-integration skill.

System Prompts

options: {
  systemPrompt: "You are a code reviewer. Be concise and actionable.",
  // or append to the default:
  appendSystemPrompt: "Always use TypeScript in examples.",
}

Multi-Turn

Use resume to continue a previous session:

const sessionId = "session-123";

for await (const msg of query({
  prompt: "Follow up: what about tests?",
  options: { model: "claude-sonnet-4-6", resume: sessionId },
})) { /* ... */ }

See the session-lifecycle skill for more.

Anti-Patterns

  1. Rebuilding the tool loop manually when the SDK handles it
  2. bypassPermissions in production — first hallucinated rm is your last
  3. Not using hooks for audit/safety — missed opportunity
  4. Mixing SDK calls with direct messages.create in the same agent — confuses session state

Best Practices

  1. Start with the SDK; drop to direct API only if SDK blocks something specific
  2. Use plan or default permission mode in prod; never bypassPermissions
  3. Add PreToolUse hooks for audit and safety checks
  4. Use resume for multi-turn rather than rebuilding history yourself
  5. Connect MCP servers for ecosystem tools; don't reimplement GitHub/Slack tools by hand
  6. Keep system prompts short — big prompts cost per call (cache them)