Claude Managed Agents: A Production Tutorial for 2026
Build your first Claude Managed Agent step by step: agent, environment, session, streaming events, rate limits, and the production gotchas no one mentions.
If you have ever tried to ship an AI agent to production, you already know the part nobody warns you about. The model is the easy bit. The real work is the harness around it. A safe place to run code. A way to keep state. A way to stream events back. Tool execution that does not crash on the third call. A queue. Logs. Retries. By the time the agent does anything useful, you have written a small distributed system.
Claude Managed Agents is Anthropic’s answer to that. You define the agent once. Anthropic runs the container, the tools, the streaming, the state. You get an API that talks in events, and the agent works inside a sandboxed cloud environment you do not have to maintain.
This post is a clean walkthrough for 2026. What Managed Agents actually is, the four concepts you need to understand, a working session you can copy and run, and the production decisions to check before deployment. The examples are documentation-based; they are not a claim of a paid live API test.
TL;DR. Claude Managed Agents is a hosted runtime for autonomous agents. You create an
agent(model + tools), anenvironment(container template), then start asessionand streamevents. All requests need themanaged-agents-2026-04-01beta header. Check the current reference for endpoint-specific limits.
What Claude Managed Agents actually is
Anthropic now ships two ways to build with Claude.
| Messages API | Claude Managed Agents | |
|---|---|---|
| What it is | Direct model prompting | Hosted agent harness with a sandboxed container |
| Best for | Custom loops you fully control | Long-running, multi-step tasks |
| You manage | The whole loop, sandbox, tools | Just the agent definition and the events |
| State | Stateless per request | Stateful sessions with persistent filesystem |
The Messages API is the right choice when you want fine-grained control over every model call and you already have your own infrastructure. Managed Agents is the right choice when the agent runs for minutes or hours, calls a lot of tools, and you would rather not babysit a container fleet to make that happen.
Managed Agents is currently in beta. Every endpoint requires the header anthropic-beta: managed-agents-2026-04-01. The official SDKs add it for you. If you are calling the API with curl, you must add it yourself or you will get a clean 4xx and waste an hour wondering why.
The four concepts you have to understand
Managed Agents only has four moving parts. Get these right and the rest is plumbing.
| Concept | What it is | Created how often |
|---|---|---|
| Agent | Model, system prompt, tools, MCP servers, skills | Once per use case, then versioned |
| Environment | Container template: packages, networking, mounted files | Once per environment shape |
| Session | A running agent inside an environment, doing one task | Per task |
| Events | Messages between your app and the agent | Many per session |
A good way to remember it: agent is the recipe, environment is the kitchen, session is the meal, events are the conversation while it is being cooked. The first two you reuse. The last two are fresh every time.
Prerequisites
You need three things before any of this works.
- An Anthropic Console account with an API key.
- Python 3.10 or newer and the current Anthropic Python SDK. The examples below use Python.
- The beta header on every request. The SDK sets it for you. Curl callers, set it manually.
pip install anthropic
export ANTHROPIC_API_KEY="sk-ant-..."
That is the entire setup. No infrastructure, no Docker, no queue.
Step 1: create the agent
The agent is the long-lived definition of what you are building. Model, system prompt, tools.
from anthropic import Anthropic
client = Anthropic()
agent = client.beta.agents.create(
name="Coding Assistant",
model="claude-opus-5-5",
system="You are a careful coding assistant. Write small, well-tested code. Ask before deleting files.",
tools=[
{"type": "agent_toolset_20260401"},
],
)
print(f"Agent ID: {agent.id}, version: {agent.version}")
A few things worth pointing out.
agent_toolset_20260401is a single line that turns on the full pre-built kit: bash, file read/write/edit, glob, grep, web search, web fetch. You almost always want it.- Agents are versioned. Every time you change the system prompt or tools, a new version is created and the old one keeps working. This matters in production. You can pin a session to a specific agent version so a deploy of a new prompt does not break a session that is already running.
- Save the
agent.idsomewhere persistent. You reference it from every session.
Step 2: create the environment
The environment is the container the agent runs inside. You are configuring the box, not the agent.
environment = client.beta.environments.create(
name="quickstart-env",
config={
"type": "cloud",
"networking": {"type": "limited"},
},
)
print(f"Environment ID: {environment.id}")
The example uses limited networking with no extra hosts allowed. The Fibonacci task only needs local code and files. For tasks that need external services, explicitly allow the required hosts rather than opening access to the whole internet. See the environment configuration reference.
Environments are reusable. You do not need a new one per session. One coding environment, one data-science environment, one browser-automation environment, and you are done.
Step 3: start a session
A session is a running instance of the agent inside the environment. One task per session is the rule of thumb.
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment.id,
title="Generate a Fibonacci script",
)
print(f"Session ID: {session.id}")
Sessions hold state. The container’s filesystem persists across events inside the same session, and the conversation history is server-side. That is the whole point: you can come back to a session, send another message, and the agent picks up where it left off. Keep a deliberate retention policy for their history and files. Runtime billing depends on session status, as explained below.
Step 4: send events and stream the response
Now the actual work. You open a stream, send a user.message event, and read events as they come back.
with client.beta.sessions.events.stream(session.id) as stream:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [
{
"type": "text",
"text": (
"Create a Python script that generates the first "
"20 Fibonacci numbers and saves them to fibonacci.txt"
),
},
],
},
],
)
for event in stream:
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "agent.tool_use":
print(f"\n[Using tool: {event.name}]")
case "session.status_idle":
print("\n\nSession is idle; verify the result and stop reason.")
break
For a successful run, expect tool events and a message describing the generated file. Treat that as expected behavior, not a guaranteed transcript. An idle event can also mean that the session needs input or hit a limit. Check the stop reason and output before marking a job successful. Workflows with background runs need additional completion tracking; see workflow completion rules.
The stream is opened before the message is sent so the application is ready to receive events. Production clients also need reconnect and error handling; this short example is not a complete job runner.
What is happening under the hood
When you send a user event, Managed Agents does five things.
- Provisions a container based on your environment config (or reuses a warm one).
- Runs the Claude agent loop, deciding which tool to call next.
- Runs tools, including shell commands and file operations in the sandbox.
- Streams events to your stream as they happen.
- Emits
session.status_idlewhen the agent has nothing more to do, so you know it is safe to close.
You can also send another user.message mid-flight. The agent will see it as a steering message and adjust. This is genuinely useful — it lets you nudge the agent without restarting the session.
Production: the things that bite you
A quickstart demonstrates the API flow. Before deployment, decide how your application will handle limits, state, permissions, and output verification.
Rate limits are tight enough to plan around
Check the Managed Agents reference for the current limits. Queue bursts of new work, handle rate-limit responses, and back off instead of repeatedly retrying immediately. Persist session IDs so reconnecting does not accidentally create another job.
Tokens and running time both affect cost
Managed Agents charges for model usage and session runtime. The documented runtime rate is $0.08 per session-hour while the status is running. Time in idle, rescheduling, or terminated does not count toward that runtime charge. Tool charges can also apply. Verify current rates on the pricing page.
Set an application budget and monitor actual usage. Do not delete a session just because it became idle: it may hold results you still need. Download required files first. Deleting the session removes its record, events, and associated sandbox; independent uploaded files and other resources have separate lifecycles. See session operations.
Network restrictions are how you stay safe
Allow only the external hosts needed by the task. The ability to reach a host also permits requests that can change data there, depending on credentials. Review tool permissions as well as networking. Do not put production secrets in a learning example. Our API key protection guide covers that boundary.
Pin agent versions in long-running flows
Agents are versioned for a reason. If you push a new system prompt while a session is running, you do not want it to swap mid-task. Reference the specific version when starting sessions for production runs:
session = client.beta.sessions.create(
agent={"id": agent.id, "version": agent.version},
environment_id=environment.id,
)
Webhooks beat polling
For long-running sessions, do not sit on the stream the entire time. Use the webhook configuration in production to get notified when the agent goes idle, then fetch the result. Your servers will thank you.
Feature availability and data handling
Check the current Managed Agents overview before committing to an optional feature. The platform is stateful, and its data-retention eligibility is not identical to every other Claude API feature. Review the terms that apply to the workload you plan to send.
Using your own files
A cloud session cannot automatically read a CSV on your laptop. Upload or attach the file using the documented file workflow, confirm it is available in the session, and tell the agent which file to use. See attaching and downloading files.
For a first test, use a tiny synthetic dataset whose answer you can check by hand. Ask for row count, column names, and a summary. Verify the result and download it before deleting any resources. This makes an incorrect file path or missing input obvious before you introduce real customer data.
Common questions
Do I need to use the Agent SDK or is the Anthropic SDK enough? The Anthropic SDK is enough for Managed Agents. The Claude Agent SDK is for building your own loop with the Messages API. They are complementary, not redundant.
Can I attach my own MCP servers to a Managed Agent? Yes. Configure the MCP integration supported by Managed Agents and provide the required connection and authentication settings; do not assume it starts a local MCP server automatically. If you are new to MCP, start with the first MCP server tutorial.
How is this different from the Claude Code CLI? Claude Code is the CLI you use on your own machine. Managed Agents is a hosted API for running agents in the cloud. Same model, very different product. Anthropic’s branding guidelines explicitly ask you not to label your Managed Agent product as “Claude Code”.
What model can I use?
Use a model supported by Managed Agents and available to your account. The example uses claude-opus-5-5; check the agent setup reference before choosing a model or changing its settings.
Where does the container actually run? The example uses an Anthropic-managed cloud sandbox. The platform also documents self-hosted sandboxes. Sandbox location and model inference geography are separate decisions; verify both against your requirements.
How long can a session run? Do not treat a session as an unlimited job. Check current platform limits and track its status, budget, and errors. Your application should define its own timeout and recovery behavior.
Can I attach files to the environment? Yes. Environments support mounted files in their config. Put your prompts, datasets, and config there rather than re-uploading them on every session.
Where to go from there
Managed Agents is the easiest production path Anthropic has shipped. The pattern is small enough to fit in your head: agent, environment, session, events. Once you have one running, the rest is shaping the system prompt, tightening the network policy, and wiring up the right tools.
If you want to go deeper, four places I would point you next:
- The first MCP server walkthrough for plugging your own tools into the agent.
- The Claude Agent SDK vs LangChain comparison and the Claude Agent SDK vs Vercel AI SDK 6 comparison for picking the right harness when you outgrow the managed runtime.
- The Claude Code skills guide and the hooks guide for local Claude Code workflows; do not assume their configuration directly transfers to Managed Agents.
- The agentic RAG tutorial for the most common knowledge-retrieval pattern these agents end up needing.
- The Claude Code Outcomes guide for adding a rubric-graded check on the agent’s output so quality is measurable, not just felt.
- The Claude Agent SDK cost tracking guide for a separate SDK-based workflow. Managed Agents usage should be measured through its own session usage reporting.
The ecosystem around all of this is moving fast. The stable parts are the four concepts above. Build your first session today, and you have a foundation that survives most of the changes still on the roadmap.
For the official spec, the Claude Managed Agents overview and quickstart are the canonical references — bookmark them, check them when updating an SDK or adopting a new feature.