Claude Certification Guides
CCDV-F/Domain 19 min read

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

ApproachPackageYou writeTools available
Manual loopanthropic / @anthropic-ai/sdkThe whole while stop_reason == "tool_use" loopOnly tools you define
Tool runnersame SDK, client.beta.messages.tool_runner / toolRunnerJust the tool functionsOnly tools you define
Claude Agent SDKclaude-agent-sdk / @anthropic-ai/claude-agent-sdkA prompt plus optionsBuilt-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_tools restrict which built-in tools the agent may call. A read-only reviewer should not have Write, Edit or Bash.
  • permission_mode controls how tool calls are approved. default prompts according to permission rules, acceptEdits auto-approves file edits, plan lets the agent plan without acting, and bypassPermissions skips checks entirely and should only be used in sandboxed environments.
  • system_prompt replaces or extends the default. The SDK also supports a preset that reuses Claude Code's own system prompt with your additions appended.
  • mcp_servers attaches MCP servers (stdio commands or remote URLs) so their tools appear alongside the built-ins. MCP tools are named mcp__<server>__<tool> and must be included in allowed_tools to be callable without prompting.
  • cwd scopes file tools to a directory; max_turns bounds the loop; model selects the model.
  • hooks run 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 as allowed_tools, permission_mode, system_prompt, mcp_servers, cwd and max_turns.
  • permission_mode values include default, acceptEdits, plan and bypassPermissions; 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. 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. 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. 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. 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. 5.How does a developer make the tools of an MCP server available to an Agent SDK agent?