---
title: "Managed Agents: why Anthropic split the brain from the hands"
description: "Claude Platform's engineering and product leads described separating an agent's brain from its hands on Latent Space. Checked against the docs: credentials, latency, Rust."
url: https://udon-dev.com/en/notes/anthropic-brain-hands-managed-agents/
lang: en
published: 2026-10-28
topic: [ai]
tags: ["claude", "ai-agent", "managed-agents", "claude-platform", "security"]
---

# Managed Agents: why Anthropic split the brain from the hands

- Managed Agents splits an agent into three parts: the session (a log of events), the harness (the loop that calls Claude), and the sandbox (where code runs). If one fails, the others can resume the work
- Credentials never enter the sandbox where generated code runs. Git is wired up at initialization, and MCP tools are called through a vault and a proxy. Provisioning containers only when needed cut median time to first token by about 60%
- A team with no Rust developers when it started ported the Messages API to Rust, with people doing the design and Claude doing the implementation. It mirrored production traffic to confirm identical output before switching, and the guests say CPU dropped by roughly 40 to 50%

When you build infrastructure for running agents, the question is how much to put in one box. Putting the loop that calls the model, the conversation log, and the code execution environment in the same container is the easy way to build it. But when the container dies, you lose everything, and the keys to external services end up somewhere the code can read them.

In an episode the Latent Space podcast published on October 27, the two people who lead Claude Platform [described their answer](https://latent.space/p/opus55/) as "separating the brain from the hands": Katelyn Lesse on engineering and Angela Jiang on product. The show notes cite Anthropic's engineering post "[Scaling Managed Agents: Decoupling the brain from the hands](https://www.anthropic.com/engineering/managed-agents)," published on April 8, as the basis. In this note I check what was said on the show against that post and the official docs, and pick out the parts you can use when building your own agents.

（図: Image from Anthropic's engineering post "Scaling Managed Agents": on a magenta background, a wide green grid and a tall blue grid overlap in the center）
Source: [Scaling Managed Agents: Decoupling the brain from the hands (Anthropic Engineering)](https://www.anthropic.com/engineering/managed-agents)

## Why three parts

Managed Agents is a hosted service for running agents on Claude Platform. It launched as a public beta on April 8. According to the engineering post, an agent is split into three parts:

- Session: an append-only log of what happened
- Harness: the loop that calls Claude and routes Claude's tool calls to where they need to go
- Sandbox: the environment where Claude runs code and edits files

The post calls Claude and the harness the "brain," and the sandbox and tools the "hands."

At first, all three lived in one container. That had advantages: a file edit was just a system call, and nobody had to design service boundaries. But when the container died, the session went with it. The only way to investigate an unresponsive session was to open a shell inside the container, and that container also held user data, so in practice it could not be debugged. And when customers wanted to connect Claude to resources in their own virtual private cloud (VPC), the only options were to peer the networks or to run the harness in the customer's environment.

After the split, the harness calls the container the same way it calls any other tool: `execute(name, input) → string`. If the container dies, the harness returns that to Claude as a tool-call error, and if Claude decides to retry, `provision({resources})` sets up a new container. If the harness dies, `wake(sessionId)` starts a new harness, which uses `getSession(id)` to fetch the log and resume from the last event. Because the log lives outside the harness, nothing inside the harness needs to survive a crash.

## Keeping credentials out of the sandbox

One benefit of the split is a security boundary. In the single-container design, untrusted code that Claude generated ran in the same place as the credentials. An attacker only had to use prompt injection to make Claude read the inside of the container, and the token was theirs. The engineering post says that narrowing token permissions relies on the assumption of "what Claude can't do with a limited token," and that assumption gets shakier as Claude gets smarter. So they made the tokens unreachable from the sandbox where Claude's generated code runs.

They use two patterns. For Git, the sandbox clones the repository with a per-repository access token at initialization and wires it into the local remote. The agent can `push` and `pull` without ever touching the token. For MCP tools, OAuth tokens sit in a vault, and Claude calls tools through a dedicated proxy. The proxy receives a token tied to the session, pulls the credentials from the vault, and calls the external service, so even the harness never sees the credentials.

Users see this vault as a feature called [vaults](https://platform.claude.com/docs/en/managed-agents/vaults). You register credentials for an external service once and reference them by ID when you create a session, and you can keep a separate vault per end user. Vaults and credentials are shared at the workspace level, and you revoke access by deleting the vault or the credential.

The show also brought up egress control: limiting where the sandbox can connect with a domain allowlist, or blocking network access entirely. An allowlist alone does not make you safe, though. In a May post, "[How we contain Claude across products](https://www.anthropic.com/research/how-we-contain-claude)," Anthropic describes an incident in Claude Cowork. The cause was that api.anthropic.com was on the egress allowlist. A malicious file placed in the working folder contained an attacker's API key and hidden instructions, and Claude uploaded other files to the attacker's account. The destination was an allowed domain, so the proxy let it through. Anthropic now treats an allowlist less as a filter on destinations and more as "granting every capability reachable at that domain." It then added a proxy that rejects anything other than the session token assigned to the virtual machine. When you write your own allowlist, it seems worth checking what each domain lets you do, too.

## Latency, where the hands live, and pricing

The split also shows up in speed. When the brain lived in the container, even sessions that never used the sandbox had to wait for the container to be ready. Inference could not start until the repository was cloned, processes were started, and pending events were fetched. After the split, the brain provisions a container through a tool call only when it needs one. According to the engineering post, time to first token (TTFT) dropped by about 60% at the median and by more than 90% at the 95th percentile.

Since brains and hands no longer have to be one-to-one, one brain can use several hands, and brains can pass hands to each other. Every hand is a tool that takes a name and input and returns a string, so the harness does not know whether the sandbox is a container or a phone.

You can also keep the hands in your own environment. With [self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes), Claude still runs on Anthropic's side, and only tool execution is handled by workers on your own infrastructure. However, tool inputs and outputs pass through Anthropic's control plane so the model can decide its next step. It seems wise to choose what data you handle on the assumption that tool results reach Anthropic as well.

Pricing is the normal token price plus $0.08 per hour while a session is `running` ([pricing page](https://platform.claude.com/docs/en/about-claude/pricing)). Time spent waiting for the next input or for a tool approval does not count.

## Handing the Messages API implementation to Claude and porting it to Rust

The second half of the episode moves away from brains and hands to the rebuilding of Claude Platform itself. When one of the guests joined about a year earlier, the Messages API was one large Python application running in a single Google Cloud region. As usage grew, what ran short was CPU rather than GPU: running the API, sandboxes, and CI for the growing codebase all use CPU. CPU that they used to be able to add on demand now had to be reserved in advance, they said.

So they rewrote the Messages API in Rust. When they started, the team had not a single Rust developer (they hired a few people with experience along the way). People handled the design, and Claude handled the implementation. The two things the guests named as most important were planning and verification.

1. Build a complete copy of the API in Rust
2. Mirror production traffic to it and check that the Python and Rust versions return the same output
3. Shift over to the Rust version gradually, confirming the output keeps matching

They did not add features as part of the rewrite and kept it a pure port. Because other team members kept adding features to the Python version in parallel, they also set up static analysis that flags when someone adds a feature the Rust version does not support. They finished the switchover the week before recording, and said CPU improved by roughly 40 to 50% and TTFT by roughly 10 to 20%. Both are rough figures given aloud, not numbers Anthropic has published in writing.

At the end of the episode, a guest said they put more weight on the overall plan and design, plus the verification setup, than on people reading code line by line. It is the same division the Claude Code team described: give Claude the means to verify its work, and have people decide whether something should be built and what design patterns to use ([How the Claude Code team does code review](/en/notes/claude-code-team-code-review/)).

## Behind the Opus 5.5 launch, and Dreams

The episode opens with some background on the Opus 5.5 launch. Adding a mechanism that preserves thinking blocks across turns, to keep reasoning from being extracted for distillation, can break customers' existing harnesses. When they introduced this mechanism with Fable 5.1, they gave existing customers a migration grace period and used an internal authorization system (trust grants) to manage who was covered. If your harness drops or rewrites thinking blocks, it seems worth checking for changed API requirements when you switch models.

The other item was [Dreams](https://platform.claude.com/docs/en/managed-agents/dreams), an experiment built on top of Managed Agents. According to the docs, it reads an existing memory store and past session transcripts, merges duplicates, replaces outdated entries with newer values, and produces a separate, new memory. On the show it was described as "one agent reading another agent's work and writing memories back." It is currently a research preview and requires a dedicated beta header.

The show notes leave three questions for anyone designing agent infrastructure: what needs to survive a crash, where untrusted work runs, and which secrets the place where code runs actually needs.
