Once you've written an agent as a bare while-loop, the next question is when to stop hand-rolling — and what to graduate to. On the Claude API there are four ways to build an agent, and the choice is clean once you see the two questions that separate them:

  1. Who supplies the harness — the agent loop plus context management?
  2. Who supplies the deployment — the infrastructure the agent runs on?

Two of the four (the Tool Runner and the Claude Agent SDK) supply a harness only — you still host them yourself, which is exactly why they get conflated. Only one supplies both harness and managed deployment. Here's the whole map in one screen, then each option in turn.

The four approaches, at a glance#

ApproachYou writeHarness & deploymentTools available
Manual loopThe while loop yourselfYou build the harness; you hostOnly tools you define
Tool RunnerJust the tool functionsSDK supplies the loop (harness only); you hostOnly tools you define
Managed AgentsAgent config + your tool resultsAnthropic supplies harness and hosts a sandboxHosted sandbox (bash/files/code) + Skills/MCP + your tools
Claude Agent SDKA prompt + optionsSDK supplies the Claude Code harness; you hostBuilt-in Read/Write/Edit/Bash/Grep/Web + MCP + subagents

The mental model that matters: approaches 1, 2, and 4 all leave deployment to you. Only Managed Agents adds managed deployment. Get that split and the rest falls out.

1. The manual loop — you own everything#

You write the while stop_reason == "tool_use" loop by hand: call the model, execute the tool blocks it asks for, append the results, call again. No beta dependency, no framework. Reach for it when you want to own the entire loop — a control flow the other options' hooks don't fit, or simply to understand what an agent is before adding abstraction. The cost is that everything — retries, streaming, context management — is yours to build. We wrote the full ~90-line version in Build an AI agent from scratch.

2. The Tool Runner — the SDK writes the loop#

The Tool Runner is part of the regular Anthropic SDK, reached via client.beta.messages.tool_runner. You define your tools (Python's @beta_tool decorator, TypeScript's betaZodTool) and it drives the request → execute → loop cycle for you. You still host the compute and it only ever calls tools you define — no built-in tools, no sandbox.

from anthropic import Anthropic
from anthropic.lib.tools import beta_tool

client = Anthropic()

@beta_tool
def get_weather(location: str) -> str:
    """Get the current weather for a city."""
    return f"18°C, light rain in {location}."

runner = client.beta.messages.tool_runner(
    model="claude-opus-4-8",
    max_tokens=4096,
    tools=[get_weather],
    messages=[{"role": "user", "content": "Weather in Lisbon?"}],
)
final = runner.until_done()

The reason this is the default for most custom-tool agents: "I need control" is rarely a reason to drop back to the manual loop. The runner exposes per-turn hooks — inspect and gate a tool call before it runs (human-in-the-loop approval), intercept the result before it returns to the model, modify it (add cache_control), retry a truncated turn, stream, and auto-compact. All the control the hand-rolled loop gives you, without the loop.

3. Managed Agents — Anthropic runs the loop and the box#

Managed Agents is the only option where Anthropic supplies both the harness and the deployment. You create a persisted, versioned agent config (model, system prompt, tools, MCP servers, skills), then start sessions that reference it. Each session provisions a container where the agent's tools execute — bash, file operations, code execution — all hosted by Anthropic. You send messages and tool results in; the session streams events back.

The mandatory flow is Agent (once) → Session (every run) — create the agent one time, store its ID, and reference it from every session. Reach for it when you want a hosted sandbox you don't manage, a persisted/versioned config, a long-running multi-turn session with file mounts, or — its cleanest use — a scheduled deployment that fires a session on a cron cadence with no client-side scheduler to run. It's a bigger platform than the Tool Runner, but for a hosted, stateful, or scheduled agent it's usually less code you own, not more.

4. The Claude Agent SDK — a different product entirely#

This is the one that trips people up. The Claude Agent SDK (claude-agent-sdk / @anthropic-ai/claude-agent-sdk) is Claude Code packaged as a library: it ships built-in tools (file read/write/edit, bash, grep, web search), the full agent loop, context management, subagents, and permissions. You call query(prompt, options) and it drives everything — on infrastructure you host.

It is not the API's Tool Runner. Both are harness-only and both you deploy yourself, but the Tool Runner loops over tools you define with no built-in tools, while the Agent SDK is the whole Claude Code harness with a batteries-included toolset. Use the Agent SDK when you want a coding or filesystem agent that already knows how to read, edit, and run code; use the Tool Runner when your agent's tools are your own domain functions. Don't substitute one for the other because the names rhyme.

The decision, in one line each#

Start as low on the ladder as your product allows. Every rung up trades transparency for leverage — worth it exactly when you've hit the need that rung solves, and not a day before. For the framework alternative to the Agent SDK, see Claude Agent SDK vs LangGraph: inherit a loop or own the graph.