What is the Claude Agent SDK? A Beginner's Primer for CCA-F Candidates
Piyush Palod
May 22, 2026
15 min read
10 views
A practical introduction to the Claude Agent SDK -- core concepts, Python and TypeScript code examples, hooks, MCP integration, forkSession, and exactly how this knowledge shows up on the CCA-F exam.
## What is the Claude Agent SDK?
The Claude Agent SDK is Anthropic's official library for building agents that use Claude as their reasoning core. It bundles the same agentic primitives that power Claude Code -- subagents, tool calling, lifecycle hooks, session management, MCP integration, and policy controls like `allowedTools` and `disallowedTools` -- into a programmable interface you can drop into your own application.
If the Messages API is how you talk to the model, the Agent SDK is how you build durable, tool-using, multi-step agents on top of it. It handles the boring parts -- the tool-use loop, session state, hook orchestration, MCP wiring -- so you can focus on the parts that are specific to your product.
The SDK ships in two officially supported languages: **Python** and **TypeScript**. Both expose the same conceptual model, so the API surface is intentionally narrow and recognisable across languages.
## Why the Agent SDK Matters
Before the Agent SDK, building a non-trivial Claude agent meant rebuilding the same five plumbing layers in every project: the tool-use loop, session persistence, permission gating, lifecycle hooks, and MCP wiring. Every team had a slightly different version, and every version had subtle bugs. The Agent SDK collapses that work into a few imports and a single declarative agent definition.
For the CCA-F exam specifically, the SDK matters because it sits at the intersection of three of the five exam domains: **Agentic Architecture and Orchestration (27%)**, **Claude Code Configuration and Workflows (20%)**, and **Tool Design and MCP Integration (18%)**. Roughly two thirds of the exam touches concepts the SDK exposes directly. You cannot afford to be vague about it.
## Core Concepts You Must Know
The SDK is built around six concepts. Learn these, and the rest of the API is a translation exercise.
### 1. The Agent
An **agent** is the top-level object: a Claude model plus a configuration that tells it which tools it can call, which hooks fire around its actions, which MCP servers it can talk to, and which policy constraints apply. You create an agent, hand it a query, and it runs the agentic loop until it produces a final answer or you stop it.
### 2. Sessions
A **session** is a persistent context for an agent's work. Sessions hold conversation history, tool-call records, and intermediate state. You can resume a session by ID, **fork** it to branch off an experiment without polluting the original thread, and compact it when context limits approach. Session management is what lets long-running agents actually be long-running.
### 3. Tools and Tool Definitions
A **tool** is a callable function exposed to the model with a JSON schema, a name, and a description. The model selects tools based primarily on description quality. Tools can come from three sources: ones you define inline in code, ones loaded from an MCP server, and built-in Anthropic-hosted tools like web search, code execution, and computer use.
### 4. allowedTools and disallowedTools
These two configuration knobs are the SDK's primary policy lever. `allowedTools` is a whitelist -- if set, only listed tools can be called. `disallowedTools` is a blacklist -- listed tools are blocked even if otherwise available. Used well, they keep agents inside a tight safety envelope. Used badly, they cause silent capability gaps that look like model failures.
### 5. Hooks
**Hooks** are user-supplied callbacks that fire at specific points in the agentic lifecycle. The SDK exposes the same hook event names Claude Code uses, so the mental model transfers cleanly between them: `PreToolUse`, `PostToolUse`, `Stop`, `SubagentStop`, `UserPromptSubmit`, `SessionStart`, `SessionEnd`, `PreCompact`, and `Notification`. Hooks are how you implement audit logs, cost ceilings, command blocking, and per-step instrumentation.
The full reference is at https://docs.claude.com/en/docs/agent-sdk/hooks.
### 6. Subagents
A **subagent** is an agent spawned by a parent agent to handle a narrowly scoped task. Subagents have their own context window, their own permission set (they do NOT inherit the parent's permissions), and their own session. They are the SDK's answer to the "do not build one giant agent" principle -- decompose a complex task into focused subagents, each with the minimal toolset it needs.
### 7. CLAUDE.md
The Agent SDK respects the same `CLAUDE.md` file convention used by Claude Code. A `CLAUDE.md` in the working directory is loaded as persistent project context for every conversation. The SDK supports the same tiered hierarchy (project, user, enterprise) and the same `@path/to/file.md` import syntax for composing larger memory bases.
### 8. MCP Integration
The SDK consumes MCP servers as first-class tool sources. You point the agent at one or more MCP servers via configuration, and the tools, resources, and prompts those servers expose become available to the model. Transports include **stdio, HTTP, SSE, and WebSocket** -- the same set as Claude Code.
## A First Agent in Python
The quickest way to grasp the SDK is to read a small but realistic example. Here is a minimal Python agent that uses one custom tool, blocks a dangerous one, and logs every tool call via a `PreToolUse` hook:
```python
from claude_agent_sdk import Agent, tool
@tool
def get_weather(city: str) -> str:
"""Return the current weather for a given city.
Args:
city: The city name, e.g. 'Bangalore' or 'San Francisco'.
"""
# Real implementation would call a weather API.
return f"It is 28 degrees and sunny in {city}."
async def log_tool_use(event):
print(f"[hook] {event.tool_name} called with {event.input}")
return {"allow": True}
agent = Agent(
model="claude-sonnet-4-6",
system="You are a helpful weather assistant.",
tools=[get_weather],
allowedTools=["get_weather"],
disallowedTools=["Bash", "Edit"],
hooks={
"PreToolUse": [log_tool_use],
},
)
async def main():
async for chunk in agent.query("What is the weather in Bangalore today?"):
print(chunk, end="")
import asyncio
asyncio.run(main())
```
A few things to notice:
- The `@tool` decorator turns a plain Python function into a tool definition. The docstring becomes the description the model uses for selection -- write it carefully.
- `allowedTools` and `disallowedTools` coexist. The blacklist wins on conflict.
- The `PreToolUse` hook receives an event object and returns a decision. Returning `{"allow": False, "reason": "..."}` blocks the tool call.
- `agent.query()` returns a streaming async iterator, not a single response.
## The Same Agent in TypeScript
The TypeScript SDK mirrors the Python surface. Here is the same agent, idiomatically:
```typescript
import { Agent, defineTool } from "@anthropic-ai/agent-sdk";
const getWeather = defineTool({
name: "get_weather",
description: "Return the current weather for a given city.",
inputSchema: {
type: "object",
properties: {
city: { type: "string", description: "The city name." },
},
required: ["city"],
},
async run({ city }) {
return `It is 28 degrees and sunny in ${city}.`;
},
});
const agent = new Agent({
model: "claude-sonnet-4-6",
system: "You are a helpful weather assistant.",
tools: [getWeather],
allowedTools: ["get_weather"],
disallowedTools: ["Bash", "Edit"],
hooks: {
PreToolUse: [
async (event) => {
console.log(`[hook] ${event.toolName} called with`, event.input);
return { allow: true };
},
],
},
});
for await (const chunk of agent.query("What is the weather in Bangalore today?")) {
process.stdout.write(chunk.toString());
}
```
The two SDKs are deliberately near-isomorphic. If you learn one, you can read code in the other within an hour.
## MCP Integration in Practice
MCP servers plug into the SDK declaratively. You declare them on the agent, and the model gets access to their tools, resources, and prompts as if they were native. Here is a Python example that wires up two MCP servers -- one local over stdio, one hosted over HTTP:
```python
agent = Agent(
model="claude-sonnet-4-6",
mcpServers={
"notes": {
"transport": "stdio",
"command": "python",
"args": ["./mcp_servers/notes_server.py"],
},
"crm": {
"transport": "http",
"url": "https://crm.internal/mcp",
"headers": {"Authorization": "Bearer ${CRM_TOKEN}"},
},
},
allowedTools=["notes__search", "notes__create", "crm__lookup_customer"],
)
```
Note the tool naming convention: MCP-exposed tools are namespaced as `{server_name}__{tool_name}`. Be explicit in `allowedTools` -- the wildcard pattern is easy to misconfigure under exam pressure.
In TypeScript, the shape is the same:
```typescript
const agent = new Agent({
model: "claude-sonnet-4-6",
mcpServers: {
notes: {
transport: "stdio",
command: "node",
args: ["./mcp-servers/notes-server.js"],
},
crm: {
transport: "http",
url: "https://crm.internal/mcp",
headers: { Authorization: `Bearer ${process.env.CRM_TOKEN}` },
},
},
allowedTools: ["notes__search", "notes__create", "crm__lookup_customer"],
});
```
For deeper MCP wiring patterns, the canonical reference is https://docs.claude.com/en/docs/agent-sdk/mcp.
## Forking Sessions
One of the SDK's quieter but more powerful features is `forkSession`. Forking creates a copy of an existing session, including its conversation history and accumulated state, that you can experiment on without touching the original. It is the equivalent of `git checkout -b` for an agent run.
The canonical use case: you have a long-running planning agent, and you want to try two competing follow-up strategies in parallel. Fork the session twice, run each variant, compare the outputs, then continue with the winner -- the original session is untouched.
```python
planning_session = await agent.create_session()
await planning_session.query("Draft a release plan for the v2 launch.")
variant_a = await planning_session.fork()
variant_b = await planning_session.fork()
async for chunk in variant_a.query("Optimise for speed of delivery."):
...
async for chunk in variant_b.query("Optimise for risk minimisation."):
...
```
In TypeScript:
```typescript
const planningSession = await agent.createSession();
await planningSession.query("Draft a release plan for the v2 launch.");
const variantA = await planningSession.forkSession();
const variantB = await planningSession.forkSession();
for await (const chunk of variantA.query("Optimise for speed of delivery.")) {
/* ... */
}
for await (const chunk of variantB.query("Optimise for risk minimisation.")) {
/* ... */
}
```
Forking is not free -- each branch has its own token budget -- but the productivity gain on exploratory work is significant. Expect at least one CCA-F scenario that hinges on whether you would fork or restart a session.
## Subagents in the SDK
Subagents are the SDK's primary tool for managing complexity. Instead of one giant agent with a thirty-tool catalogue, you build a parent agent that spawns focused subagents on demand.
```python
researcher = Agent(
model="claude-haiku-4-5",
system="You are a research subagent. Search and summarise.",
allowedTools=["web_search", "notes__search"],
)
writer = Agent(
model="claude-opus-4-7",
system="You are a writer subagent. Produce final prose.",
allowedTools=["notes__create"],
)
async def cost_tracker(event):
print(f"[cost] subagent {event.subagent_name} used {event.tokens_used} tokens")
orchestrator = Agent(
model="claude-sonnet-4-6",
system="You are an orchestrator. Delegate research and writing.",
subagents={"researcher": researcher, "writer": writer},
hooks={"SubagentStop": [cost_tracker]},
)
```
Three things the CCA-F exam consistently tests on subagent design:
1. **Subagents do not inherit parent permissions.** Each subagent re-declares its own `allowedTools` and `disallowedTools`. Forgetting this is the single most common bug.
2. **Pick the right model per subagent.** A cheap classifier subagent should be Haiku 4.5. A deep-reasoning writer subagent earns Opus 4.7. The orchestrator is usually Sonnet 4.6.
3. **Instrument with `SubagentStop`.** Per-subagent cost tracking is impossible without it. The exam will hand you a scenario where this hook is the right answer.
## Architectural Patterns
You should recognise three multi-agent patterns by name and be able to argue when each applies:
- **Hub-and-spoke** -- one orchestrator dispatches to many specialised subagents. Best when the subtasks are heterogeneous and independent. Easiest to debug.
- **Orchestrator-worker** -- one orchestrator drives a small worker pool, often with shared state or queued tasks. Best when the same subtask type repeats and parallelism matters.
- **Peer-to-peer handoff** -- agents pass control to each other based on routing rules, with no central coordinator. Best when the workflow is naturally pipelined and stages are well-defined. Hardest to reason about.
The SDK does not impose a pattern. You build the topology you want by combining agents, subagents, sessions, and hooks. Knowing which pattern fits a given scenario is more valuable than knowing the SDK's API surface.
## Common Pitfalls
These trip people up in production, and they show up on the exam:
1. **Vague tool descriptions.** Two tools with overlapping descriptions cause routing errors that look like model failures. Fix the descriptions, not the model.
2. **Forgetting `disallowedTools` precedence.** A tool listed in both `allowedTools` and `disallowedTools` is blocked. The blacklist always wins.
3. **Loading too many tools.** Over a certain count, tool selection accuracy degrades. Use `defer_loading` and tool search to keep large catalogues out of the active context.
4. **Skipping the `PreCompact` hook on long sessions.** Compaction can drop intermediate state you needed. A `PreCompact` snapshot is cheap insurance.
5. **Picking Opus 4.7 by default.** Cost compounds quickly across subagents. The right starting model for an agent is usually Sonnet 4.6; promote to Opus only when reasoning depth justifies it; demote to Haiku 4.5 when latency and cost dominate.
6. **Treating subagents as inherited.** They are not. Every subagent declares its own tools and hooks.
7. **Confusing SDK hooks with Claude Code hooks.** Event names overlap, payloads do not. Know which one a scenario question is asking about.
8. **Not using `forkSession` for experiments.** Branching is cheap. Polluting your main session with throwaway queries is expensive.
## How the Agent SDK Shows Up on CCA-F
The SDK is woven through three of the five domains. Expect questions in roughly these shapes:
- **Agentic Architecture and Orchestration (27%)** -- scenarios that ask you to pick the right topology (hub-and-spoke vs orchestrator-worker vs peer-to-peer), assign the right model per subagent, and choose the right hook for an observability requirement. `forkSession`, `SubagentStop`, and `PreCompact` come up often.
- **Claude Code Configuration and Workflows (20%)** -- scenarios that test whether you know which hook event name and payload belong to the SDK vs Claude Code, and how `CLAUDE.md` composes across project, user, and enterprise scope.
- **Tool Design and MCP Integration (18%)** -- scenarios on tool description quality, `allowedTools` vs `disallowedTools` precedence, MCP transport choice, and namespaced tool naming.
No single question will ask you to write SDK code from scratch, but several will test whether you can read a code snippet and identify the bug or the better alternative. That is the right level to study at -- read fluently, diagnose quickly.
If you want to test that skill under realistic conditions, the CCA-F practice exam at https://www.prepmycert.com/course/ccaf-claude-certified-architect-foundations has scenario sets built specifically around SDK code reads and subagent-design decisions.
## A Mental Model That Stops You Getting Lost
When you read SDK code under exam pressure, hold this three-layer mental model:
1. **The agent** -- model, system prompt, policy (`allowedTools`, `disallowedTools`), tools, MCP servers, hooks. This is the static configuration.
2. **The session** -- conversation history, accumulated state, tool-call log. This is what the agent operates on. Forkable. Resumable. Compactable.
3. **The loop** -- model call, tool execution, observation, repeat. This is what the SDK runs for you. Hooks fire at fixed points inside the loop. You configure the loop, the SDK runs it.
Every SDK question can be located inside one of these three layers. When you spot the layer, the answer usually becomes obvious.
## Frequently Asked Questions
### Is the Claude Agent SDK the same as Claude Code?
No. They share concepts -- the same hook event names, the same `CLAUDE.md` convention, the same MCP integration model -- but Claude Code is the interactive CLI and the Agent SDK is the programmable library. You can build an agent that behaves like Claude Code using the SDK, but Claude Code itself is a separate product. CCA-F tests both, separately and in combination.
### Which language should I use, Python or TypeScript?
Whichever you ship in day to day. The two SDKs are deliberately near-isomorphic, and exam scenarios show pseudo-code rather than language-specific syntax. Pick one and become fluent rather than splitting your time.
### Do I need to memorise every SDK API name?
No. You need to recognise the core ones -- `Agent`, `query`, `tools`, `allowedTools`, `disallowedTools`, `mcpServers`, `hooks`, `forkSession`, `createSession` -- and what they do. You do not need to recite every keyword argument by heart.
### How does the Agent SDK relate to the Messages API?
The SDK is built on top of the Messages API. Under the hood, every agent turn becomes one or more Messages API calls, plus the SDK's tool-use loop, hook orchestration, and session state. You can use the Messages API directly without the SDK -- you just rebuild the agentic plumbing yourself. The SDK exists so you do not have to.
### When should I NOT use the Agent SDK?
For single-shot prompts with no tool use, the Messages API is simpler and lighter. For interactive coding workflows, Claude Code is the right surface. The SDK shines when you need programmatic agents with tools, multi-turn sessions, hooks, or subagents inside your own application.
### What is the difference between a tool defined in code and one from an MCP server?
Functionally, none -- the model treats them the same. Operationally, MCP-sourced tools are namespaced (`{server}__{tool}`), live in a separate process, can be developed and deployed independently, and can be shared across multiple agents and across Claude Code. Code-defined tools are tightly coupled to the agent that owns them. Use MCP when the tool surface is reusable or owned by a different team; use inline tools when the tool is bespoke to one agent.
### How do hooks interact with subagents?
Hooks declared on the parent agent fire on the parent's lifecycle. Hooks declared on a subagent fire on the subagent's lifecycle. The `SubagentStop` event is the special bridge -- it fires on the parent when a subagent completes, which is the cleanest place to track per-subagent cost and outcome. Master this distinction and at least one exam question will fall into your lap.
### Is there an official SDK reference I should bookmark?
Yes -- https://docs.claude.com/en/docs/agent-sdk for the overview, https://docs.claude.com/en/docs/agent-sdk/hooks for the full lifecycle map, and https://docs.claude.com/en/docs/agent-sdk/mcp for MCP wiring patterns. These three URLs cover most of the SDK surface area tested on CCA-F.
## Where to Go Next
If the SDK still feels abstract, the fastest cure is to write one. Spend 90 minutes building the weather agent from this primer in your language of choice, then add a `PreToolUse` hook, then spawn a subagent. The concepts that read as jargon on the page become reflex once you have shipped them once.
When you are ready to test SDK fluency under exam conditions, take the CCA-F practice exam at https://www.prepmycert.com/course/ccaf-claude-certified-architect-foundations. The scenario sets are built around the same code-reading and architectural-decision skills the real exam rewards.
Good luck. Read every scenario twice -- including the code.
Join 10,000+ IT professionals preparing for their certifications. Get 20 free practice questions, exam tips, and exclusive discounts delivered to your inbox!