Building your first agent with the Claude Agent SDK
The Claude Code SDK was renamed to the Claude Agent SDK — but the name change is less interesting than what you can build with it. Here’s a working guide.
SDK vs CLI vs Managed Agents — when to use which
| Agent SDK | Claude Code CLI | Managed Agents | |
|---|---|---|---|
| Use case | Custom apps, CI/CD, production automation | Interactive dev, one-off tasks | Long-running autonomous work |
| Language | Python, TypeScript | Terminal | API (Python, TS, curl) |
| Model selection | You pick per-agent | Session-level | You pick per-agent |
| Cost | API billing (pay per token) | Subscription | $0.08/hr + API tokens |
| Tools included | Read, Write, Edit, Bash, Glob, Grep, WebSearch, WebFetch | All of the above + Agent, Monitor | Same as SDK |
| When it’s best | You need programmatic control, CI integration, or multi-agent orchestration | Daily development, exploring codebases, manual tasks | Tasks that run for hours, need cloud infra, or run when your machine is off |
A working agent in 10 lines
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
async for message in query(
prompt="Find all TODO comments in this repo and summarize them",
options=ClaudeAgentOptions(allowed_tools=["Read", "Glob", "Grep"]),
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())
This agent reads your codebase, greps for TODOs, and summarizes — using the same tools that power Claude Code. No tool implementation needed.
Multi-agent: specialist delegation
async for message in query(
prompt="Use the security-reviewer to audit this codebase",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep", "Agent"],
agents={
"security-reviewer": AgentDefinition(
description="Security expert for code review",
prompt="Analyze for OWASP Top 10 vulnerabilities. Check for injection, auth issues, data exposure.",
tools=["Read", "Glob", "Grep"],
)
},
),
):
...
The main agent delegates to security-reviewer, which runs in its own context with restricted tools. Results flow back.
Hooks: intercepting agent behavior
async def block_dangerous_commands(input_data, tool_use_id, context):
cmd = input_data.get("tool_input", {}).get("command", "")
if any(danger in cmd for danger in ["rm -rf", "curl", "wget"]):
return {"decision": "block", "message": "Blocked dangerous command"}
return {}
options = ClaudeAgentOptions(
hooks={"PreToolUse": [HookMatcher(matcher="Bash", hooks=[block_dangerous_commands])]}
)
Hooks give you programmatic guardrails — block dangerous commands, log file changes, require approval for specific actions.
Key decisions
Use the SDK when: You’re building a product, running agents in CI, need multi-model routing, or want programmatic control over permissions and tool access.
Use the CLI when: You’re exploring a codebase, doing daily development, or want the fastest path to a working result.
Use Managed Agents when: You need cloud-hosted execution, long-running sessions, or Anthropic to handle the infrastructure.