Every coding agent you run is, from the kernel's point of view, an untrusted user who types very fast. It fetches dependencies, executes generated code, opens sockets, and writes files — all inside your cluster, all at machine speed, all authored by a model that has never read your threat model. The industry's answer has converged on running each agent session in its own sandbox, and Kubernetes finally has an upstream answer for what that sandbox should be: the SIG Apps Agent Sandbox project, a Sandbox CRD that packages a stateful, singleton, isolated pod with a stable identity behind one declarative API.
The question for a self-hosted platform team is not whether to sandbox agent code — it is which parts of the stack to adopt: the upstream controller or a hand-rolled StatefulSet, gVisor or Kata Containers underneath, and how many warm sandboxes to keep burning idle capacity so agents resume in milliseconds instead of tens of seconds. Here is the whole decision on one table, then the numbers behind every cell:
| Decision | Default pick for coding agents | When to pick the other one |
|---|---|---|
| Controller vs hand-rolled StatefulSet | Upstream Sandbox controller: one CR replaces a StatefulSet plus PVC plus headless Service plus suspend/resume glue | Hand-roll only if you need multi-container sidecars per agent today — Sandbox is a single-container primitive |
| gVisor vs Kata isolation | gVisor for CPU-only coding agents: no KVM needed, ~150 ms added startup, syscall filtering | Kata when tenants are mutually untrusted or you need GPUs: hardware boundary, VFIO passthrough, at the price of KVM plus 150–500 ms boot |
| Warm pool size | Pool the p95 of concurrent sessions, hibernate the rest to PVC-backed zero | Size zero only if your agents tolerate 5–30 s cold starts on every resume |
What the upstream controller actually is
Agent Sandbox lives at kubernetes-sigs/agent-sandbox, a SIG Apps subproject incubated at Google, and its own mission statement names the workload exactly: "isolated environments for executing untrusted, LLM-generated code." The Kubernetes blog introduced it in March 2026, and Red Hat shipped a supported build that July — this is past the experiment stage and into the adopt-with-eyes-open stage.
The API is four objects. Sandbox (agents.x-k8s.io/v1beta1) is the core: one agent definition maps to at most one running pod, with a stable hostname and network identity so multi-agent setups can discover each other, plus persistent storage so state survives restarts. SandboxTemplate is the reusable blueprint — image, resources, and isolation policy in one place. SandboxClaim is the user-facing request, deliberately shaped like the PVC-to-PV relationship: a developer claims a sandbox from a template without knowing which node or pool backs it. SandboxWarmPool keeps N pre-provisioned sandboxes ready so a claim resolves against a running pod instead of scheduling a new one.
Two lifecycle properties do most of the economic work. First, idle sandboxes scale to zero: suspend means the pod drops to nothing while the PVC keeps the workspace, and resume scales it back with state intact. Mostly-idle agents — which is nearly all of them between tool calls — stop consuming CPU and RAM the moment they go quiet. Second, the controller delegates the actual isolation boundary to whatever RuntimeClass the template names, so the gVisor-vs-Kata choice becomes a per-template field instead of a per-cluster rebuild.
What you stop hand-rolling
Before this controller, the standard recipe for one persistent agent environment on Kubernetes was a small pile of hand-wired objects: a StatefulSet (stable hostname, singleton replica), a PersistentVolumeClaim template (workspace survival), a headless Service (stable network identity), a NetworkPolicy (no chatty-neighbor exfiltration), and then the part nobody demos — a suspend/resume mechanism, usually a cronjob or operator that scales the StatefulSet to zero after idle timeout and back up on demand, plus the bookkeeping that remembers which PVC belongs to which agent across the gap.
The Sandbox controller absorbs the StatefulSet, the PVC wiring, the identity, and the suspend/resume loop into one reconciled object. What it does not absorb is worth naming, because it is the remainder of your own runbook: image pulls still take as long as your registry locality allows, NetworkPolicy is still yours to write per tenant tier, per-tenant CPU/RAM quotas still live in ResourceQuotas you define, and admission control over which templates a tenant may claim is still your policy agent to enforce. Adopt the controller to delete the lifecycle glue, not the platform thinking. The honest accounting is that it removes roughly the most bug-prone third of the stack — the stateful identity plus idle-lifecycle state machine — while the networking, quota, and supply-chain thirds stay exactly where they were.
There is one more structural limit to budget for: a Sandbox is a single-container primitive. If your agent session needs sidecars today — a proxy, a metrics exporter, a filesystem syncer riding alongside the agent process — that shape still wants a StatefulSet or Deployment you assemble yourself. For the common coding-agent case (one workspace, one process tree, one network identity), the singleton constraint is a simplification, not a sacrifice.
gVisor or Kata: the isolation decision with numbers
Both runtimes plug in through RuntimeClass, so a single cluster can offer both behind different templates — a coding-default template on gVisor and a coding-untrusted or gpu template on Kata, claimed through the same SandboxClaim surface. The choice per template comes down to four numbers and two hard constraints:
| Property | gVisor (runsc) | Kata Containers |
|---|---|---|
| Isolation model | User-space kernel (Sentry) intercepts syscalls; software boundary | Lightweight micro-VM per pod (QEMU, Cloud Hypervisor, Firecracker); hardware boundary |
| Added startup | ~150 ms | ~150–300 ms (Firecracker at the fast end, QEMU slower; up to ~500 ms worst case) |
| Steady-state tax | +20–60% syscall latency vs native runc; roughly 84 MiB per sandbox | +50–100 MB RSS per pod; ~5–15% overall overhead |
| Host requirement | None — runs anywhere runc runs | KVM (/dev/kvm) on every node scheduled for Kata pods |
| GPU story | Effectively no: nvproxy covers NVIDIA CUDA compute through a limited ioctl allowlist, no hardware GPU isolation | Full device via VFIO passthrough — but the whole GPU goes to one pod, no sharing |
| Best fit | Your own agents and semi-trusted tenant code on shared nodes | Mutually untrusted tenants, regulated workloads, anything needing a hardware boundary or a GPU |
Read the table as two different answers to "who am I afraid of." gVisor's syscall filter is a strong answer to buggy or reckless code — the agent that rm -rfs the wrong path or pulls a malicious dependency hurts only itself, and Google runs this exact technology under Cloud Run and GKE Sandbox at planetary scale. It is a weaker answer to a deliberately adversarial tenant probing for kernel escapes from a shared host kernel, because the host kernel is still one boundary away. Kata inverts the tradeoff: each pod gets its own guest kernel behind a hypervisor, so a container escape still faces the VM boundary — but you pay per-pod megabytes, hundreds of milliseconds of boot, and the operational fact that every Kata node needs KVM.
The GPU row deserves emphasis because it surprises teams. Coding agents today are CPU workloads — edit, test, lint, repeat — and gVisor handles them with zero node prerequisites. The moment an agent workload wants a GPU (local inference, CUDA test runs), gVisor's answer thins to an allowlisted proxy while Kata hands over the whole card through VFIO. Note the corollary neither runtime gives you: fractional GPU sharing is a separate layer (DRA, HAMi, or time-slicing), not something either sandbox runtime provides. If your roadmap has "many agents share one GPU," budget that project independently of this decision.
The practical fleet answer is tiering, not a winner: gVisor as the default template for first-party and low-risk agent sessions, Kata for untrusted-tenant and GPU templates, both claimed through identical SandboxClaims so tenants never learn which boundary sits underneath them.
Warm pools: what a millisecond resume actually costs
Cold-starting a sandbox pod takes 5–30 seconds end to end — scheduling, image pull, container start, plus a VM boot when the template names Kata. The Kubernetes blog's own figure for just the new-Pod overhead is about a second, and that second breaks interaction continuity every time an agent resumes. A SandboxWarmPool converts that wait into a claim against an already-running pod: the pool hands one over in milliseconds to a few seconds and immediately starts refilling the empty slot.
The price is idle capacity, and it is exactly countable: pool size N times the template's CPU/RAM requests, burning 24 hours a day whether agents are working or not. Three rules keep the bill honest. First, size the pool from measured concurrency, not optimism — the p95 of simultaneous active sessions, since the p99 burst can cold-start without anyone noticing among hundreds of fast claims. Second, pair every pool with aggressive hibernation: a claimed-then-idle sandbox should suspend to its PVC within minutes, so the pool pays for readiness while individual sessions pay only for active time. Third, remember the pool and the hibernation solve opposite ends — the pool shortens the first claim, hibernation cheapens every idle minute after it. A pool of five with no suspend timeout is just five servers you heat for fun; suspend-to-zero with no pool is cheap and sluggish. The upstream design wants both knobs turned at once, and the community's rule-of-thumb reports (sub-second claims against pools of 3–5 for team-scale fleets) match that shape.
One subtlety worth instrumenting from day one: track claim latency at p50/p95/p99 separately from first-command latency. "Warm allocation in milliseconds" measures handing over the pod; the agent's first real command still pays container-exec and filesystem-cache warmup. If you only graph one, graph the one your developers feel.
What this means on a self-hosted fleet
Three checks decide how smoothly this lands on owned hardware. First, KVM availability: Kata needs it, gVisor does not, so verify /dev/kvm on the node pool behind your Kata template — trivially true on bare metal, worth one explicit check on rented virtual machines. Second, image locality: the single biggest slice of cold start is the pull, so pre-pull sandbox images to every node (a DaemonSet or the pool's own refill traffic does this naturally) and keep a registry mirror close to the fleet. Third, template governance: because isolation is now one field in a template, the dangerous misconfiguration is a tenant claiming a weaker template than their trust level allows — gate SandboxClaim creation per namespace with the same seriousness you gate RuntimeClass today.
None of this requires a hyperscaler. A small Cluster API fleet on flat-rate hardware runs the controller, both runtimes, and a modest warm pool as ordinary reconcilers and pods — no per-second meter ticking while sandboxes idle, no per-claim fee on the resume path. The idle-capacity math that makes warm pools debatable on a metered cloud (every warm pod is metered compute) collapses on owned boxes to hardware you already bought: the pool consumes a slice of sunk capacity instead of adding a line item.
Sandboxed agents are infrastructure now, not a demo trick — every team running coding agents is operating a multi-user execution platform whether they named it one or not. The upstream controller gives that platform a standard API, the two runtimes give it two well-understood trust tiers, and the warm pool turns resume latency from a physics problem into a capacity-planning row. Adopt all three deliberately, measure the claim latency, and let tenants pick templates while you keep the keys to which template means what.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Agent sandboxes like these are exactly the kind of tenant workload it schedules onto your own Cluster API fleet. Star the repo on GitHub or deploy your first app today.



