Code sandboxes must meter burstiness, not average utilization
Code sandboxes must meter burstiness, not average utilization. An agent can look inexpensive across a ten-minute run while repeatedly creating second-long CPU spikes, memory peaks, subprocess fans, and network bursts that destabilize every neighbouring workload. Average CPU and memory describe the invoice after the fact; they do not describe the contention that makes execution unsafe.
Agent-generated code produces a burst-silence pattern. The model reasons quietly, then a tool call decompresses an archive, compiles a dependency tree, launches tests, or loads a dataframe. Research on agent resource dynamics finds that peak-to-average memory can diverge sharply and that the same nominal task can have high execution-time variance. Retry loops make the pattern worse: partial failures retain state, add processes, and accumulate memory before the next attempt. A pod-level average smooths away exactly the moment an operator needed to see.
This is a granularity mismatch. The accountable unit is not the long-lived agent container but the individual effect it asks the machine to perform. The schedulable unit of agent work is the effect because each shell command, browser session, or code execution carries a different resource profile and blast radius. Tool-call-scoped child cgroups give those effects boundaries: CPU, memory, process count, I/O, and wall-clock duration can be attributed and constrained without killing the parent conversation.
It is also a responsiveness mismatch. Kubernetes requests, limits, and vertical recommendations move too slowly for a compile burst that starts and ends in seconds. Historical allocation is weak when agent behavior changes with model output and tool results. A useful sandbox therefore combines hard ceilings with live pressure signals. Memory pressure, throttling, queue delay, and process growth should be observed at short intervals, then attached to the tool trajectory that caused them.
The response should be graduated rather than binary. Soft throttling can slow a noisy effect; freezing preserves state while pressure clears; cancellation can return a typed resource error to the agent; atomic termination is the final containment step. Killing and restarting the whole sandbox imposes three costs — lost work, cold-start latency, and repeated setup — and can trigger a restart storm. Sizing the sandbox to the blast radius remains necessary, but size alone is not an operating policy.
I would expose resource outcomes to the harness as structured feedback: the declared intent, observed peak, throttling applied, termination reason, and retry eligibility. That makes limits part of planning instead of an invisible infrastructure surprise. It also supports fleet fairness. Rate limits are fairness policy; resource bursts need the same tenant-aware treatment so one agent’s generated build cannot consume everyone else’s latency budget.
There is one precise concession: stable, single-tenant batch jobs with known code and generous deadlines can often be governed by coarse job-level quotas. The burst model matters most for multi-tenant, interactive agent fleets where generated code is unknown until execution and noisy-neighbour damage appears faster than a conventional autoscaler can react.
Sandboxing is usually discussed as isolation — files, credentials, syscalls, and network egress. Those boundaries prevent unauthorized effects, but they do not allocate authorized resource use well. A sandbox that contains a process yet lets it monopolize memory is secure in one dimension and unreliable in another. Meter the peaks, bind them to the effect, and make degradation explicit; averages can remain useful for capacity planning, but they should never be mistaken for runtime control.