Sandbox AI agents with Agent Sandbox and Edera

6 min read · Intermediate


Agent Sandbox is a Kubernetes SIG project that provides a Sandbox API for stateful, singleton workloads—the shape AI agents need: a stable identity, persistent storage, and a long-running runtime you can pause and resume.

By default, a Sandbox pod shares the host kernel. An agent that runs untrusted code, executes shell commands, or fetches arbitrary content is one container escape away from the node. Edera changes the runtime underneath: add runtimeClassName: edera and each Sandbox boots inside its own zone—a lightweight virtual machine with a dedicated kernel. Same Agent Sandbox API, same workload, now contained to its own kernel with no shared kernel surface to attack.

This guide installs the Agent Sandbox controller, runs a sandbox on Edera, and verifies the isolation. For the concepts behind isolating AI agents, see AI Agent Sandboxing.

What you’ll learn

  • How Agent Sandbox and Edera fit together
  • How to install the Agent Sandbox controller
  • How to run a sandbox on the Edera runtime
  • How to verify each sandbox has its own kernel
  • How to size zones for agent workloads

Prerequisites

Before you begin, make sure you have:

  • An Edera-enabled Kubernetes cluster. If you don’t have one, follow Installing Edera with AWS EKS or another install guide. Confirm the runtime is registered:

    kubectl get runtimeclass edera
    NAME    HANDLER   AGE
    edera   edera     1h
  • kubectl configured against that cluster.

  • A default StorageClass that supports dynamic provisioning (only needed for the stateful example in Step 3). On EKS, install the AWS EBS CSI driver; the in-tree kubernetes.io/aws-ebs provisioner used by the legacy gp2 class has been removed from Kubernetes and will leave PersistentVolumeClaims Pending.

How it works

Agent Sandbox uses the standard Kubernetes runtimeClassName field—the same mechanism Edera uses for any workload. When the scheduler places a Sandbox pod with runtimeClassName: edera, the Edera runtime boots a new zone with its own guest kernel and runs the sandbox container inside it.

The result is the same isolation model Edera gives any pod (see Deploy your app to Edera), applied to the Agent Sandbox lifecycle: the agent never shares the host kernel, and a container escape only reaches the zone’s kernel, not the node.

Step 1: Install the Agent Sandbox controller

Install the controller and the Sandbox CRD. Pin a release that serves the v1beta1 API (v0.5.0rc1 or newer).

export AGENT_SANDBOX_VERSION="v0.5.0rc1"
kubectl apply -f "https://github.com/kubernetes-sigs/agent-sandbox/releases/download/${AGENT_SANDBOX_VERSION}/manifest.yaml"
kubectl -n agent-sandbox-system rollout status deploy/agent-sandbox-controller

Expected Result: The controller is Running and the CRD is installed.

kubectl get crd sandboxes.agents.x-k8s.io \
  -o jsonpath='{range .spec.versions[*]}{.name}{" served="}{.served}{"\n"}{end}'
v1beta1 served=true
⚠️
Pin to a v1beta1 release. Agent Sandbox v0.4.x releases serve only the older v1alpha1 API, and the project ships no conversion webhook—so the API version you install is the one you must use. Mixing a v1alpha1 controller with v1beta1 manifests fails with no matches for kind "Sandbox" in version "agents.x-k8s.io/v1beta1".

Step 2: Run a sandbox on Edera

The only Edera-specific line is runtimeClassName: edera.

apiVersion: agents.x-k8s.io/v1beta1
kind: Sandbox
metadata:
  name: edera-minimal
spec:
  podTemplate:
    spec:
      runtimeClassName: edera   # Run this sandbox in its own Edera zone
      containers:
        - name: main
          image: public.ecr.aws/docker/library/alpine:3.20
          command: ["sleep", "infinity"]
          resources:
            requests:
              cpu: "250m"
              memory: "256Mi"
            limits:
              memory: "256Mi"

Apply it and wait for it to be ready:

kubectl apply -f https://raw.githubusercontent.com/edera-dev/edera-agent/main/manifests/minimal-sandbox.yaml
kubectl wait --for=condition=Ready sandbox/edera-minimal --timeout=120s

Verify the sandbox has its own kernel

Because each Edera zone runs a dedicated kernel, the kernel reported inside the sandbox differs from the host node’s kernel.

# Host node kernel (the Edera-patched host)
kubectl get node -o jsonpath='{.items[0].status.nodeInfo.kernelVersion}{"\n"}'

# Guest kernel inside the sandbox
kubectl exec edera-minimal -- uname -r

Expected Output: two different kernels. The host carries the -edera suffix; the sandbox runs its own kernel.

6.18.34-edera     # host
6.18.34           # sandbox zone

Process isolation follows from the same fact—the sandbox has its own PID 1 and cannot see host processes:

kubectl exec edera-minimal -- ps -ef

Clean up before moving on:

kubectl delete sandbox edera-minimal

Step 3: Run a stateful agent sandbox

A real agent needs persistent storage and a heavier runtime. This example deploys a VS Code (code-server) devcontainer with a persistent workspace on a PersistentVolume—a realistic stand-in for a coding agent.

kubectl apply -f https://raw.githubusercontent.com/edera-dev/edera-agent/main/manifests/vscode-sandbox.yaml
kubectl get pvc       # the workspace PVC should be Bound
kubectl logs -f sandbox-example

The first start takes several minutes while the devcontainer builds. Once it’s up, verify isolation the same way as Step 2:

kubectl exec sandbox-example -c devcontainer-main -- uname -r
kubectl exec sandbox-example -c devcontainer-main -- df -h /workspaces

Accessing the sandbox

With VM-based runtimes, direct pod port-forward is not compatible. Use the Sandbox Router, a reverse proxy that routes requests to the right sandbox by an X-Sandbox-ID header:

kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/agent-sandbox/v0.5.0rc1/clients/python/agentic-sandbox-client/sandbox-router/sandbox_router.yaml
kubectl port-forward svc/sandbox-router-svc 8080:8080
curl -H "X-Sandbox-ID: sandbox-example" -H "X-Sandbox-Port: 13337" http://localhost:8080

Sizing zones for agent workloads

Each sandbox is a zone—a real VM—so size it like one. Two settings matter most for agent workloads, which tend to be memory- and CPU-hungry during builds and tool execution.

Set a memory limit. Edera maps a container’s memory limit to the zone’s maximum memory. Without a limit, the zone falls back to Edera’s default maximum (1024M) regardless of the pod’s memory request—which OOM-kills heavier agents mid-task. Always set resources.limits.memory to the peak the workload needs.

Set dev.edera/cpu for multi-core agents. Match it to your CPU request so the zone gets the right vCPU count:

metadata:
  annotations:
    dev.edera/cpu: "4"
spec:
  runtimeClassName: edera
  containers:
    - name: main
      resources:
        requests:
          cpu: "4"
        limits:
          memory: "8Gi"   # becomes the zone's max memory
ℹ️
For finer control—dynamic vs. static memory, ballooning targets, and the dev.edera/initial-memory-request annotation—see Memory ballooning with Edera. For CPU tuning, see CPU performance benchmarking.

Troubleshooting

Sandbox pod is OOMKilled during startup

Problem: The agent runs out of memory while building or pulling dependencies. Solution: Set resources.limits.memory. Without it, the zone caps at the 1024M default. See Sizing zones for agent workloads.

PersistentVolumeClaim stays Pending

Problem: No CSI driver is provisioning the volume. Solution: Install a working CSI driver and default StorageClass. On EKS, install the AWS EBS CSI driver—the legacy in-tree provisioner has been removed from Kubernetes.

no matches for kind "Sandbox" in version "agents.x-k8s.io/v1beta1"

Problem: An older Agent Sandbox controller (v1alpha1) is installed. Solution: Reinstall a v0.5.0rc1+ release (Step 1).

kubectl exec fails with execvpe failed

Problem: The workload’s image has no shell yet (for example, while a devcontainer is still building). Solution: Wait for the build to finish, or test isolation with the minimal sandbox from Step 2.

Next steps

Summary

Key Points:

  • Agent Sandbox runs on Edera by setting one field: runtimeClassName: edera.
  • Each sandbox boots into its own zone with a dedicated kernel—verified by comparing uname -r inside the sandbox against the host node.
  • Size zones for agent workloads: always set a memory limit, and set dev.edera/cpu for multi-core agents.
  • Ready-to-apply manifests live in edera-dev/edera-agent.
Last updated on