Sandboxes Aren't Optional: 4 Ways to Isolate Coding Agents — Robert Brennan, OpenHands
Read the talk
Sandboxes Aren’t Optional: 4 Ways to Isolate Coding Agents
Robert Brennan compares local Docker containers, GitHub Actions, dedicated machines and Kubernetes sessions—and explains why moving an agent off your laptop only helps when its access moves with the task.
From a talk by Robert Brennan
At a glance
Ideas worth remembering
Least privilege starts with the task’s required repository, secrets and tools. Restricting those inputs limits the damage from prompt injection or agent mistakes.
Local Docker preserves an interactive checkout-based workflow; remote jobs make scheduled and event-driven execution independent of the laptop.
A dedicated machine separates agents from your workstation, but colocated agents can still share unnecessary credentials and modify one another’s state.
Disposable session environments avoid carrying broken machine state into later runs. Useful outputs can persist separately in files or external systems.
Sandboxing reduces exposure without eliminating escape risks. Choose the execution environment deliberately, even when a tool makes switching environments easy.
From copying snippets to handing over a terminal
The first workflow was simple: ask ChatGPT for a SQL query, paste it into an IDE, run it, then paste the error back into ChatGPT. Robert Brennan, CEO and co-founder of OpenHands, remembers being astonished when the query worked immediately. But the repeated copying soon suggested an obvious improvement: connect the APIs and let software carry the messages.
AI-powered IDEs brought the model closer to the code. Cursor and GitHub Copilot could use repository context and available variable names rather than generate isolated snippets. Agents added another capability: executing the code they wrote, reading errors and searching for explanations. The development loop now included actions in an environment, so the environment’s permissions became part of the agent’s capabilities.
OpenHands followed that expansion, growing from an MIT-licensed coding agent into a platform spanning the agent harness, execution infrastructure and a control plane for monitoring agents at scale. Brennan frames the next transition as moving manually prompted laptop agents into the cloud. Each agent still needs a terminal and filesystem, but it may now work without a person watching every action.
Event-driven work makes that transition useful. A GitHub event, Datadog incident or Slack message can start an agent; one agent might open a pull request while another reviews it. Brennan’s longer-term forecast is full software-development lifecycle automation, potentially without humans reading source code. The immediate engineering question is narrower: how do you give an unattended agent somewhere to work without giving it everything you can access?
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Skipped permissions inherit the reach of your account
Brennan asks who runs a local coding agent, then asks users of “dangerously skip permissions” to keep their hands up. “Somehow more hands than before.” The joke captures the attraction: repeated approval prompts interrupt autonomous work, while skipping them lets the agent continue without supervision.
In the unrestricted local setup he describes, the agent can reach the filesystem, environment-variable secrets and credentials stored in the home directory. If those credentials provide access to a production database or Kubernetes cluster, the agent can use that access too. A mistaken command or malicious instruction can therefore affect resources far beyond the repository being edited.
The corrective mechanism is the principle of least privilege: give the agent only what its job requires. For a repository task, that might mean access to the relevant GitHub repository and a few credentials for a local database. First identify those inputs; then construct an environment containing them. This reduces the blast radius of prompt injection or ordinary confusion by reducing what the agent can read, change or use.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
1. Docker keeps the local workflow and narrows its inputs
OpenHands originally created a fresh Docker container for each new conversation. The agent received a disposable environment: if it destroyed that environment with a command such as rm -rf /, the recovery was to discard the container and start another. That reset addresses damage inside the disposable environment; the repository, secrets and other resources deliberately exposed to it still determine the agent’s reach.
Selective connections make the container useful without reproducing the whole laptop inside it:
- Repository access. Mount the local Git repository so the agent edits the working copy you already use.
- Application access. Expose application ports so you can inspect the running app in your browser.
- Credentials. Pass specific secrets and environment variables needed for the task.
- Tool access. Run MCP servers on the laptop or inside the container, depending on where those tools belong.
This preserves a familiar division of work: the agent edits your local checkout, while you inspect the changes and decide when to push. The cost is that execution remains tied to the workstation. A laptop has limited capacity for simultaneous containers, and the local arrangement Brennan describes is oriented around manual work rather than an always-running service receiving Slack or Datadog events.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
2. GitHub Actions turns repository events into agent jobs
Running Claude Code in GitHub Actions changes where the working copy lives. An ephemeral job clones the repository, runs the agent and sends its work onward before the execution environment disappears. The agent no longer edits the checkout on your laptop. GitHub Actions supplies the job infrastructure and a built-in place to manage secrets.
Two examples show what becomes possible when a laptop prompt no longer starts every task:
- Scheduled maintenance. Every Monday at 9 a.m., an action starts an agent to update dependencies.
- Pull-request review. Opening a pull request starts an agent that reviews the proposed code.
These are separate triggers for separate jobs. Both let repository work begin without a developer keeping a local process alive.
The capacity tradeoff moves from laptop resources to paid job execution. The integration tradeoff is attachment to GitHub Actions’ workflow system. Brennan describes the straightforward setup as GitHub-centered: it does not directly receive Slack or Datadog webhooks. That limitation applies to the integration presented here; the talk does not establish that external events could never be connected through additional infrastructure.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
3. A dedicated VM adds persistence—and shared exposure
Another approach puts the agents on a separate computer: a cloud virtual machine or a dedicated Mac Mini. Unlike a disposable Actions job, this machine survives between runs. An agent can modify the system and find those modifications still present two days later. Unfortunately, a broken configuration can survive just as reliably, leaving someone to investigate and repair it.
A VM also provides a place to run scheduled work and receive incoming webhooks. Brennan’s examples include Twilio text messages, Slack messages, Datadog incidents and GitHub events. This gives agents a broader set of automatic starting points than the GitHub-centered setup, with a long-lived environment available between tasks.
But separating agents from your laptop does not necessarily separate them from each other. Consider a code-review agent and a Datadog incident-triage bot sharing a VM and its resources. The reviewer may inherit Datadog access it does not need. It may even be able to edit the triage bot’s memory. The failure is specific: colocating jobs with different responsibilities can pool their credentials and writable state, recreating the least-privilege problem on another machine.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
4. A Kubernetes pod per session starts each job fresh
Brennan’s preferred strategy for scalable autonomous work is an ephemeral environment for every agent session, implemented with Kubernetes or a comparable platform. A pod starts, the agent works in its own repository copy, and the session ends after producing something useful, such as a pull request. The execution environment is then discarded.
Starting fresh prevents one session’s damaged environment from becoming the default starting point for the next. Giving each session its own workspace also avoids the shared-workspace problem of the colocated VM example. Those benefits depend on how the environment is provisioned: the least-privilege requirement still determines which repositories, secrets and external systems each session should receive.
Cloud capacity supports more concurrent sessions than a laptop, with CPU and memory becoming explicit costs. Brennan later contrasts a handful of comfortable local runs with thousands of Kubernetes agents; this is a capacity comparison, not a measured throughput result. Cron jobs can start scheduled sessions, while HTTP events from Slack, GitHub or Jira can initiate event-driven work.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Compare the workspace, persistence and trigger—not just the host
Which differences actually change how you work? Brennan compares five dimensions: local versus remote execution, scale, isolation, persistence and triggers. Local execution lets the agent work on your existing checkout. Remote execution gives it another copy and lets the job continue independently of your workstation. Neither choice alone answers how much access the agent receives.
The comparison below separates two easily confused properties: whether the execution environment survives, and whether agents share access within it.
| Setup described | Working copy and scale | Isolation and persistence | Typical starting point |
|---|---|---|---|
| Local Docker | Local checkout; laptop-limited capacity | Fresh container per conversation; selected local resources exposed | Manual prompt |
| GitHub Actions | Cloned remote checkout; paid job capacity | Disposable job environment | Schedule or GitHub event |
| Dedicated VM or Mac Mini | Separate machine; capacity of that machine | Long-lived state; colocated agents may share resources | Schedule; a VM can receive webhooks |
| Kubernetes session | Session workspace; cloud CPU and memory capacity | Separate workspace per session; environment discarded afterward | Cron job or HTTP event |
The crucial distinction is visible in the dedicated-machine row: remote execution can protect your workstation while still leaving agents able to interfere with one another.
Ephemeral execution does not require throwing away useful results. Files can be saved outside the environment, and agents can write to external systems. The difference is that persistence becomes a deliberate choice instead of an automatic consequence of keeping a laptop or VM alive. Remote execution also solves a more human problem: Brennan jokes about biking home with a laptop open so Claude Code will not stop.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Sandboxes reduce exposure; the environment still needs choosing
A sandbox is not a guarantee of containment. Brennan cites an Anthropic testing incident in which an agent reportedly escaped its sandbox and gained internet access; the recording does not provide the exploit details needed to evaluate that example. He also points to container-escape vulnerabilities, including risks from older Docker versions. Sandboxing remains a useful first restriction on an agent’s reach, while the containment mechanism itself can have flaws.
The closing product example, OpenHands Agent Canvas, separates the coding harness from the execution environment. Brennan describes support for Claude Code, Codex and the OpenHands harness, with controls to switch execution into Docker, a remote VM or Kubernetes. He characterizes its default local mode as comparable to running Claude Code with skipped permissions, making the environment selection consequential rather than cosmetic.
The choice follows the work. Quick back-and-forth development may benefit from the local checkout, where you can inspect code as the agent edits it. An event-triggered task expected to run autonomously for several hours benefits from a remote VM or Kubernetes session. Agent Canvas is presented as a way to move between those arrangements: keep the harness you want, then choose the environment—and the access—that the job needs.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Read the complete timestamped transcript
- 0:12
Uh, my name is Robert Brennan. Uh, I'm the CEO at OpenHands, uh, and I wanna talk to you a little bit about-- today about, uh, sandboxing coding agents, uh, why this is a really important pattern and, uh, different ways to actually get this done. Uh, a little bit about me. Um, like I said, I'm the, I'm the CEO of OpenHands. Uh, co-founded it, uh, a little over two years ago, really with the vision of bringing, uh, coding agents to the community, right? Uh, really giving software developers a say in the gigantic change that's happening to our
- 0:42
jobs. Uh, and we started OpenHands as an MIT licensed coding agent, uh, and I would say now we've, we've evolved really to a, a platform for running coding agents. Everything from the harness to the infrastructure to the control plane to actually, like, monitor these agents at scale.
- 1:00
Uh, a little bit about the history of AI-driven development and how we got to where we are today and, you know, where I think things are going in the future. Uh, we really started with, like, uh, code snippets being generated by a chatbot, right? I remember the first time I typed into ChatGPT, like, "Write a SQL query that does X," and it just, like, one-shotted it, and I was blown away. Uh, that feels very, um, uh, antiquated today. Um, but, uh, you know, my, my original workflow was a lot of, like, type into ChatGPT, paste something into my IDE, hit Enter, paste an
- 1:30
error message back into ChatGPT, and it's pretty quick that I realized, like, "Hey, this is kinda dumb. I can just, like, wire some APIs together." Uh, and very quickly we got, uh, these AI-powered IDEs. Stuff like Cursor and GitHub Copilot doing things like autocomplete, right? Where now you have the context of the code base. You're not just generating code snippets inside of a chat window, you're actually modifying the code itself. You can see the variable names that are available there. So the AI gets a little bit smarter, a little bit more context-aware. And then the big leap in, like, the beginning of twenty-twenty-four, uh, was this leap
- 2:00
to agents. So, uh, AI that wasn't just writing code, but was actually running the code that it wrote, right? Um, actually, like, looking at the error messages, googling them, really doing that entire loop of development on top of the LLM. Um, and that's kind of where we're at today. I would say most developers today are still-- They're running something like Claude Code or OpenHands, uh, or Codex on their laptop, um, uh, as, like, kind of a pair programmer model, right? They're manually prompting this thing. The leap that we're seeing organizations make over the course of
- 2:30
twenty-twenty-six is really to agents that run in the cloud, and this is really where sandboxing comes into play. Uh, one, because, you know, it needs a place to work in the cloud, right? You need to give this agent a terminal, a file system, et cetera. Um, but two, because, um, you're really, uh, you're able to do a lot more once you've got these agents in the cloud, right? Um, and you need to make sure that they have access only to the things that they're, they're allowed to access, um, 'cause there's not necessarily going to be a human there to babysit them, right? Um, going forward from there, I think the more we get
- 3:00
agents running in the cloud, running autonomously, running, uh, you know, in response to events coming out of systems like GitHub and Datadog and Slack, rather than being manually prompted, you're gonna get these interactions between agents where, like, one agent opens a PR, another's doing code review, and they're going back and forth, and we see these multi-agent teams emerging. Uh, and then I think the end game is really this full SDLC automation where, you know, humans aren't even looking at the source code anymore. Uh, but the really-- thing I really wanna talk today about is how do we make this leap from, from number three, where we're running agents on our machine, to number
- 3:30
four, where we've got agents running in the cloud?
- 3:34
Uh, so let's talk a little bit about, uh, running locally. Uh, who here runs Claude Code on their laptop or Codex or OpenHands? Something, some local agent. All right. Fewer than I would expect. Uh, keep your hand raised if you use Dangerously skip permissions. Yeah, okay. Somehow more hands than before. Um, so the, the-- this is the big trade-off when running agents locally, right? Is you can either sit there and hit, like, yes, yes, yes, you're allowed to do that, over and over again and babysit the agent while it works, or you can go into dangerly-- dangerously skip
- 4:03
permissions mode and just, like, trust that the agent isn't going to delete a file you really care about or access your production database or anything like that, right? Um, so running locally, you, you are kind of limited by those, those two options. Uh, and if you do run locally and you run with Dangerously skip permissions, uh, the agent does have access to a lot of things, right? It has access to your whole local file system, uh, it has acc-access to any secrets that are in your environment variables, uh, it has access to any secrets that are in, like, in your, in your home
- 4:33
directory. Uh, if you're connected to, like, a production database or a production Kubernetes cluster, the agent can get in there. It has access basically to everything that you have access to, right? Um, so super important that you, uh, either sit there and babysit it and watch what it's doing, or you find a way to cut off its access and really only give it access to the things that it needs. And this is a, this is a paradigm that we actually know well from, you know, pre-agent security days. It's the principle of least privilege, right? The idea is that both
- 5:03
agents and humans should only have access to the things that they need in order to do their job, right? So the agent shouldn't have access to every secret on your system. It shouldn't have access to every file on your system. It should only have access to the GitHub repo that it's editing and maybe a couple secrets that it needs to access a local database, something like that. Um, so it's important when we start to sandbox these agents that we're looking at what exactly does this agent need in order to do its job, and then we can create a sandbox that has just exactly those things. And then we know that the, the blast radius of a prompt injection attack,
- 5:33
uh, or the agent getting confused, anything that could go wrong, like, we, we limit the blast radius by limiting how much the agent has access to.
- 5:43
So the first strategy that folks tend to experiment with is running inside of Docker containers on their laptop. This is actually the, uh, way we originally launched OpenHands was as an interface where every time you started a new conversation with the agent, we'd spin up a brand-new Docker container, the agent would get its own, its own container, and this, this works really nicely for several things, right? Uh, one, it's ephemeral, so the agent can do kinda whatever it wants. If it runs rm -rf / and deletes everything, uh, you just kill the container and start again, right? It's, it's a very nice, uh-- the agent
- 6:13
can, can just kinda run wild. You don't have to worry too much about what it's gonna do. Um, and because it's running locally on your laptop, you can also mount in things selectively from your local file system, uh, you know, like a, a Git repo. Uh, you can mount ports so that the agent can run out an application, and you can view it in your browser. You can mount specific secrets and environment variables for the agent. Um, you can have MCP servers either running locally on your laptop or inside the Docker container. Uh, and it's nice because the agent is still working with, like, your local copy of the code, right? It's similar to how you're used to working where
- 6:43
you've got, like, a, a copy of the code on your workstation, and instead of you editing it, the agent's editing it now, and you're deciding when to Git Push and all that. Uh, but this doesn't really scale very well. Uh, there's only so many Docker containers you can get running on a laptop. Uh, your laptop can't, like, listen for events coming out of, like, Slack and Datadog, et cetera. Um, so this, this is pretty limited in terms of what you can do here.
- 7:05
The next strategy we see folks taking is starting to, like, glue together Claude Code and GitHub Actions. Um, uh, this is definitely different from, like, running Docker containers on your computer. Uh, now you're no longer working with your local copy of the code base. You're now, uh, you know, having, uh, this, this agent inside of a, like, an ephemeral environment, somewhere inside of GitHub Actions, cloning the repo, doing stuff, you know, uh, and then, like, shipping it off, and then everything, everything goes away once that action spins down.
- 7:34
But what's nice is that, you know, you can run as many GitHub Actions as you're willing to pay for, right? It has built-in support for things like a secrets registry. Um, so you get these nice, these nice isolated environments, and what's really cool is now you can run them on a schedule, right? You can just have a GitHub Action that spins up an agent, you know, every Monday morning at nine AM and updates your dependencies, right? You can have a GitHub Action that anytime a PR gets opened, is gonna use an agent to do code review. So you can start to get some automation in place now that the agents are, are off your laptop and in the cloud. Uh, but you're locked into GitHub
- 8:04
Actions, right? This is a proprietary standard. Uh, you're not gonna be able to really port this. Um, it's only able to respond to events coming out of GitHub, right? You can't respond to, like, a Slack webhook or a Datadog webhook. Um, so you're, you're kind of limited in terms of what you can do by just, like, gluing things together with GitHub Actions.
- 8:22
The next strategy we saw folks take was kind of in the OpenClaw craze where you actually get a separate computer, you know, a virtual machine in the cloud or maybe a Mac Mini, uh, and just put all your agents on that, right? Um, this is different from GitHub Actions in that now you've got a, a long-lived environment. You've got persistence, right? Which is good and bad, right? You, you-- your agents can modify the system and know it's gonna be that way again when they run, you know, two days from now. Um, but your machine could get into a bad state as well, and you might have to go and debug and figure out what's going on. Um, you can, again, you
- 8:52
can, uh, just like in GitHub Actions, you can run agents on a schedule. Uh, now since-- if you're on a-- running on a VM, you can actually listen for webhooks coming in from, uh, you know, Twilio, if you wanna listen for text messages, from Slack. Uh, you can listen for incidents coming out of Datadog, events coming out of GitHub. So you get agents running automatically now, uh, but you still have this principle-of-least-privilege problem, right, where all of your agents are now, like, co-located in this virtual machine, and they all have access to the same stuff. So you might have, like, a, a code review agent in there, uh,
- 9:22
alongside of, uh, you know, a Datadog triage, like, incident triage bot. And the code review agent now for some reason has access to Datadog, and there's just a lot more possibility for things to go wrong, right? The code review bot can even, like, uh, you know, edit the, the memory for the Datadog bot. Uh, so, like, there's this co-locating problem, uh, quickly runs into issues where agents have access to way more than they necessarily need in order to do their job. So way more opportunities for things to go wrong when all these agents are bumping into each other.
- 9:51
The fourth and, and really, like, the most robust strategy here, I would say, is to use Kubernetes, uh, or some other, like, you know, highly scalable environment, uh, that's ephemeral, right? Um, and now you're getting, you know, with Kubernetes, say, uh, you get a pod for every agent session you wanna run. Uh, it spins up, the agent runs, does its work, you know, maybe working on a local copy of the, of the repo. Then it spins down, and all that environment goes away. You know, the agent has opened up a pull request or something like that, right? Um, this is really nice because, uh, you don't have to worry about, like, the long-term
- 10:21
state of this thing the way you do with a VM. You don't have to worry about it getting into a bad state because every time an agent runs, you're, you're basically killing the environment and starting fresh. Um, and you get, like, an infinite amount of scale, right? You're-- You have cloud scale at this point. Um, you can run as many agents as you want as long as you're, again, willing to pay for the memory and CPU, uh, to run them.
- 10:41
And again, because it's, it's Kubernetes, it's running in the cloud, uh, you can respond to, uh, you can run things on a schedule using, uh, cron jobs. You can, uh, run things in response to HTTP events coming out of, you know, Slack and GitHub and Jira. Um, you can basically run agents fully automatically. Um,
- 11:02
a little, uh, kind of like quick comparison here. I'll just go down the, the, the things that I look at when I'm comparing these different strategies. Um, one is, is it local, or is it remote, right? Is it on your, on your laptop working with your copy of the code base, or is it running somewhere else that has to, like, clone in the code itself or with its own copy? Those are two very different ways of working. Um, what kind of scale can you get out of this thing, right? If you're, if you're running locally on your laptop, you can maybe run ones of agents before things start getting uncomfortable. If you're in Kubernetes, you can run thousands. Um, level of
- 11:32
isolation, right? Uh, if you're not running-- if you're running, like, dangerously-skip permissions on your laptop, you've got nothing. Uh, if you've got all your agents, like, co-located in a VM, they're separated from your environment, but they can still step on each other's toes. But something like Kubernetes, uh, every agent has its own workspace. You know, it's, it's doing its own thing. Uh, level of persistence. Um, you know, you can, you can always get some persistence by saving files out or, like, writing to external systems. Uh, but when you're working on your laptop or you're working in a VM, you do get just, like, persistence by default, right? That system is long-lived.
- 12:02
Um, and then what kinds of triggers can actually cause these agents to run, right? If you're running locally on your laptop, it's typically just gonna be a manual. You're typing in a prompt. Uh, once you get into the cloud, you can start to run things on a schedule or run things in response to events. Uh, if you've ever, like, uh, been, like, biking home with your laptop open 'cause you didn't want Claude Code to shut down, this is a great reason to start moving your agents to the cloud.
- 12:25
Uh, I did want to, uh, touch on the fact that sandboxing is not a panacea. Um, there is, uh, evidence of agents escaping their sandboxes. Um, you know, here we, we saw during, uh, one, when Anthropic was te- testing Mythos, uh, one of the Mythos instances actually managed to break out of its sandbox, gain internet access, start doing other things. There are container escape attacks out there. Um, some of them are known if you're running an old version of Docker, say. Um, so it's not, it's not
- 12:55
perfect. You still have to be a little bit careful. Um, but it is, it is at least a, uh, a good first pass at keeping agents limited to, uh, what they're-- what they should be doing.
- 13:07
Um, last, I'll give a quick plug for OpenHands Agent Canvas. Um, this is a way, you know, really to run, uh, with any type of sandbox. You can run it with Claude Code or Codex or the OpenHands harness. Uh, but we've designed it really to, you know, by default, if you saw it on your laptop, it's like running Claude Code with dangerously skip permissions. But with one quick toggle, you can start running things in Docker containers. Another toggle, you can start running it in a remote VM. Another toggle, you can run it inside of Kubernetes. Um, so it's a really great way to, like, pick the right environment for the job, right? Sometimes
- 13:37
you really do wanna be working with your local copy of the code base. You wanna be doing that quick iterative development back and forth with an agent where you're looking at the code locally. Sometimes you really just wanna fire off events that, you know, let agents run autonomously in the background for a few hours. Um, you really want it running inside of Kubernetes or inside of a VM. Um, so this is a, a great way to kinda move between these different types of environments. Uh, that's all I've got, but I'm happy to, to take questions from the audience.