The Claude Agent SDK

Claude Code · Expert · 16 min

When a CLI script is not enough, the SDK lets you build custom agents on the same engine with full programmatic control.

The Claude Agent SDK (formerly the Claude Code SDK) is Claude Code as a library. It gives your program the same agent loop, built-in tools, context management, permissions, sessions, hooks, subagents, MCP support and skills, from Python or TypeScript. Compare the options:

  • the CLI with -p: quickest for scripts and CI, any language via a subprocess,
  • the Agent SDK: an agent inside your own application, with callbacks and typed messages,
  • the plain Claude API client SDKs: you write the tool loop yourself.

In Python, install claude-agent-sdk (Python 3.10+); the TypeScript package is @anthropic-ai/claude-agent-sdk. The entry point query() is an async function that yields messages as the agent works: assistant text, tool use, tool results and a final result with cost. Options go in ClaudeAgentOptions:

  • allowed_tools: tools approved automatically (it does not remove others; use disallowed_tools for that),
  • permission_mode: for example acceptEdits or dontAsk,
  • cwd: the project directory,
  • system_prompt, max_turns, MCP servers and more.

For two-way conversations, custom tools written as Python functions and hooks as callbacks, use ClaudeSDKClient. The SDK loads skills, commands and memory from .claude/ like the CLI does unless you configure otherwise.

Authentication for products you build uses an API key (ANTHROPIC_API_KEY) or a cloud provider, not a personal claude.ai login. Treat an SDK agent like any service with shell access: run it in a container, give it minimal tools and credentials, cap turns and budget, and log its actions.

Example

# pip install claude-agent-sdk     (needs ANTHROPIC_API_KEY)
import anyio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock

async def main():
    options = ClaudeAgentOptions(
        cwd="/srv/repos/billing",
        allowed_tools=["Read", "Grep", "Glob", "Bash(pytest *)"],
        permission_mode="dontAsk",      # anything not allowed is denied
        system_prompt="You are a careful maintenance bot. Never edit tests.",
        max_turns=15,
    )
    async for message in query(prompt="Run pytest and summarize failures by root cause",
                               options=options):
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(block.text)

anyio.run(main)

Remember

  • The Agent SDK exposes Claude Code's loop, tools, permissions and hooks as a library
  • Python: query() streams messages; configure with ClaudeAgentOptions
  • allowed_tools auto-approves; it doesn't remove tools, so also set permission_mode or disallowed_tools

Watch out for

  • Assuming allowed_tools is a whitelist that hides every other tool; unlisted tools fall through to the permission mode.

Check yourself

  1. You need a custom agent inside a Python web service with callbacks for tool approval. Which fits best?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: code.claude.com/docs/en/agent-sdk/overview

Builds on

Unlocks

Nothing builds on this yet.