Self-Hosted OpenHands for Autonomous Code Execution
Building an autonomous code agent requires understanding its sandbox boundaries before deployment.

OpenHands gives a developer complete control over an autonomous coding agent, provided that developer understands what pieces make up the system before turning the keys over to it. The agent is built to run the full software engineering loop on its own: it reads an issue, writes the code, runs terminal commands, looks up documentation, calls APIs, runs test suites, debugs what fails, and opens a pull request, all without a human directing each step.
What ships today looks different from what the project looked like at its start. Agent Canvas is the browser-based client. The Software Agent SDK and the Agent Server are what actually run the agent. An Automation Server handles jobs that fire on a schedule or in response to events. The CLI is still there and still supported. The older Local GUI has been marked deprecated. Put together, these changes mark a real shift in how the project expects people to deploy it: away from a Docker-run graphical tool and toward an SDK-first, programmatic setup meant to be built into pipelines and services.
That shift matters because of where All Hands AI has drawn the line between what's free and what isn't. Single sign-on, role-based access control, audit logs, LLM budgeting, and the guardrails that catch prompt injection are not part of the MIT-licensed core. A self-hoster gets the whole engine for free, but the dashboard and the guardrails that a security team would want before putting this in front of a company's codebase are sold separately. That gap is the first thing to understand about self-hosting OpenHands, since it decides how much infrastructure work the self-hoster is actually signing up for before anyone touches a single sandbox setting.
The agentic execution loop and the sandbox it needs
The agent's usefulness and its risk come from the same source: it doesn't just suggest code, it runs it, immediately, to check whether its own reasoning holds up. That loop isn't optional or advisory. The agent installs packages, runs test suites, shells out to whatever command it decides it needs, browses the open web, and rewrites files on disk, because that's how it confirms a fix actually works. Strip out any one of those capabilities and the agent stops being able to do the job it's built for.
In practice that means swapping from a LocalWorkspace to a DockerWorkspace to a RemoteAPIWorkspace is the only code change required to move an agent from a laptop to a remote, isolated environment. The MCP integration isn't a roadmap item either: microagent skills can spin up their own MCP server the moment a skill activates, registering new tools on the fly while the agent is running.
Put these pieces together: every task OpenHands runs creates a live arbitrary-code-execution surface, because the agent's value depends on actually executing what it writes. That surface can't be designed away without breaking the thing that makes the agent an agent. It can only be contained. How well it's contained, and at what layer, is the question the rest of this piece works through.
What Docker sandboxing provides
For most people self-hosting OpenHands today, Docker is the sandbox, and for a large share of real use, it's enough. Each agent session gets its own container: its own filesystem, its own shell, its own browser, its own editor. The host machine stays untouched, and under ordinary operation, the agent has no path to damage the real environment it's running on top of. That's a genuine, functional boundary, not a cosmetic one.
What a container actually enforces breaks down into a few concrete mechanisms. Control groups (cgroups) cap how much CPU and memory any one container can consume, which keeps one runaway agent from starving the others.
All of that sits on top of one shared assumption: every container on a host uses the same kernel as the host itself, and that shared kernel is the structural limit. If a kernel vulnerability surfaces, an agent running inside a container can potentially use it to escape the container and reach the host directly. Sharing one kernel across every sandboxed process on the machine is the architectural consequence that produces this.
That limit matters most in two situations. A misconfigured sandbox under these conditions is a direct remote-code-execution risk, not a box to check for a compliance form, and nothing in the MIT core enforces a hardening policy on a self-hoster's behalf. That responsibility stays entirely with whoever stood the system up.
Why Firecracker microVMs provide qualitatively stronger isolation than containers
The alternative to a shared kernel is giving each sandboxed workload its own kernel, enforced by the hardware underneath it rather than by rules running inside the same kernel the agent can touch. That's the architectural move a microVM makes, and it changes where the security boundary sits rather than just reinforcing the boundary that's already there.
Firecracker, built by developers at Amazon Web Services and written in Rust, is the clearest example of this approach in wide production use: it's the virtualization engine behind AWS Lambda and AWS Fargate. Each Firecracker microVM boots its own guest kernel on top of hardware virtualization through KVM, instead of borrowing the host's kernel the way a container does. Two sandboxes built this way share no kernel code paths at all, so a kernel exploit inside one microVM has nowhere to go: it can't reach the host, and it can't reach any other microVM running alongside it. Firecracker also wraps its own process in something called a "Jailer," which layers cgroups, namespaces, and seccomp filters around the virtualization engine itself, restricting what that engine is allowed to do on the host. The isolation here is layered at multiple points, not resting on one single control.
The two models are architecturally distinct. A container, under Docker's default setup, shares a kernel with the host, relies on namespace separation and cgroup limits, and leaves open the possibility of escape through a kernel vulnerability. A microVM gives each workload its own kernel on top of hardware virtualization, so a kernel exploit inside one VM has no path to the host or to any other VM. That's the current standard for running code nobody can fully vouch for in advance.
The common objection, that containers hardened with seccomp and AppArmor are good enough, misses where the actual boundary sits. Those controls operate in userspace and in kernel-space, which is precisely the layer where the agent itself is operating. A microVM's isolation is enforced by hardware, a level below anything the agent can reach, regardless of what it's running or what it's trying to do.
The infrastructure decisions that determine whether a self-hosted deployment scales
Running OpenHands on a single machine for a single developer is genuinely simple, and the MIT core handles that case well. The infrastructure work starts once that same deployment needs to support a team, or scale to one agent session per user across an organization, because the core project does not solve that problem for the self-hoster.
Kubernetes, the default choice for most teams scaling anything, runs into a specific limitation here: it has no native concept of hibernating a pod. And the standard tag-based FinOps tooling most teams already use assumes a stable, traceable mapping between a given pod and the team or customer it belongs to. Once agents start getting suspended and resumed onto whatever worker node happens to be free at the time, that mapping disappears, and cost attribution breaks along with it.
A cost problem causes this: it has nothing to do with isolation and everything to do with how agents actually spend their time, most of it waiting on a user. General-purpose cloud compute already runs at low average utilization, and idle agent sandboxes push that number lower still, which makes paying for idle compute the single biggest economic drag on any fleet-scale deployment.
The fix that's emerged for this is snapshot-restore, and it depends on a distinction that's easy to blur: ephemeral scale-to-zero deletes the sandbox and loses its state, while perpetual scale-to-zero pauses the sandbox and keeps the state intact. Done well, the approach is to boot a machine once, snapshot it while running, and restore from that snapshot every time a new session starts, which performs like a warm, pre-started pool without the cost of actually keeping one running. The same mechanism supports branching exploration: a fork clones a running sandbox using copy-on-write, sharing guest memory through MAP_PRIVATE and cloning the root filesystem with a reflink, so each reasoning path the agent tries becomes its own fully isolated machine. Snapshotting applies that same trick across time.
Raw Firecracker gives a team the primitives to build all of this, and the primitives are genuinely open. But a complete implementation also needs a networking pool, a scheduler, egress controls, and multi-tenant billing layered on top, which turns this into a platform-building project.
Quota and cost-attribution problems in multi-tenant agent fleets
Once multiple agents are running at once for multiple users, the question facing the infrastructure changes. It's no longer only "is each agent properly isolated?" It becomes "how does the system stop agents from collectively burning through shared resources, and how does anyone know afterward who spent what?"
A specific failure mode appears here: sub-agents belonging to the same tenant can each individually stay under their own rate limit while, together, exhausting the tenant's entire shared quota. Without active coordination between them, this failure is invisible right up until it happens. The fix is a shared ledger kept per tenant, where each agent registers a soft reservation the moment a task starts, the ledger tracks total reserved capacity alongside what's actually been consumed, and agents sitting idle donate their unused capacity back to the shared pool.
An agent-specific FinOps stack is forming around three layers of control. Per-action token budgets cap how much context any single tool call is allowed to consume. Per-agent budgets cap total spend across an entire session or task thread, with automatic escalation or graceful slowdown as a session nears its limit. Fleet-level throttling caps how many agents can run concurrently across the whole system, stopping a runaway process from draining API quota that other agents and other users depend on.
Token costs from the underlying LLM compound on top of whatever the infrastructure already costs, and the range is wide. A multi-hour autonomous run against a genuinely complex issue can cost far more than that again, and without something like a context condenser trimming what the agent re-reads, that cost climbs further still. Managing this is a core part of running a fleet. All Hands AI's September 2026 Enterprise release added a budget dashboard that shows each member their own usage, alongside organization-wide secrets management added separately. Both live in the Enterprise tier, not the MIT core, so a self-hoster running a multi-tenant fleet either builds the equivalent controls directly or pays for the tier that already has them. A self-hoster who has fully solved VM-level isolation has not yet solved this problem: it sits one layer up, at the application and billing level, and nothing about strong sandboxing touches it.
Persistent, VM-isolated agent infrastructure for production OpenHands deployments
A production deployment of OpenHands that can handle a team's workload, keep agent state alive across sessions, and hold up strong isolation guarantees is achievable today, but it does not happen by default. It requires deliberately choosing an infrastructure layer built to solve snapshot-restore, per-agent VM isolation, and idle-cost control, rather than assuming the agent platform will handle any of that on its own.
The requirements that sit outside the OpenHands MIT core, for anyone building this for production, run through each of the problems laid out above. Isolation has to move from a shared-kernel container to a hardware-virtualized microVM for any workload touching untrusted input or running inside a multi-tenant environment. Idle compute has to be solved through genuine snapshot-restore, pausing and resuming machine state, rather than through either an always-on warm pool or a scale-to-zero setup that throws state away. And budget enforcement has to exist at the level of the token, the agent session, and the fleet all at once, because any single layer left uncapped becomes the layer where costs quietly run away.
None of these are OpenHands problems in the sense of a bug to file against the project. They are infrastructure problems that sit in the layer OpenHands was built to run on top of. A team can build that layer directly on open primitives like Firecracker, accepting the scheduler, networking, and billing work that comes with it, or it can adopt a platform built specifically to handle snapshot-restore and per-agent microVM isolation as a managed layer underneath OpenHands. Either path demands the same understanding: self-hosting OpenHands means owning every layer beneath the agent loop, and the agent loop is only as trustworthy, and only as affordable, as the infrastructure built to carry it.
Sources
- Making Containers More Isolated: An Overview of Sandboxed Container Technologies
- AI Code Sandboxes: A Comparative Security Study. Part 1 of 2 -- Engine-Level Properties (Attack Surface, Leakage, Stackability, CVE History, Patch Cadence, Fuzzing)
- The OpenHands Software Agent SDK: A Composable and Extensible Foundation for Production Agents


