Lesson 1.3
Agent SDK Basics
What the Claude Agent SDK is, how it differs from the Messages API tool runner, and how to run a first query with permissions, tools and MCP servers configured.
The Claude Agent SDK packages the same harness that powers Claude Code into a library you can call from Python or TypeScript. Instead of writing an agent loop and inventing file, shell and search tools, you hand the SDK a prompt and a set of options and it runs the whole thing. The exam tests whether you can tell the Agent SDK apart from the Messages API and its tool runner, and whether you know the core configuration knobs.
Three ways to build an agent
| Approach | Package | You write | Tools available |
|---|---|---|---|
| Manual loop | anthropic / @anthropic-ai/sdk | The whole while stop_reason == "tool_use" loop | Only tools you define |
| Tool runner | same SDK, client.beta.messages.tool_runner / toolRunner | Just the tool functions | Only tools you define |
| Claude Agent SDK | claude-agent-sdk / @anthropic-ai/claude-agent-sdk | A prompt plus options | Built-in Read, Write, Edit, Bash, Glob, Grep, WebSearch, WebFetch, plus MCP and subagents |
The first two are thin layers over POST /v1/messages. The Agent SDK is a different product with its own documentation at code.claude.com; it manages the loop, context, permissions, hooks and sessions for you. All three leave hosting and deployment to you.
A first query
The SDK is installed with pip install claude-agent-sdk or npm install @anthropic-ai/claude-agent-sdk. It authenticates with the same ANTHROPIC_API_KEY environment variable as the base SDK (and can also use Bedrock or Vertex credentials when configured).
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
options = ClaudeAgentOptions(
system_prompt="You are a careful code reviewer.",
allowed_tools=["Read", "Grep", "Glob"],
permission_mode="default",
cwd="/path/to/repo",
max_turns=10,
)
async for message in query(prompt="Find unused exports in src/", options=options):
print(message)
asyncio.run(main())
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Find unused exports in src/",
options: {
systemPrompt: "You are a careful code reviewer.",
allowedTools: ["Read", "Grep", "Glob"],
permissionMode: "default",
cwd: "/path/to/repo",
maxTurns: 10,
},
})) {
console.log(message);
}
query() returns an async iterator of messages: assistant text, tool calls, tool results, system events and a final result message carrying cost and usage. You consume it as a stream rather than waiting for one blob.
The options that matter
allowed_tools/disallowed_toolsrestrict which built-in tools the agent may call. A read-only reviewer should not haveWrite,EditorBash.permission_modecontrols how tool calls are approved.defaultprompts according to permission rules,acceptEditsauto-approves file edits,planlets the agent plan without acting, andbypassPermissionsskips checks entirely and should only be used in sandboxed environments.system_promptreplaces or extends the default. The SDK also supports a preset that reuses Claude Code's own system prompt with your additions appended.mcp_serversattaches MCP servers (stdio commands or remote URLs) so their tools appear alongside the built-ins. MCP tools are namedmcp__<server>__<tool>and must be included inallowed_toolsto be callable without prompting.cwdscopes file tools to a directory;max_turnsbounds the loop;modelselects the model.hooksrun your code at lifecycle points such as before or after a tool call, which is how you add logging, blocking rules or custom approval flows.
Sessions, subagents and custom tools
Each query() call creates a session with an ID. Passing resume with that ID continues the conversation with its context intact, which is how you build multi-turn agents without managing history yourself. Subagents are defined in options as named agents with their own prompts and tool lists, and the main agent delegates to them through the Task tool. For custom tools you can either define an in-process MCP server with the SDK's helper (create_sdk_mcp_server in Python, createSdkMcpServer in TypeScript) or attach an external MCP server.
When to pick which
Use the Agent SDK when you want a coding or filesystem agent quickly, when built-in tools cover most of the work, or when you want Claude Code's permission and hook model in your own application. Use the Messages API with a manual loop or tool runner when you need to own every tool, avoid a dependency on the Claude Code harness, or run in an environment where shell and file access would be inappropriate. The two are not interchangeable: do not substitute one for the other when a specification names a specific surface.
Exam focus
- The Claude Agent SDK is a separate package (
claude-agent-sdk/@anthropic-ai/claude-agent-sdk) that embeds the Claude Code harness; the tool runner is part of the regular Anthropic SDK. - The Agent SDK supplies built-in tools (Read, Write, Edit, Bash, Glob, Grep, WebSearch, WebFetch); the Messages API provides only the tools you define.
query()streams messages asynchronously and accepts options such asallowed_tools,permission_mode,system_prompt,mcp_servers,cwdandmax_turns.permission_modevalues includedefault,acceptEdits,planandbypassPermissions; the last is for sandboxes only.- MCP tools surface as
mcp__<server>__<tool>and must be allow-listed; hooks let you intercept tool calls. - Neither the Agent SDK nor the tool runner hosts your agent; deployment remains your responsibility.
Check yourself
5 questions
1.What does the Claude Agent SDK (@anthropic-ai/claude-agent-sdk or claude-agent-sdk for Python) provide that the plain Anthropic SDK (@anthropic-ai/sdk or anthropic) does not?
2.A developer runs: import { query } from "@anthropic-ai/claude-agent-sdk"; for await (const msg of query({ prompt: "Fix the failing unit tests", options: { allowedTools: ["Read", "Grep"] } })) { console.log(msg); } The agent explains the fix but reports it cannot modify any files. Why?
3.To stop permission prompts, a developer sets options.permissionMode to "bypassPermissions" for an Agent SDK agent that runs on a shared build server with access to production credentials. What is the risk?
4.A Python developer calls query() twice: async for m in query(prompt="Read config.yaml and remember the DB host"): ... async for m in query(prompt="What was the DB host?"): ... The second run says it has no idea. How should the code be changed so the agent keeps context between turns?
5.How does a developer make the tools of an MCP server available to an Agent SDK agent?
