TL;DR
There are two complementary ways to build agents with Claude:
- The Claude Agent SDK — a Python and TypeScript library that gives you the same agent loop, built-in tools, and context management that power Claude Code, runnable inside your own application. You call
query() (or ClaudeSDKClient) and Claude autonomously reads files, runs commands, edits code, and searches the web.
- Claude Code subagents — specialized assistants defined as Markdown files with YAML frontmatter. Each runs in its own context window with a focused system prompt, restricted tools, and an optional cheaper model. The main agent delegates matching tasks and gets back only a summary.
This guide shows a minimal SDK query() loop, the built-in tools you get for free, how to define and delegate to subagents, and how to control models and permissions.
Prerequisites
Knowledge: Basic Python or TypeScript and API experience
Tools: An Anthropic API key from the Console; Python 3.10+ for the Python SDK
Auth: export ANTHROPIC_API_KEY=your-api-key (the SDK also supports Amazon Bedrock, Google Vertex AI, and Microsoft Azure providers via environment variables)
What the Agent SDK gives you
The Agent SDK includes built-in tools for reading files, running commands, and editing code, so your agent can start working immediately without you implementing tool execution. This is the key difference from the Anthropic Client SDK, where you send prompts and write the tool-execution loop yourself.
Install it:
# Python (requires Python 3.10+)
pip install claude-agent-sdk
# TypeScript
npm install @anthropic-ai/claude-agent-sdk
The TypeScript SDK bundles a native Claude Code binary for your platform as an optional dependency, so you don't need to install Claude Code separately.
Step 1: A minimal query loop
query() runs a one-off task and yields messages as Claude works. This Python example asks the agent to fix a bug, pre-approving the Read, Edit, and Bash tools:
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) # Claude reads the file, finds the bug, edits it
asyncio.run(main())
The TypeScript equivalent uses the same shape:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Find and fix the bug in auth.ts",
options: { allowedTools: ["Read", "Edit", "Bash"] }
})) {
console.log(message); // Claude reads the file, finds the bug, edits it
}
For multi-turn conversations that keep context, use ClaudeSDKClient instead of query():
async with ClaudeSDKClient() as client:
await client.query("First question")
async for message in client.receive_response():
print(message)
await client.query("Follow-up question") # Same session context
async for message in client.receive_response():
print(message)
Step 2: Built-in tools
Everything that makes Claude Code powerful is available in the SDK. You enable tools by listing them in allowed_tools (Python) / allowedTools (TypeScript). Key built-in tools:
| Tool |
What it does |
| Read |
Read any file in the working directory |
| Write |
Create new files |
| Edit |
Make precise edits to existing files |
| Bash |
Run terminal commands, scripts, git operations |
| Glob |
Find files by pattern (**/*.ts, src/**/*.py) |
| Grep |
Search file contents with regex |
| WebSearch |
Search the web for current information |
| WebFetch |
Fetch and parse web page content |
Beyond tools, the SDK also exposes hooks (PreToolUse, PostToolUse, Stop, SessionStart, and more), MCP server connections, sessions you can resume or fork, and Claude Code's filesystem-based configuration (skills, commands, CLAUDE.md memory, and plugins) loaded from .claude/.
Step 3: Delegate to subagents
Subagents are specialized AI assistants that handle specific types of tasks. Each runs in its own context window with a custom system prompt, specific tool access, and independent permissions. When Claude encounters a task that matches a subagent's description, it delegates to that subagent, which works independently and returns results.
Subagents help you:
- Preserve context by keeping exploration and implementation out of your main conversation
- Enforce constraints by limiting which tools a subagent can use
- Reuse configurations across projects with user-level subagents
- Specialize behavior with focused system prompts for specific domains
- Control costs by routing tasks to faster, cheaper models like Haiku
Define a subagent as a file
Subagents are Markdown files with YAML frontmatter; the body becomes the subagent's system prompt. Save them to .claude/agents/ (project scope, check into version control) or ~/.claude/agents/ (available across all your projects). Only name and description are required:
---
name: code-reviewer
description: Reviews code for quality and best practices
tools: Read, Glob, Grep
model: sonnet
---
You are a code reviewer. When invoked, analyze the code and provide
specific, actionable feedback on quality, security, and best practices.
Claude uses the description to decide when to delegate, so write it clearly. You can also create and manage subagents interactively with the /agents command, which takes effect without a session restart (files edited directly on disk require a restart).
Define subagents from the Agent SDK
In the SDK, pass an agents map and include Agent in allowed_tools so subagent invocations are auto-approved:
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
async def main():
async for message in query(
prompt="Use the code-reviewer agent to review this codebase",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep", "Agent"],
agents={
"code-reviewer": AgentDefinition(
description="Expert code reviewer for quality and security reviews.",
prompt="Analyze code quality and suggest improvements.",
tools=["Read", "Glob", "Grep"],
)
},
),
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())
Claude Code also ships built-in subagents it uses automatically: Explore (a fast, read-only Haiku agent for codebase search), Plan (read-only research during plan mode), and general-purpose (all tools, for complex multi-step tasks).
Agent SDK vs subagents: when to use which
|
Agent SDK |
Claude Code subagents |
| What it is |
Python/TypeScript library that runs the agent loop in your process |
Markdown files that define specialized assistants within a session |
| Where it runs |
Your application / infrastructure |
Inside a Claude Code (or SDK) session, in an isolated context window |
| Best for |
Custom applications, CI/CD, production automation |
Offloading focused side tasks (search, review, debugging) to preserve main context |
| Configuration |
Code (ClaudeAgentOptions, AgentDefinition) |
YAML frontmatter (name, description, tools, model, ...) |
| Defined by |
query() / ClaudeSDKClient calls |
.claude/agents/*.md, ~/.claude/agents/*.md, /agents, or --agents JSON |
They are not mutually exclusive: an SDK agent can delegate to subagents, and subagents inherit the same built-in tools.
Step 4: Choose models and control permissions
Models. A subagent's model field accepts an alias (sonnet, opus, haiku, fable), a full model ID (for example claude-opus-4-8), or inherit. It defaults to inherit (the main conversation's model). Routing inexpensive, high-volume work to Haiku is the documented way to control cost.
Permissions. Control exactly which tools an agent can use so it can analyze without modifying, or require approval for sensitive actions. The main levers:
| Field (Python / frontmatter) |
Effect |
allowed_tools / tools |
Tools the agent may use (a read-only agent might list only Read, Glob, Grep) |
disallowedTools |
Tools to deny, removed from the inherited or specified list |
permission_mode / permissionMode |
default, acceptEdits, plan, bypassPermissions, and more |
max_turns / maxTurns |
Caps the number of agentic turns before the agent stops |
A read-only reviewer is simply an agent whose tool list contains only Read, Glob, and Grep — it can analyze but cannot edit or run commands.
Troubleshooting
Common issues and fixes
No matching distribution found for claude-agent-sdk
Your Python interpreter is older than 3.10. The Python package requires Python 3.10 or later. Check with python3 --version (macOS/Linux) or py --version (Windows).
Subagent edits to a file you didn't expect
The subagent inherited all tools because tools was omitted. List only the tools it needs (for a reviewer, the read-only set) to enforce least privilege.
A subagent file isn't picked up
Subagents are loaded at session start. If you add or edit a file directly on disk, restart your session. Subagents created through /agents take effect immediately.
Subagent never gets delegated to
Claude decides delegation from the description field. Make it specific about when the subagent should be used.
Authentication errors
Set ANTHROPIC_API_KEY as an environment variable, or configure a supported provider (Amazon Bedrock, Google Vertex AI, or Microsoft Azure) via its environment variables and credentials.
Safety and privacy
Agents run real tools autonomously. Before granting Bash, Edit, Write, or MCP servers, decide whether the task actually needs them and prefer the narrowest tool set. Keep your API key in an environment variable, never in prompts or committed code, and remember that WebFetch, WebSearch, and connected MCP servers can send project data to external systems.
Quick reference
- Install:
pip install claude-agent-sdk / npm install @anthropic-ai/claude-agent-sdk
- Run a task:
query(prompt=..., options=ClaudeAgentOptions(allowed_tools=[...]))
- Multi-turn:
ClaudeSDKClient with client.query() + client.receive_response()
- Subagent file:
.claude/agents/<name>.md with name + description frontmatter (required), optional tools and model
- Manage subagents interactively:
/agents
- Restrict capability:
allowed_tools / disallowedTools / permission_mode
Next steps
Sources: Claude Agent SDK overview, Python SDK reference, and Create custom subagents (code.claude.com).