Agent Sandbox
OpenClaw on Kata Containers (AKS)
Overview
This example runs OpenClaw — a headless agent gateway with a web Control UI — inside an Agent Sandbox that is isolated by Kata Containers on Azure Kubernetes Service (AKS).
It is the hardware-virtualized counterpart to the gVisor-isolated OpenClaw example: where that one uses a syscall-interception sandbox and the template/warm-pool/claim pattern, this one uses a single Sandbox running in its own lightweight VM with a dedicated guest kernel, via the AKS Pod Sandboxing feature.
Isolating an agent runtime this way is useful when the agent executes untrusted, model-generated code: the blast radius of a container escape is the pod VM, not the node kernel.
Prerequisites
- An AKS cluster with a Pod Sandboxing (Kata) node pool, and the
kata-vm-isolationRuntimeClass available. The kata-aks-sandbox example provides asetup.shthat creates one; see also the AKS Pod Sandboxing documentation. - The Agent Sandbox controller installed on the cluster (Installation Guide).
- A default StorageClass for the workspace
PersistentVolumeClaim(AKS provides one).
Step 1: Deploy the Sandbox
kubectl apply -f openclaw-config.yaml
kubectl apply -f openclaw-sandbox-kata-aks.yaml
Wait for it to become ready:
kubectl wait --for=condition=Ready sandbox/openclaw-kata-aks-sandbox --timeout=5m
kubectl get pod openclaw-kata-aks-sandbox
The gateway takes a few seconds after the pod is Running before it starts listening; there is no readiness probe gating it.
Step 2: Reach the Control UI
kubectl port-forward openclaw-kata-aks-sandbox 18789:18789
Then open http://localhost:18789/#token=dummy-token-for-sandbox. The token fragment is required — the gateway rejects a bare load. The token is set by OPENCLAW_GATEWAY_TOKEN in the manifest; change it for anything beyond a local demo.
Step 3: Add a provider API key (optional)
The sandbox starts with --allow-unconfigured, so the gateway runs without any model provider. To let the agent actually answer, create the Secret:
kubectl create secret generic openclaw-provider-keys \
--from-literal=ANTHROPIC_API_KEY="sk-ant-..."
Then uncomment the ANTHROPIC_API_KEY block in openclaw-sandbox-kata-aks.yaml and re-apply it. Run an agent turn from inside the sandbox:
kubectl exec openclaw-kata-aks-sandbox -- \
openclaw agent --local --session-id demo -m "Say hi in three words"
Running the turn in-guest keeps it on the gateway’s loopback interface, which avoids the device-pairing flow a remote client would need.
Step 4: Verify the isolation
# Kernel inside the sandbox (the Kata pod VM's guest kernel)
kubectl exec openclaw-kata-aks-sandbox -- uname -r
# Kernel on the node hosting the sandbox
SANDBOX_NODE="$(kubectl get pod openclaw-kata-aks-sandbox -o jsonpath='{.spec.nodeName}')"
kubectl get node "${SANDBOX_NODE}" -o jsonpath='{.status.nodeInfo.kernelVersion}'
The two differ: the agent runtime is running in its own VM, not sharing the host kernel.
Notes on sizing
The pod VM is sized from the container’s resource limits. The Node.js gateway needs considerably more memory than the default pod VM size, and an embedded agent turn (--local) needs more still — with too little guest memory the gateway is OOM-killed inside the VM. The manifest requests 2Gi / limits 4Gi, which leaves room for both. See the AKS Pod Sandboxing resource management notes for how pod VM sizing and RuntimeClass overhead interact.
Cleanup
kubectl delete -f openclaw-sandbox-kata-aks.yaml
kubectl delete -f openclaw-config.yaml
kubectl delete secret openclaw-provider-keys --ignore-not-found
Deleting the Sandbox does not delete the workspace PersistentVolumeClaim; remove it explicitly if you no longer need the agent’s state.