Claude Managed Agents — The Managed Infrastructure Path
Managed Agents is Anthropic's hosted agent harness for async production pipelines — distinct from Claude Code, built for systems you deploy and forget.
There is a decision that every team building with Claude eventually reaches: should this pipeline run in Claude Code, through the Messages API, or somewhere else entirely? For a specific class of production workloads — long-running, async, infrastructure-intensive, and not developer-interactive — the answer is Claude Managed Agents.
This is Anthropic's hosted agent harness. It is not a wrapper around Claude Code. It is not a fancy Messages API call. It is a distinct infrastructure path with different tradeoffs, different session semantics, and different operational characteristics. Understanding where it fits is the prerequisite for using it well.
What Managed Agents Is
Claude Managed Agents is an API-first hosted execution environment for agents. You define an agent — its model, system prompt, tools, and skills — and Anthropic's infrastructure handles the rest: container lifecycle, session persistence, scaling, and execution.
The core concepts:
Agent. A named, versioned configuration — model + system prompt + tools + skills. An agent is like a job definition. It describes what the agent can do, not a particular instance of it running.
Session. A running instance of an agent. Sessions are async — you start one, it works, it completes. You do not need to hold a connection open. You can start a session, close your client, and poll for results later.
Events. The communication protocol inside a session. The agent emits events as it works — tool calls, intermediate output, errors, completion. Events arrive as Server-Sent Events (SSE) if you are streaming, or via polling if you are not.
Environment. A reusable container-configuration template — networking rules, packages, cloud vs self-hosted. Environments are created once and referenced by every session (environment_id is a required field on session creation). The agent's tools execute inside a container provisioned from this template on Anthropic's infrastructure.
How It Differs from Claude Code and Messages API
The three tools serve fundamentally different use cases:
Standard Messages API — stateless, single-turn or short multi-turn inference. You own the orchestration. The model receives a prompt and returns a response. There is no persistent session, no built-in tool execution environment, no async execution. Right for: classification, generation, structured extraction, and any task where your code drives the loop.
Claude Code agent teams — developer-facing, interactive sessions. A human (usually a developer) is in the loop. The agent takes actions in a local environment: reads files, runs commands, edits code. Right for: development work, exploration, tasks that benefit from human oversight and iteration in real time.
Claude Managed Agents — production async pipelines. No human in the loop. The agent runs to completion in Anthropic's infrastructure. Right for: nightly processing pipelines, research agents that gather and synthesize information over hours, code generation workflows that run after a commit, and any task where "fire and forget" is the right operational model.
The API Surface
Managed Agents requires the anthropic-beta: managed-agents-2026-04-01 header on every request — without it you will get a 404. The SDK sets it automatically for all client.beta.agents / sessions / environments calls, so you only pass it yourself on raw HTTP.
Every flow needs two durable resources before any session can run — an environment (the container template) and an agent:
import anthropic
client = anthropic.Anthropic()
# 1. Create the environment — a reusable container template.
# environment_id is REQUIRED when starting sessions.
environment = client.beta.environments.create(
name="research-env",
config={"type": "cloud", "networking": {"type": "unrestricted"}},
)
# 2. Create the agent. Built-in tools (bash, file ops, web_search, web_fetch)
# come from the versioned agent toolset — not individual tool types.
agent = client.beta.agents.create(
name="research-pipeline",
model="claude-sonnet-4-6",
system="""You are a research specialist. Given a company name,
you will gather publicly available information about their recent
product launches, funding rounds, and executive changes.
Synthesize findings into a structured report.""",
tools=[{"type": "agent_toolset_20260401"}],
)
print(f"Agent ID: {agent.id}, Environment ID: {environment.id}")
The agent and environment IDs are stable — these are durable resources you reference when starting sessions. Create them once; run sessions many times.
Starting a Session and Receiving Events
# Start a session — sessions live at client.beta.sessions (not nested under
# agents), and environment_id is required
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment.id,
)
# Open the event stream FIRST, then send the kickoff message — the stream
# only delivers events emitted after it opens
with client.beta.sessions.events.stream(session_id=session.id) as stream:
client.beta.sessions.events.send(
session_id=session.id,
events=[{
"type": "user.message",
"content": [{"type": "text", "text": "Research Anthropic's recent model releases and funding news."}],
}],
)
for event in stream:
if event.type == "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="", flush=True)
elif event.type == "session.status_idle":
print("\nAgent idle — task complete.")
break
elif event.type == "session.status_terminated":
print("\nSession terminated.")
break
elif event.type == "session.error":
print(f"Error event: {event}")
Note the event names: sessions emit their own event vocabulary (agent.message, agent.tool_use, session.status_idle, session.error) — not the Messages API streaming events (message_start / content_block_delta / message_stop).
Sessions are async by nature. If you do not need to stream output, you can start a session, send the kickoff event, and poll its status:
import time
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment.id,
)
client.beta.sessions.events.send(
session_id=session.id,
events=[{
"type": "user.message",
"content": [{"type": "text", "text": "Research Stripe's Q1 2026 product launches."}],
}],
)
# Poll until the agent stops working. Session statuses are
# idle / running / rescheduling / terminated — there is no 'completed'
# or 'failed'; a finished task surfaces as idle.
while True:
status = client.beta.sessions.retrieve(session_id=session.id)
if status.status in ["idle", "terminated"]:
break
time.sleep(5)
print(f"Session status: {status.status}")
Built-In Tools
Managed Agents ships with built-in tools that do not require any custom implementation. They are enabled as one versioned bundle — {"type": "agent_toolset_20260401"} in the agent's tools array — and individually configurable within it:
bash — execute shell commands in the agent's container. The agent can write scripts, run Python, install packages (within what the environment allows), and work with files.
web_search — search the web and retrieve content. Useful for research agents, competitive intelligence pipelines, and any task that requires current information.
file operations — read and write files within the session's ephemeral file system. Files written in one step of the agent's work are available to subsequent steps within the same session.
MCP servers — if you have MCP servers configured, they can be attached to an agent and their tools become available to the agent within a session.
The Decision Framework
Use this to route a workload to the right tool:
Is a developer interactively driving the work? → Claude Code.
Is this a single inference call or a short conversation with no persistent state? → Messages API.
Is this an autonomous pipeline that runs to completion without human intervention, processes complex multi-step tasks, and needs session persistence? → Managed Agents.
Does the pipeline run overnight, on a schedule, or triggered by an external event? → Managed Agents.
Does it need to browse the web, run code, or interact with external services without a human in the loop? → Managed Agents.
What You Give Up
The tradeoffs are real:
Reduced debugging transparency. When something goes wrong in a local Claude Code session, you can inspect every file change and command. In Managed Agents, you have events and logs — but the execution environment is opaque. Debugging a silent failure requires more inference from event streams.
Less infrastructure control. You cannot install arbitrary system packages, mount your own file systems, or configure network access in ways that fall outside the environment schema. The infrastructure is managed, which means you accept the constraints that come with that.
Preview API maturity. Managed Agents is in beta. API shapes can change, behavior may shift between versions, and some edge cases are still being worked out. Build with this awareness — pin to explicit agent IDs and session versions, log aggressively, and have fallback paths.
The managed infrastructure path is the right choice when the operational simplicity matters more than the control. For production pipelines that run unattended and need to scale, that tradeoff usually favors Managed Agents.