Inside Anthropic's Managed Agents: A Modular Architecture for Reliable AI Agents
Anthropic recently released an engineering blog detailing how they rethought the underlying architecture for AI agents. On the surface, it's an infrastructure article, but the design philosophy behind it offers valuable insights for anyone building autonomous systems.
The Problem with Patches: Workarounds That Become Dead Code Every AI developer has faced this: a model exhibits a quirky behavior, so you add logic in the framework to circumvent it. The problem is solved, but that patch becomes a permanent part of the codebase.
Anthropic encountered this firsthand. They noticed Claude Sonnet 4.5 would prematurely abandon tasks as the context window approached its limit, acting as if "time was running out"—a phenomenon they termed "context anxiety." Their fix was to implement a context reset mechanism in the agent harness. Later, when they applied the same harness to Claude Opus 4.5, the behavior vanished. The model's improved capabilities made the anxiety obsolete, leaving the reset logic as meaningless dead code.
This illustrates a broader issue: every architectural design decision is fundamentally an assumption about what a model cannot do. Models evolve, assumptions expire, but code doesn't automatically retire. Anthropic's response was to stop patching and redesign the architecture from the ground up, aiming for interfaces stable enough to survive multiple model generations. The result is their new Managed Agents framework.
The Single-Container Trap: A Debt That Eventually Comes Due Anthropic's initial implementation was straightforward: everything the agent needed—scheduling logic, execution environment, session history—was packed into a single container. The simplicity was appealing; file I/O was just system calls with no cross-service communication.
The problem was that this container became an overloaded, monolithic entity. If it crashed, the entire session was lost with no recovery path. If it hung, engineers had to manually debug it, a process made cumbersome and risky by the presence of user data. More profoundly, this design hard-coded the assumption that Claude's execution environment must be co-located with its harness. When enterprise customers wanted to integrate Claude with their private cloud resources, the only options were to bridge networks or deploy the entire harness themselves. An implicit assumption had become a scalability blocker.
The Solution: Separating the Brain from the Hands The fix is a clean separation into three distinct components:
- Brain: Claude itself plus the harness that orchestrates it.
- Hands: The sandboxed environment that executes concrete actions, like running code or manipulating files.
- Session: A complete, external event log recording everything that happens in an agent session.
These components communicate through simple interfaces. The Hands expose an execute(name, input) → string API. The Brain doesn't need to know whether the Hand is a container, a phone, or something else; it just sends instructions and gets results.
This split yields two immediate benefits.
First is reliability. If a sandbox container fails, the harness simply receives a tool-call error and can decide to retry or spin up a new one. The Session log lives externally, so even if the harness itself crashes, a new one can restart, read the log, and resume from where it left off with zero state loss. Each component can fail and recover independently.
Second is performance. In the old design, every agent session had to start a container before reasoning could begin. Now, containers are provisioned on-demand—if a session doesn't need to execute code immediately, it doesn't wait for one. Reasoning can start as soon as the harness retrieves the session log. This change reduced the p50 latency for the first token by about 60% and the p95 by over 90%.
Security by Structural Isolation: Credentials Can't Leak from the Sandbox In the original coupled design, the code Claude generated and sensitive API tokens or access credentials all resided in the same container. This meant that if Claude was compromised via a prompt injection attack—for example, tricked into running code that read environment variables—an attacker could extract all tokens and make unauthorized requests.
The new architecture's structural solution: make it physically impossible for code running in the sandbox to access any credentials.
Take Git as an example. Claude needs to push and pull code but doesn't need to "know" the token used for authentication. Anthropic's approach: during sandbox initialization, use the repository's access token to complete the clone and configure it into the local git remote settings. After that, when Claude executes git push or git pull in the sandbox, the git tool handles authentication directly. Claude's code never touches the token itself. This is what "wiring the token in" means—it's embedded into the tool's configuration during setup, not exposed as a variable in the runtime environment.
For other external services, Anthropic uses an MCP proxy model. OAuth tokens are stored in a secure vault outside the harness. When Claude calls an external tool, the request goes to a proxy, which uses the session identifier to fetch the corresponding credentials from the vault and forwards the call. Neither Claude's sandbox nor the harness ever holds these credentials.
The result: even if code in the sandbox is hijacked, there are no credentials to steal. Security doesn't rely on "trusting the model won't be fooled," but on structural isolation.
Session vs. Context Window: An Event Log, Not a Copy Long-running agents quickly hit context length limits. A common workaround is compaction—summarizing the current context into a digest to free space. But this is irreversible; once compressed, original information is lost, and it's hard to predict which details might be needed later.
Managed Agents' Session design fundamentally solves this. The Session is a complete, externally-stored event stream, and the context window is merely a view into that stream.
Specifically, the harness can call getEvents() to retrieve any segment of events from the Session and then decide what to load into Claude's context window. It might load only the last N events, re-read context before a critical decision, or pull in extra prior events for reference before a specific action.
This differs crucially from traditional compaction: operations on the context window are reversible. Compression, trimming, and reorganization are view-level choices made by the harness; the original data remains intact in the Session. Issues can be traced back, and future changes to context management strategies require no data migration.
Stable Interfaces, Swappable Implementations
Anthropic uses an operating system analogy to illustrate the goal. Unix's read() system call has remained unchanged from the disk era of the 1970s to today's NVMe SSDs; only the underlying implementation evolved. Applications don't need to care about the storage medium.
Managed Agents aims for the same principle. Define interfaces for Session, Harness, and Sandbox; what runs behind them can be swapped at any time. Claude Code is one type of harness, but specialized harnesses can plug in, and future ones yet to be imagined can too. The architecture doesn't bet on any specific implementation, only on the shape of the interfaces.
For developers building agent applications, the takeaway is clear: don't hardcode workarounds for current model limitations into your architecture. Instead, regularly ask which design decisions are assumptions about model constraints, and whether those assumptions still hold true.
Loading...