# Kubernetes sandbox platform: using Substrate without an LLM

> A Kubernetes sandbox platform is Agent Substrate without the LLM: dense sandboxes, suspend and resume, and a worker pool that pods do not give you.

- Canonical URL: https://webofmike.com/kubernetes-sandbox-platform/
- Author: Mike Moore (https://webofmike.com/about/)
- Published: 2026-11-09
- Last modified: 2026-11-08
- Tags: Kubernetes, Platform Engineering, AI Agents
- Cite as: Mike Moore, "Kubernetes Sandbox Platform", Web of Mike (webofmike.com), 2026-11-09. https://webofmike.com/kubernetes-sandbox-platform/


<!-- ART: a WorkerPool labeled not agents, filled with CI jobs and idle shells as snapshot cards. -->

A Kubernetes sandbox platform is what Agent Substrate still is after you ignore the word agent: a pool of sandboxes, native suspend and resume, rehydrate from object storage, and capacity you scale independently of how many sandboxes exist. Pods do not do that. A Pod that is idle still reserves, and a Job that completed is gone.

I would not migrate a stateless web app onto this. I would look at it for work that is mostly parked. The same density graph I measured with agents (nine, then 18, on two workers, over a thousand sessions, reserved capacity about 4.5x lower than always-on pods) is a statement about idle time, not about language models. [What is Agent Substrate](/what-is-agent-substrate/) is the runtime. This page is the primitive with the LLM left off.

## What is a Kubernetes sandbox platform without an LLM?

A WorkerPool of pre-warmed sandboxes. An ActorTemplate for the workload. Idle state as a zstd snapshot in object storage. Restore onto a free worker when someone actually needs the process. One actor per worker. Isolation is still a sandbox. gVisor in my lab.

Kubernetes gives you two shapes that almost look like this and are not. A Deployment that is scaled to zero is gone: cold start is a pod boot, and there is no process memory waiting in a bucket. A paused container still holds the node's RAM. A Job that waits on an approval still holds a CPU request while it waits. Substrate's trick is that the interesting state is a filesystem and a little RAM you may need again later, stored off the node, restored onto any free bay.

The dataplane does not care that the process was an SRE on-call assistant. `ateapi` still holds assignment. `atenet` still routes into the actor. `atelet` still moves snapshot bytes. `ateom` still talks to `runsc`. I mapped those names in [Agent Substrate dataplane](/agent-substrate-dataplane/). If you skip the LLM, you still have to operate those four processes, plus object storage.

The kagent concept page already says the quiet part: Substrate is a Kubernetes-native runtime for AI agents *and other stateful workloads*. I am not stretching the product pitch. I am saying which of those other workloads I would actually try, and which I would stop at the design review.

## Which non-agent workloads fit a snapshot-backed sandbox?

The pattern is the same as agents: lots of registered work, few actually running.

**Idle preview environments.** One sandbox per pull request, suspended overnight, restored when someone opens the link. Today we scale those as Deployments and pay for sleep. A preview that nobody is looking at is the same idle reservation I measured on always-on agents: CPU request sitting still, memory resident, graph looks cheap, bill is not.

**CI that waits.** A job blocked on an approval does not need a CPU request. It needs a snapshot and a resume hook from the approval webhook. Size the pool to jobs that are compiling or testing at once, not to jobs that are waiting on a human. That is [how many agents per Kubernetes pod](/how-many-agents-per-kubernetes-pod/) with the word agent crossed out: live work equals workers, registered work equals snapshots.

**Tenant shells.** A class of 200 students, 8 actually typing. That is the agent density graph with homework instead of tool calls. You do not need 200 pods. You need 8 worker slots and 200 snapshots, plus a buffer so a restore storm has somewhere to land.

In all three, the how-to is the same as [suspend and resume agents](/suspend-and-resume-agents/). Measure restore time. Put secrets back in at resume. Do not host-network. Do not checkpoint long-lived credentials. A snapshot is a copy. Copies leak. [Proof of agent identity](/proof-of-agent-identity/) still applies if you rename "agent" to "tenant."

A test plan I would run in a lab before I believed a non-agent sandbox:

- Bake a golden snapshot. Confirm it exists in the bucket you own, not on the node's disk.
- Suspend on node A. Confirm the worker is free. Restore on node B. Confirm the workspace files and the session id. If you cannot do that, you have a backup script, not checkpoint. [Agent checkpoint to object storage](/agent-checkpoint-to-object-storage/).
- Kill a session mid-flight. Confirm you can see the pinned slot on the workers list, not on `kubectl get pods`. Reset the pool. Confirm the snapshot survived. [Ghost actors pin your workers](/ghost-actors-pin-your-workers/).
- Fill the pool. Confirm the next restore is a rejection, not a queue. Decide who retries. [Who runs next when the agent pool is full](/who-runs-next-when-the-agent-pool-is-full/).
- Turn off the LLM. If the workload still makes sense, it was never an agent problem.

## When is using Substrate for non-agent work a bad idea?

**Anything with a Service and a stable IP.** Resume lands on a different worker. Your clients needed a proxy that tracks the actor, which is atenet in the agent case. You will rebuild a service mesh for a shell. Kubernetes NetworkPolicy attaches to pods. The actor is not a pod. [Kubernetes network policy for agents](/kubernetes-network-policy-for-agents/) is the composition, and it does not get easier when the process is a preview app.

**In-sandbox GPUs.** Same veto as [GPUs for agents](/gpus-for-agents-on-kubernetes/). GPU memory is not a file. Suspend drops that state or pins the device. Both are the opposite of multiplexing. Keep the device on a shared inference or build service. Call it from the sandbox.

**Databases.** Checkpointing Postgres "because we can" is how you discover WAL and sockets the hard way. Use a database. The sentry virtualized `flock()`. It will not virtualize a storage engine you pretended was a filesystem. [Does checkpoint survive a held file lock?](/substrate-pinned-resources/) is the writeup that made me more precise, not more reckless.

**High-frequency trading loops, game servers, anything latency-bound to a live process.** Restore is not `epoll`. Golden snapshot bake is about a minute in my lab. Later restore is faster and still not a warm in-memory process. If the time you save by parking is smaller than restore, you bought a control plane to lose.

**Long-lived TCP.** Suspend cuts sockets in the versions I have run. [Suspend-safe networking](/suspend-safe-networking/) is the missing piece. Do not park a CI job that is waiting on a live connection to a flaky device farm. Wait the call out, or put the I/O on a proxy that outlives the actor.

**Multi-tenant untrusted code with no egress policy.** Substrate does not forgive a missing [sandbox network](/sandboxed-networking-for-agents/). Non-agent workloads are not safer. They are often worse, because people skip the identity work. A student shell with host network is a node NIC with homework on it.

**Software that assumes it is a Pod.** Probes, a Service, a PDB, downward API, "my IP is in an env var." Actors rotate through workers. Anything keyed on pod IP is wrong after restore. If the app cannot live behind a router that tracks the actor, it wants a pod.

## Why does this still teach you the agent case?

The reason these primitives fit agents is the same reason they fit idle previews: the interesting state is not CPU. It is a filesystem and a little RAM you may need again later. If a workload does not look like that, [agent-sandbox vs Agent Substrate](/agent-sandbox-vs-agent-substrate/) already told you to use a pod.

I would push a non-agent sandbox onto Substrate to find the edges without also debugging a model. Ghost slots, restore storms, DNS. Actor egress in my lab died when substrate's CoreDNS reload failed (`plugin/reload: Corefile changed but reload failed`). Restarting `deploy/dns` in `ate-system` fixed it. That failure has nothing to do with an LLM. It will still page you when the process is a preview environment that cannot reach the package registry.

CPU HPAs will still sleep through a full pool. Workers hosting live work idle at single-digit mCPU. [CPU is the wrong signal to autoscale agents](/cpu-is-the-wrong-signal-to-autoscale-agents/) is not agent-specific. Occupancy and rejections are. `kubectl get pods` will still show two quiet workers while the snapshot shelf is the actual fleet. [kubectl is lying to you](/kubectl-is-lying-to-you-watch-agent-substrate/).

Then I would put the LLM back. That is the only justification I have for the terrible ideas: some of them are tests. A restore drill that never talks to a model is a cheaper way to learn whether your bucket, your workers list, and your reset runbook work. [Running Agent Substrate in production](/running-agent-substrate-in-production/) is the checklist I would not skip either way.

A practical default:

- Idle-heavy, parked most of the day, restore is acceptable: try Substrate in a lab.
- Needs a stable IP, a GPU, a database, or a live process that cannot wait on restore: use a pod.
- Untrusted tenants: sandbox class on purpose, egress default-deny, identity per tenant. Do not skip those because the process is not named agent.

Field guide: [Agent Substrate](/agent-substrate-field-guide/).

