The engineering journal Research note · 2026.08.09
Agents Noorle Agent OS

Outside the Sandbox: Why Production Agent Runtimes Need a Hybrid Architecture

Most agent platforms force you to choose between security and state — orchestration inside the sandbox is convenient but unsafe; orchestration outside with ephemeral sandboxes is safe but stateless. The hybrid pattern resolves the trade-off.

Figure 01 · field image Article file
Abstract circuit board pattern representing the boundary between an agent's control plane and its execution environment.
Abstract circuit board pattern representing the boundary between an agent's control plane and its execution environment.

When teams move agents from prototype to production, the same architectural question keeps surfacing: where should the agent loop live relative to the sandbox?

The agent loop — the orchestration code that calls the model, parses tool calls, manages memory, and drives the next step — has to run somewhere. So do the things the agent decides to do: shell commands, code execution, browser sessions, file operations. Whether you put those in the same execution environment or separate them sounds like a low-level detail. It isn’t. It’s the decision that determines how secure your agents are, how much state they can keep, and how much infrastructure your team has to rebuild on the way to production.

There are essentially three ways to answer it. Two of them are common. The third is what we built Noorle around.

The two common patterns

Pattern A: Agent loop inside the sandbox. The orchestration code runs in the same container or VM as the tools it executes. This is convenient — local state is easy, the model’s outputs flow directly into local function calls, and there’s no IPC to design. It’s how most prototype agents work, and it’s the default in many open-source frameworks.

The problem shows up when the agent does something untrusted. The model is now driving code execution inside the same boundary that holds your orchestration logic, your credentials, your memory store, and your audit trail. A prompt injection that gets the agent to rm -rf doesn’t just lose work — it can corrupt the supervisor that’s supposed to detect that the agent went off the rails. Multi-tenant deployments amplify the blast radius. “The agent and its supervisor share a process” is a fine model for a developer’s laptop and a poor one for production.

Pattern B: Agent loop outside, ephemeral sandbox per call. The orchestration runs in a hardened control plane. Each tool call spawns a fresh, short-lived sandbox, executes, returns the result, and is destroyed. This is the pattern most labs converge on for security reasons, and it’s clean: no shared state, strong isolation, easy to reason about.

The problem here is the opposite one. State doesn’t survive between calls. A long compile, a cloned repo, an authenticated browser session, a virtualenv with 300MB of dependencies — none of them persist. Every meaningful workflow has to be reconstructed each time, or pushed into external storage and rehydrated. For agents that need to do work over time — debug a build, navigate a multi-step web flow, hold a shell open while a job runs — ephemeral sandboxes are an architectural mismatch.

Neither pattern is wrong; they’re each optimized for a different priority. The teams we’ve talked to keep wanting both.

The hybrid pattern: control plane outside, persistent execution inside

The third option is to put the agent loop in a separate, hardened control plane and let the execution environment be persistent when the workload calls for it. The agent’s orchestration never shares a process or VM with the agent’s tools. But the sandbox the agent operates in can be a real, long-lived Linux environment with a filesystem that survives between turns.

This is the architecture Noorle’s runtime is built on. The control plane — model routing, memory, scheduling, tool gateways, audit trails, multi-agent coordination — runs in our managed layer, completely outside any execution environment. Agents don’t have a path to it. They request capabilities through it.

The execution side is graded:

  • WASM sandboxes for fast, lightweight operations with strict memory and CPU limits and capability-based filesystem isolation. This is where the agent’s built-in code runner executes Python and JavaScript, and where customer-uploaded plugins run — the agent reaches for it directly whenever it needs to run code.
  • Container sandboxes for heavier workloads that need full isolation but don’t fit the WASM profile. These are ephemeral and scoped to a single session: created when the work starts and torn down with it, so nothing lingers between sessions.
  • Persistent machines — exposed to agents via the Computer capability — a dedicated Linux environment bound to the agent and shared across that agent’s sessions. It stays alive across turns with a real shell, persistent workspace volumes, long-running processes, and lifecycle management.

The agent picks the right tier (or has it picked for it) based on what the work needs. A one-shot HTTP call doesn’t justify a VM; a multi-hour debugging session doesn’t fit a 30-second WASM invocation. Different workloads, different boundaries, same control plane.

We covered the compute-tier reasoning in more depth in Compute Engines for AI Agents. The point worth pulling forward here is that the choice of execution tier is separate from the question of where the orchestration runs. You don’t have to pull the agent loop into the sandbox to get persistence, and you don’t have to give up persistence to keep the agent loop out of harm’s way.

Why the separation matters

A few properties fall out of this design that are hard to retrofit if you start with one of the other patterns:

The control plane survives the agent. If an agent corrupts its own working directory, gets stuck in a loop, or trips a tool that crashes its environment, the orchestration layer is unaffected. It can kill the runaway process, restart the sandbox, replay the journal, or escalate to a human. None of that is possible if the supervisor lives in the same process as the thing it’s supposed to supervise.

Credentials never enter the sandbox. Tool authentication happens in the control plane. The agent makes a request through a gateway; the gateway holds the secret. The sandbox sees the result, not the key. The same pattern lets us govern which agents reach which tools, and rate-limit them independently of the model’s behavior.

Persistence is opt-in, not load-bearing. Because the orchestration doesn’t depend on local state, you can throw away a sandbox and rebuild it without losing the agent. State that should persist (a workspace volume, a long-running process) does. State that shouldn’t (a stuck shell, a corrupted env) is cheap to discard.

Scaling is per-tier. Control-plane capacity scales with orchestration load — model calls, scheduling, journals. Compute capacity scales with the work the agents do. They don’t have to grow together, and they have very different cost profiles.

Multi-tenancy works. Isolation, audit, and governance live in the layer that all tenants share, not in the sandbox an individual agent might compromise. We didn’t have to bolt this on; it’s a property of where the boundary lives.

PatternControl-plane safetyPersistent stateScaling profileWhere it fits
Agent loop inside sandboxWeakEasyCoupledLocal prototypes
Agent loop outside, ephemeral onlyStrongNoneClean but statelessLab / one-shot agents
Agent loop outside, persistent insideStrongYes, when neededIndependent per tierProduction workloads

What this looks like in practice

A concrete shape for the persistent case: an agent is asked to triage a build failure in a repository. The control plane picks the model, retrieves the relevant memory, and starts the loop. The agent requests a Computer environment — a persistent Linux machine — and clones the repo into a workspace volume. Subsequent turns reuse the same shell, the same checkout, the same browser session if it opened one. The agent can run a 20-minute test suite without the orchestrator holding a connection open the whole time.

Throughout, the control plane is recording every step in a journal it owns. Token budgets, execution quotas, and tool-access rules are enforced outside the sandbox, so the agent can’t disable them by misbehaving. When the work is done, the workspace either persists for the next session or is torn down — that’s a policy decision, not an architectural one.

The same runtime is what’s underneath our Autonomous Agents, MCP Gateways, and Workflows. They differ in the surface they expose, not in where the boundary lives.

Why we made this the default

Putting the agent loop outside isn’t a novel idea — security-conscious teams have been doing it for a while. Persistent execution sandboxes aren’t novel either; they’re how cloud development environments work. The combination is what’s worth being deliberate about, because the obvious-feeling shortcuts — “just run the loop in the sandbox so we get state for free,” or “just make every sandbox ephemeral so we don’t have to think about isolation” — quietly bake in the trade-off you’ll spend the next year trying to undo.

If you’re earlier in the curve, the hybrid pattern is worth considering before you commit to one of the simpler ones. If you’re already feeling the limits of whichever you picked, it’s the gap that’s probably hurting.


If you want to see the hybrid runtime in practice, look at the platform or start with the docs.