# Building Agents: Client SDK vs Agent SDK vs Managed Agents

> Anthropic gives developers three layers for building a Claude agent, and they are NOT interchangeable names for the same thing: the Client SDK / Messages API (you write the tool loop yourself), the Claude Agent SDK (Claude drives the loop autonomously inside your own process, pip install claude-agent-sdk / npm install @anthropic-ai/claude-agent-sdk), and Claude Managed Agents (a hosted REST API where Anthropic runs the loop and the sandbox). The common path is prototype on the Agent SDK, then migrate to Managed Agents for unattended production workloads - and hooks are an Agent SDK/Claude Code construct, not something that carries over to a Managed Agents session.

**Domain:** CCDVF-D1 · Agents & Workflows (14.7% of the exam)
**Canonical:** https://claudearchitectcertification.com/concepts/agent-construction-with-claude-agent-sdk
**Last reviewed:** 2026-05-04

## Quick stats

- **Build layers:** 3 (Client SDK / Agent SDK / Managed Agents)
- **Exam domain:** CCDVF-D1
- **Managed Agents beta header:** managed-agents-2026-04-01
- **Managed Agents eligible for ZDR/HIPAA BAA:** No
- **Hook lifecycle categories:** 5 (session/turn/tool/subagent/compaction)

## What it is

Anthropic exposes three distinct layers for building a Claude-powered agent, and this objective tests picking the right one for a given deployment, not memorizing one API. The Client SDK / Messages API is direct model access: you write the while response.stop_reason "tool_use" loop yourself and execute every tool call in your own code. The Claude Agent SDK is "the same tools, agent loop, and context management that power Claude Code, programmable in Python and TypeScript" - Claude autonomously drives tool execution inside a process you still own and deploy. Claude Managed Agents is a beta, hosted REST API where Anthropic runs both the agent loop and the sandbox; your application only sends events and streams back results over SSE.

These layers share primitives - a model call, tool definitions, optional MCP servers - but differ in who owns the loop and where state lives. The Agent SDK's session state is JSONL on your own filesystem; Managed Agents' session state is an Anthropic-hosted event log, persisted server-side and fetchable in full. That distinction drives almost every other tradeoff on this page: what you can self-host, whether hooks apply, and whether the deployment can meet Zero Data Retention.

## How it works

Client SDK vs Agent SDK is a one-line contrast the docs make explicit. With the Client SDK: response = client.messages.create(...); while response.stop_reason "tool_use": result = your_tool_executor(...); response = client.messages.create(tool_result=result, ...) - you own every iteration. With the Agent SDK: async for message in query(prompt="Fix the bug in auth.py", options=ClaudeAgentOptions(allowed_tools=["Read","Edit","Bash"])): print(message) - Claude reads the file, finds the bug, and edits it without you writing a dispatch loop. Built-in tools ship with zero tool-execution code: Read, Write, Edit, Bash, Monitor (watch a background script and react to each output line), Glob, Grep, WebSearch, WebFetch, and AskUserQuestion.

Subagents, MCP, permissions, and sessions are Agent SDK constructs configured through ClaudeAgentOptions. Subagents are declared with AgentDefinition(description=..., prompt=..., tools=[...]) inside an agents={} dict, and must be invoked via the Agent tool - so "Agent" has to appear in allowed_tools or the subagent never fires; messages emitted inside a subagent's context carry a parent_tool_use_id for tracing. MCP servers wire in as mcp_servers={"playwright": {"command": "npx", "args": ["@playwright/mcp@latest"]}} - external tool servers become callable inside the same loop with no custom glue. allowed_tools pre-approves specific tools; permission_mode="acceptEdits" is another supported mode for auto-approving file edits. Sessions resume via options=ClaudeAgentOptions(resume=session_id), where session_id is captured from the first query's SystemMessage with subtype "init" - full prior context carries forward without you re-sending history.

Hooks are deterministic actions independent of model compliance, and they run through two structurally different mechanisms that share event names but not a wire contract - conflating them is the single most common mistake on this topic. Lifecycle events span once-per-session (SessionStart, SessionEnd), once-per-turn (UserPromptSubmit, Stop), per-tool-call (PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, plus more), subagent (SubagentStart, SubagentStop), and compaction (PreCompact, PostCompact) categories, but not every event is registerable both ways. Claude Agent SDK hooks are in-process Python/TypeScript callbacks registered via HookMatcher(matcher="Edit|Write", hooks=[callback]) inside ClaudeAgentOptions/options.hooks. Each callback receives (input_data, tool_use_id, context) and returns a structured dict directly to the SDK - there is no process boundary, no exit code, and no stdout parsing. Top-level fields (systemMessage, continue) apply to every event; a PreToolUse callback blocks or allows the call by setting hookSpecificOutput.permissionDecision to "allow", "deny", or "ask" (the TypeScript SDK also supports "defer"; the Python SDK is allow/deny/ask), and returning {} allows the operation unchanged. Claude Code command hooks are a separate mechanism: shell commands configured in .claude/settings.json that Claude Code launches as external processes and that report back over stdout plus the process exit code - exit 0 means stdout is parsed as JSON, exit 2 is the blocking signal (stderr is fed back to Claude as an error message and stdout is ignored), and any other exit code is a non-blocking error. StopFailure is a documented Claude Code hook event (fires when a turn ends on an API error) but is not one of the Agent SDK's in-process callback events - it isn't something an SDK HookMatcher callback receives, so don't cite it as SDK-native. Never blend the two: an in-process SDK callback never has an "exit code," and a Claude Code shell command hook never returns a Python dict. For the day-to-day PreToolUse/PostToolUse enforcement pattern (deterministic gate vs. audit trail), see the dedicated hooks page - see Study Next.

Managed Agents is a different runtime with its own core concepts and its own governance mechanism, not hooks. Its four building blocks are Agent (model + system prompt + tools + MCP servers + skills), Environment (an Anthropic-managed cloud sandbox, or a self-hosted sandbox on your own infrastructure), Session (a running agent instance), and Events (the messages exchanged between your app and the agent). Self-hosted sandboxes move tool execution onto infrastructure you control, but orchestration stays on Anthropic's side under a shared-responsibility model - Anthropic still secures the control plane: session/queue integrity and multi-tenant isolation. All Managed Agents calls require the managed-agents-2026-04-01 beta header, and because sessions are stateful by design (server-persisted conversation history, sandbox state, and outputs), Managed Agents is not currently eligible for Zero Data Retention or HIPAA BAA coverage - a hard constraint for regulated workloads, distinct from anything about hooks or tool access. Per-tool governance on a Managed Agents session runs through always_allow/always_ask policies set at agent-configuration time, not PreToolUse callbacks - see the auth and access control page for that distinction in depth.

Migration is a named, expected path, not an edge case. "A common path is to prototype with the Agent SDK locally, then move to Managed Agents for production" once a workload needs to run unattended for hours with no process babysitting it, or needs Anthropic to own sandbox/session persistence. The same tools and MCP servers typically carry over; what changes is who runs the loop and where the state lives.

## Where you'll see it in production

### Code-review agent prototype

Built locally with the Agent SDK: query(prompt="Review this codebase", options=ClaudeAgentOptions(allowed_tools=["Read","Glob","Grep"])) plus a PostToolUse hook logging every read to an audit file.

### Unattended customer-ticket triage agent

The same tools and MCP servers migrate to Claude Managed Agents once the agent must run for hours against a live queue with no process babysitting it - governance shifts from PreToolUse hooks to always_ask per-tool policies.

## Comparison

| Layer | Runs in | Interface | Session state | Custom tools | Best for |
| --- | --- | --- | --- | --- | --- |
| Client SDK / Messages API | Your process | Direct model calls, you dispatch tools | Whatever you build | You execute them entirely | Fine-grained, custom-built loop control |
| Claude Agent SDK | Your process, your infrastructure | Python/TypeScript library (query()) | JSONL on your filesystem | In-process Python/TypeScript functions | Local prototyping; agents working directly on your filesystem/services |
| Claude Managed Agents | Anthropic-managed infrastructure (or self-hosted sandbox, orchestration still Anthropic-side) | Hosted REST API + SSE events | Anthropic-hosted event log | Claude triggers the tool; you execute and return results | Long-running/async production agents without operating your own sandbox |

## Decision tree

1. **Do you need to write and fully control every iteration of the tool-dispatch loop yourself?**
   - **Yes:** Client SDK / Messages API - direct messages.create() calls, you implement the while stop_reason "tool_use" loop.
   - **No:** Let Claude drive the loop - check the axes below.

2. **Should the agent loop run inside your own process, on your own infrastructure, with session state on your filesystem?**
   - **Yes:** Claude Agent SDK - query() + ClaudeAgentOptions, built-in tools with zero execution code.
   - **No:** Consider Managed Agents for a hosted loop instead.

3. **Does the workload need to run unattended for hours/days without a process babysitting it, with Anthropic owning the sandbox and session persistence?**
   - **Yes:** Claude Managed Agents - a hosted REST API; a common path is prototyping on the Agent SDK first, then migrating.
   - **No:** Agent SDK is likely sufficient; Managed Agents' infra ownership isn't earning its keep yet.

4. **Do you need a deterministic pre/post-tool-call action independent of model compliance?**
   - **Yes:** Use SDK hooks (PreToolUse/PostToolUse callbacks) if on the Agent SDK; on Managed Agents the equivalent governance is always_allow/always_ask per-tool policies, not hooks - they are not interchangeable.
   - **No:** Standard tool permissions (allowed_tools, permission_mode) cover it.

5. **Does the deployment require Zero Data Retention or a HIPAA BAA?**
   - **Yes:** Managed Agents cannot satisfy this today - it's stateful by design; evaluate the Agent SDK or Client SDK for that compliance posture instead.
   - **No:** Managed Agents' data-retention model is not a blocker for this deployment.

## Exam-pattern questions

### Q1. A team wants an agent prototype where they can inject extensive custom logging and manual retry logic inside every single tool-dispatch cycle, with total control over the loop's mechanics. Which layer fits?

The Client SDK / Messages API - you implement while response.stop_reason "tool_use" yourself, so custom logic goes exactly where you want it. The named distractor "the Claude Agent SDK, since it also runs in your own process" is wrong: the Agent SDK deliberately hands loop control to Claude (query() autonomously drives tools) - that is the opposite of the fine-grained control this team wants.

### Q2. An agent built and validated on the Claude Agent SDK now needs to run unattended for hours against a live customer-ticket queue, with no engineer watching the process. What's the recommended next step?

Migrate the same agent (tools/MCP servers carried over) to Claude Managed Agents, where Anthropic owns the sandbox and session persistence and the app just posts/streams events - this is explicitly the documented common path. The named distractor "keep it on the Agent SDK and add a process supervisor/cron wrapper" reinvents infrastructure Managed Agents already provides for exactly this long-running, unattended use case.

### Q3. A team ports an Agent SDK agent that used a PreToolUse hook to gate a refund tool over to a Claude Managed Agents session, assuming the hook config will keep working unchanged. What breaks?

Hooks are an Agent SDK / Claude Code construct - callbacks registered in your own process. Managed Agents sessions are governed by a different, server-side mechanism: per-tool always_allow/always_ask policies configured at agent-creation time. The named distractor "nothing breaks, Managed Agents runs the same hook callbacks server-side" is wrong - the two runtimes use structurally different governance mechanisms, not a compatible superset.

### Q4. A regulated org configures a self-hosted sandbox for its Managed Agents environment and assumes this makes the deployment fully self-hosted, with no residual dependency on Anthropic's infrastructure. Is that correct?

No. Self-hosted sandboxes move tool execution onto the org's own infrastructure, but orchestration stays on Anthropic's side under a shared-responsibility model - Anthropic still secures the control plane (session/queue integrity, multi-tenant isolation). The named distractor "self-hosted sandboxes remove Anthropic from the architecture entirely" overstates what self-hosting actually moves.

### Q5. A healthcare startup wants to build a long-running clinical-intake agent on Claude Managed Agents and needs Zero Data Retention to satisfy a HIPAA BAA requirement. Can this combination ship as designed?

No - Managed Agents is stateful by design (server-persisted conversation history, sandbox state, and outputs) and is explicitly not currently eligible for Zero Data Retention or HIPAA BAA coverage, regardless of self-hosting the sandbox. The named distractor "enabling a self-hosted sandbox satisfies the HIPAA BAA requirement" conflates tool-execution location with the data-retention/compliance eligibility question, which self-hosting does not resolve.

## FAQ

### Q1. Is the Claude Agent SDK the same thing as Claude Code?

No, but they share internals. The Agent SDK gives you "the same tools, agent loop, and context management that power Claude Code," packaged as a Python/TypeScript library you program against, rather than the interactive CLI itself.

### Q2. Do PreToolUse/PostToolUse hooks work on a Managed Agents session?

No. Hooks are an Agent SDK/Claude Code callback mechanism running in your own process. Managed Agents sessions are governed instead by per-tool always_allow/always_ask policies set at agent-configuration time and evaluated server-side.

---

**Source:** https://claudearchitectcertification.com/concepts/agent-construction-with-claude-agent-sdk
**Last reviewed:** 2026-05-04

**Evidence tiers**, 🟢 official Anthropic doc / API contract · 🟡 partial doc / inferred · 🟠 community-derived · 🔴 disputed.
