Claude Agent SDK — first contact with building your own agent
The Claude Agent SDK lets you write your own agent on the Claude API with the full tool apparatus. Showing first impressions — what surprises, where the value is, when to pick the SDK over Claude Code.

Anthropic's Agent SDK is a toolkit for building your own agent on the Claude API. It doesn't replace Claude Code, but it lets you build one from scratch for a specific use case. After a week of experimenting, here are first observations.
What it is
The Agent SDK wraps Claude API + tool use + state management in a comfortable API. Instead of hand-rolling a "send message → tool call → response → continue" loop, you get an Agent class:
from anthropic.agent import Agent
agent = Agent(
model="claude-opus-4-7",
tools=[bash_tool, file_tool, web_search],
system="You are a code reviewer. Focus on security."
)
result = await agent.run(
"Review the auth flow in my repo",
max_turns=20
)The SDK manages:
- the tool use loop
- prompt caching
- conversation compaction when it gets long
- error handling
- output streaming
Why not Claude Code
Claude Code = a universal agent for developers. Agent SDK = you build a narrow specialist.
| Claude Code | Agent SDK | |
|---|---|---|
| Use case | any dev work | specific domain |
| Audience | you | your app's users |
| Tools | all | the ones you pick |
| State | session-based | however you want |
| UI | terminal | your own |
Pick the SDK when you're building a product with a narrow scope. E.g., "agent that does research for cold outreach" or "agent that analyzes UI screenshots and suggests fixes".
My first use case: outreach researcher
I built a simple agent that, for a given company, gathers research:
from anthropic.agent import Agent
from anthropic.tools import web_search, bash, file_write
researcher = Agent(
model="claude-sonnet-4-6",
tools=[web_search, bash, file_write],
system="""You research companies for cold outreach.
For each input company:
1. Search web for their site, social media, recent news
2. Extract: name, address, services, brand voice signals
3. Save to /tmp/research/{slug}.json
Return ONLY the JSON path. No commentary."""
)
result = await researcher.run(
"Research: Pasieka Przygórze, Mszana Dolna, Poland"
)
print(result.output) # /tmp/research/pasieka-przygorze.jsonThe agent gets a minimal system prompt + 3 tools. No Bash with full system access, no file editing, only search, write and bash.
Custom tools
The SDK lets you define your own:
from anthropic.tools import tool
@tool
async def vikunja_create_task(
title: str,
project_id: int,
due_date: str | None = None
) -> dict:
"""Create a task in Vikunja."""
response = await httpx.post(
f"{VIKUNJA_URL}/api/v1/projects/{project_id}/tasks",
json={"title": title, "due_date": due_date},
headers={"Authorization": f"Bearer {VIKUNJA_TOKEN}"}
)
return response.json()
agent = Agent(
tools=[vikunja_create_task],
system="..."
)The @tool decorator generates JSON schema for the Claude API. Type hints are used to validate arguments.
Hooks — pre/post tool execution
I can intercept every tool call:
@agent.before_tool
async def log_tool_use(tool_name: str, args: dict):
print(f"[{datetime.now()}] {tool_name}({args})")
@agent.after_tool
async def validate_result(tool_name: str, result):
if tool_name == "bash" and "rm -rf" in str(result.command):
raise ValueError("Destructive command blocked")Similar to Claude Code hooks, but in Python and I control the integration.
Cost: how it stacks up
Per request the SDK costs the same as Claude Code, same underlying API. Difference: in the SDK you see every turn, can batch, can limit max_turns aggressively.
result = await agent.run(
"Research 50 companies in batch",
max_turns=200, # cap
model="claude-haiku-4-5" # cheaper for batch
)
print(f"Total cost: ${result.usage.total_cost}")My researcher: ~$0.05 per company. For a batch of 50 = $2.50. Reasonable.
What the SDK does NOT do
1. No magical memory. Every agent.run() is a fresh session by default. For persistence, save result.history and pass it in the next call.
2. No plan mode. Plan mode is a Claude Code feature, not the SDK. You could implement a similar flow by hand, but boilerplate.
3. No sub-agents out of the box. You can do nested agent.run() calls, but no built-in "spawn child agent" like Agent(...) in Claude Code.
When NOT to use the SDK
1. Personal workflow. Claude Code is enough. The SDK = overhead without added value.
2. One-off scripts. Direct API call is simpler.
3. If you have no concrete user-facing use case. The SDK makes sense when you're building a product. Without a product = form over substance.
When TO use it
1. SaaS feature powered by an agent. E.g., adding "AI assistant" to your app.
2. Narrow-domain agent. Cold outreach researcher, code review bot, customer support agent.
3. Multi-tenant with different users. Each with different context, the SDK gives you state management.
What I'd do differently
After a week:
1. I'd start with Sonnet 4.6, not Opus. For narrow tasks the quality difference is small, cost is 3× lower.
2. I'd write tools defensively. Every tool gets argument validation. The agent sometimes drops in weird values.
3. I'd log EVERY tool call. In production, without that you can't debug what went wrong. The before_tool hook is the standard pattern.
The Agent SDK isn't a competitor to Claude Code, it's a complement. Claude Code for personal work, SDK for a product. Week-one experiments gave me a working cold-outreach researcher. Entry barrier: ~3 hours of docs + ~5 hours of writing.