Skip to content

The Agent SDK — Programmatic Control

Go beyond the CLI. The Python and TypeScript SDKs let you build custom applications that control Claude Code as a library. Automation at the API level.

The CLI is great for interactive work. You sit at your terminal, type prompts, watch Claude go. But what about when you want Claude Code running inside your own application? In a CI pipeline, powering a custom dev tool, or as part of a larger automation system where no human is involved?

That's the Agent SDK. Everything Claude Code can do, packaged as a library for Python or TypeScript. Same tools, same agent loop, same autonomous behavior. Programmatic instead of interactive.

What This Actually Is

The Agent SDK (formerly the Claude Code SDK) exposes the full agent runtime as a library. Call a function, pass a prompt, get back a stream of messages as Claude reads files, runs commands, edits code, and works toward your goal.

Don't confuse this with the Anthropic Client SDK. That gives you raw API access where you send messages, get responses, and implement the tool loop yourself. The Agent SDK handles all of that. Claude decides which tools to call, executes them, streams results back. You're delegating work to an agent, not orchestrating API calls.

Installation

Python:

pip install claude-agent-sdk

TypeScript:

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

For authentication, set your API key as an environment variable:

export ANTHROPIC_API_KEY=your-api-key

Cloud providers work too. Set CLAUDE_CODE_USE_BEDROCK=1 for AWS, CLAUDE_CODE_USE_VERTEX=1 for Google, or CLAUDE_CODE_USE_FOUNDRY=1 for Azure. Same SDK, different backend.

The Core Pattern: query()

Everything starts with query(). Pass a prompt and options, get back an async iterator of messages. Each message is something Claude did or said during execution.

Python:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
 
async def main():
    async for message in query(
        prompt="Find and fix the bug in auth.py",
        options=ClaudeAgentOptions(allowed_tools=["Read", "Edit", "Bash"]),
    ):
        print(message)
 
asyncio.run(main())

TypeScript:

import { query } from "@anthropic-ai/claude-agent-sdk";
 
for await (const message of query({
  prompt: "Find and fix the bug in auth.py",
  options: { allowedTools: ["Read", "Edit", "Bash"] }
})) {
  console.log(message);
}

The allowed_tools parameter is your control surface. Only want Claude reading files, never running shell commands? Pass ["Read", "Glob", "Grep"]. Full control over what the agent can touch.

Built-In Tools

Same tools as the CLI: Read, Write, Edit, Bash, Glob, Grep, WebSearch, WebFetch, and AskUserQuestion (for interactive applications where you want the agent to ask the user something).

You don't implement these. The SDK handles execution internally. Claude decides when and how to call them.

Beyond Basics: Hooks, Subagents, and MCP

Everything from the CLI works here too, but a few things are especially useful when you're writing code against the SDK.

Hooks let you intercept tool calls. PreToolUse fires before a tool runs (block dangerous shell commands here), PostToolUse fires after completion (log every file edit here), Stop fires when the agent finishes. Attach logic to any lifecycle event.

Subagents are the genuinely powerful bit. Define custom agents with their own tool sets and instructions. Your main agent delegates subtasks to specialized subagents, each with a narrow focus. Think: one subagent for writing tests, another for documentation, a third for security scanning.

MCP connections work exactly like in the CLI. Custom tools, data sources, everything.

Session management lets you resume previous sessions or fork them into new tasks with the same context. And configuration loading with setting_sources=["project"] reads your CLAUDE.md files, skills, and plugins, so the SDK respects the same filesystem-based config as the CLI.

Try It: A Simple Code Review Bot

A practical example. Script that reviews the latest commit and prints feedback:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
 
async def review_changes():
    prompt = (
        "Run 'git diff HEAD~1' to see the latest commit changes. "
        "Review the diff for bugs, security issues, and style problems. "
        "Print a concise review with specific line references."
    )
    async for message in query(
        prompt=prompt,
        options=ClaudeAgentOptions(
            allowed_tools=["Bash", "Read", "Glob", "Grep"],
        ),
    ):
        if hasattr(message, "content"):
            print(message.content)
 
asyncio.run(review_changes())

Run this in a GitHub Actions workflow, trigger it on every PR, post the review as a comment. Claude handles the reasoning. Your code handles the plumbing.

SDK vs CLI: When to Use Which

CLI for interactive work. Sitting at your computer, solving problems in real time, pair programming with Claude.

Agent SDK for programmatic control. CI/CD pipelines, custom dev tools, automated workflows, anything where Claude runs without a human at the keyboard.

Anthropic Client SDK (not the Agent SDK) for raw API access without the agent loop. Chatbots, text classification, summaries. If you don't need autonomous tool use, you don't need the Agent SDK.

Keep those three straight. The Agent SDK gives you the full Claude Code runtime as a Python/TypeScript library. query() takes a prompt, streams messages as Claude works, and you control which tools it can access. Hooks, subagents, MCP, session management all carry over from the CLI. Everything extends.

Mastering Claude Code

Lesson 61 of 70