Skip to main content
Back to Blog
AI/MLCloud ComputingSystem Administration
8 August 20269 min readUpdated 24 August 2026

Scaling Managed Agents by Separating the Brain from the Hands

Managed Agents is a hosted service in the Claude Platform designed to run long horizon agents through interfaces intended to remain useful as implementations change. A recurring...

By Software Development Team

Managed Agents is a hosted service in the Claude Platform designed to run long-horizon agents through interfaces intended to remain useful as implementations change.

A recurring challenge in agent engineering is that harnesses encode assumptions about what Claude cannot do independently. Those assumptions must be revisited as models improve. For example, earlier work found that Claude Sonnet 4.5 sometimes ended tasks prematurely when it sensed that its context limit was near, a behavior known as “context anxiety.” Adding context resets to the harness addressed the issue. When the same harness was used with Claude Opus 4.5, the behavior was no longer present, making the resets unnecessary.

Managed Agents applies a familiar systems principle: create abstractions that remain stable while the implementations beneath them evolve. Operating systems use abstractions such as processes and files so programs can work across changing hardware. Similarly, Managed Agents virtualizes three parts of an agent:

  • Session: An append-only log of everything that happened.
  • Harness: The loop that calls Claude and routes its tool calls to infrastructure.
  • Sandbox: An execution environment where Claude can run code and edit files.

These components can be replaced or fail independently. The interfaces define how they interact without prescribing what runs behind them.

Avoiding a single, irreplaceable container

The initial design placed the session, harness, and sandbox in one container. This made file edits direct system calls and avoided service boundaries, but it also created a fragile, stateful server. If the container failed, the session was lost. If it became unresponsive, engineers had to restore it manually.

Debugging was difficult because the WebSocket event stream could not identify whether a failure came from the harness, a dropped packet, or an offline container. Engineers had to open a shell inside the container, which was often unsuitable because the container also held user data.

The design also assumed that everything Claude worked on lived alongside the harness. Customers that wanted Claude to access resources in their own virtual private cloud had to peer their network with Anthropic’s or run the harness in their own environment. An assumption in the harness therefore limited which infrastructure it could use.

Separating the brain from the hands

The revised design separates the “brain,” meaning Claude and its harness, from the “hands,” meaning sandboxes and tools, as well as from the session containing the event log. Each component has an independent interface and can be replaced or fail without taking down the others.

Moving the harness outside the container

The harness no longer lives inside the sandbox container. Instead, it treats the container like any other tool:

execute(name, input) → string

Containers become interchangeable. If one fails, the harness receives a tool-call error and passes it to Claude. If Claude retries, a new container can be created from a standard recipe:

provision({resources})

This removes the need to repair individual containers manually.

Recovering from harness failures

The harness is also interchangeable because the session log exists separately. After a crash, a replacement harness can be started with:

wake(sessionId)

It can retrieve the event history with:

getSession(id)

and resume from the last recorded event. During execution, the harness writes durable events using:

emitEvent(id, event)

Establishing a security boundary

In the coupled design, Claude-generated untrusted code ran in the same container as credentials. A prompt injection only needed to persuade Claude to read its environment. Exposed tokens could then be used to create unrestricted sessions and delegate further work. Limiting token scope helped, but that approach still depended on assumptions about what Claude could do with limited credentials.

The structural solution was to ensure that credentials are never reachable from the sandbox where Claude-generated code runs. Managed Agents uses two approaches:

  • Authentication can be bundled with a resource or stored in a vault outside the sandbox.
  • For Git, a repository access token is used during sandbox initialization to clone the repository and configure the local Git remote. Git push and pull then work from inside the sandbox without exposing the token to the agent.
  • For custom tools, Managed Agents supports MCP and stores OAuth tokens in a secure vault. Claude calls MCP tools through a dedicated proxy, which receives a session-associated token, retrieves the corresponding credentials, and calls the external service. The harness does not receive the credentials.

The session is more than Claude’s context window

Long-running tasks can exceed Claude’s context window. Common techniques for handling this include compaction, where Claude saves a summary, and the memory tool, which allows Claude to write context to files for use across sessions. Context trimming can also remove selected content, such as older tool results or thinking blocks.

These methods involve irreversible decisions about what to retain. It is difficult to know which tokens later turns will require. Once messages are transformed by compaction and removed from Claude’s context window, they can be recovered only if they were stored elsewhere.

One alternative is to store context as an object outside the context window, such as an object in a REPL that an LLM programmatically filters or slices. Managed Agents provides a similar capability through the session. Rather than storing context in a sandbox or REPL, it keeps it durably in the session log.

The getEvents() interface allows the harness to select positional slices of the event stream. It can continue from where it stopped reading, rewind several events to inspect what led to a moment, or reread the context preceding a specific action.

Fetched events can be transformed by the harness before they are sent to Claude. These transformations may include context organization for a high prompt-cache hit rate and other context-engineering techniques. Durable context storage and context management are separate because future models may require different strategies. The session guarantees that the event history remains durable and available for interrogation, while the harness determines how that history is presented to Claude.

Many brains, many hands

Many brains

Separating the harness from the sandbox addressed the limitation around customer-owned virtual private clouds. Once the harness no longer assumed that every resource was nearby, it could work with resources in other environments.

The architecture also improved performance. Previously, putting the brain in a container meant that every concurrent brain required its own container. Inference could not begin until the container was provisioned, so every session paid the full setup cost. Even sessions that never used a sandbox had to clone the repository, start the process, and retrieve pending events.

This startup delay affects time-to-first-token (TTFT), the time between accepting work and producing the first response token. With the decoupled design, the brain provisions a container through a tool call only when necessary:

execute(name, input) → string

Inference can begin as soon as the orchestration layer retrieves pending events from the session log. With this architecture, p50 TTFT fell by roughly 60%, while p95 TTFT fell by more than 90%. Scaling to many brains requires starting stateless harnesses and connecting them to hands only when needed.

Many hands

The architecture also supports connecting one brain to multiple execution environments. Claude must then reason about several environments and decide where to send work, which is more demanding than operating in a single shell. Earlier models were not capable of this, so the brain initially remained in one container. As model intelligence improved, that container became the limiting factor: a failure could remove the state associated with every hand the brain was using.

With the decoupled design, each hand is represented as a tool:

execute(name, input) → string

The interface accepts a name and input and returns a string. It can represent a custom tool, an MCP server, or an internal tool. The harness does not need to know whether the execution environment is a container, a phone, or a Pokémon emulator. Because hands are not permanently coupled to a brain, they can also be passed between brains.

Conclusion

Managed Agents addresses a long-standing systems challenge: designing for “programs as yet unthought of.” Operating systems achieved this by virtualizing hardware behind abstractions general enough to support programs that did not yet exist. Managed Agents applies the same idea to the components surrounding Claude.

It functions as a meta-harness that does not prescribe the specific harness Claude will need in the future. Claude Code is one harness used across many tasks, while task-specific harnesses can be effective in narrower domains. Managed Agents is designed to support different harnesses as Claude’s capabilities change.

The design is opinionated about the interfaces around Claude. Claude needs a way to manipulate state through the session and perform computation through the sandbox. It also needs to scale to many brains and many hands. These interfaces are designed to support reliable and secure operation over long time horizons without assuming how many brains or hands Claude will require, or where they will run.