Skip to content

Agent Sandbox on EKS — Isolated, Stateful Runtimes for AI Agents ​

Supported Versions: Agent Sandbox v1.0.6 (API v1beta1), Python SDK k8s-agent-sandbox 1.0.6, Karpenter v1.13.0+ for cpuOptions.nestedVirtualizationLast Updated: October 13, 2026

Agent Sandbox (kubernetes-sigs/agent-sandbox) is a Kubernetes SIG Apps subproject that adds a Sandbox custom resource and controller for isolated, stateful, singleton workloads. A Sandbox is one Pod with a stable identity, optional persistent storage and lifecycle controls (expiry, suspend and resume) that Deployments and StatefulSets do not model directly. The typical consumers are AI agents that execute LLM-generated code, reinforcement learning (RL) rollouts, notebooks and per-user development environments.

This chapter explains the API as it exists at tag v1.0.6 and what changes when you run it on Amazon EKS: runtime isolation options, how the default NetworkPolicy behaves under the Amazon VPC CNI, private exposure of the router, and IAM.

Facts in this chapter come from the upstream source at tag v1.0.6 (CRD types, controllers, release notes, threat model), AWS documentation and the Karpenter source. The manifests were not run on an EKS cluster for this chapter; treat them as starting points and test them on your own node and network configuration.


1. Why a New Workload API ​

NeedDeploymentStatefulSet (replicas: 1) + Service + PVCSandbox
Exactly one Pod with a stable nameNo (random suffix)Yes (name-0)Yes (Pod name = Sandbox name)
Per-instance storage that survives Pod restartsNoYesYes (volumeClaimTemplates)
Stop compute but keep the object and volumesScale to 0 (all replicas)Scale to 0operatingMode: Suspended
Absolute expiry timeNoNoshutdownTime + shutdownPolicy
Pre-warmed instances handed out on demandNoNoSandboxWarmPool + SandboxClaim
Secure defaults for untrusted codeNoNoSandboxTemplate (no SA token, managed NetworkPolicy)

An agent platform usually needs thousands of these short-lived or idle-most-of-the-time environments, each owned by one session or user. Modelling each as a StatefulSet of size 1 plus a Service and PVC works but leaves expiry, warm pools, claim latency and isolation defaults to custom code.

Project status (October 13, 2026) ​

ItemValue
Repository createdAugust 12, 2025
v1.0.0August 28, 2026: v1alpha1 and the conversion webhook removed; all CRDs serve only v1beta1
Latest releasev1.0.6 (October 8, 2026); patch releases have shipped weekly since v1.0.0
API groupsagents.x-k8s.io/v1beta1 (core), extensions.agents.x-k8s.io/v1beta1 (extensions)
Controller namespaceagent-sandbox-system
SDKsPython (k8s-agent-sandbox, Python ≥ 3.11), Go (sigs.k8s.io/agent-sandbox/clients/go/sandbox), TypeScript
IsolationDelegated to the Pod's RuntimeClass (for example gVisor or Kata Containers)

The project's version is 1.0, but its API version is still v1beta1. Pin releases and read each release's "Breaking Changes / Action Required" section; several patch releases (v1.0.2, v1.0.5, v1.0.6) contain action items.


2. Architecture ​

KindGroupShort nameRole
Sandboxagents.x-k8s.iosandboxOne Pod with stable identity, optional PVCs and headless Service, lifecycle and suspend
SandboxTemplateextensions.agents.x-k8s.iosandboxtemplateReusable blueprint plus platform policy (NetworkPolicy, env and volume injection rules)
SandboxWarmPoolextensions.agents.x-k8s.ioswpKeeps N unclaimed Sandboxes ready from a template; has a scale subresource for HPA
SandboxClaimextensions.agents.x-k8s.iosandboxclaimA request for a Sandbox from a warm pool; owns the Sandbox after adoption

Supporting components:

  • sandbox-router (optional): a Go HTTP reverse proxy (registry.k8s.io/agent-sandbox/sandbox-router-go) that routes by X-Sandbox-ID headers or, with --path-routing-prefix, by URL path. Since v1.0.2 its manifests live in agent-sandbox-system, and it supports Ed25519 scoped tokens (v2) bound to the Sandbox UID, port, method and path.
  • sandboxd: an in-sandbox runtime daemon (REST filesystem on :8080, gRPC ProcessService on :9090) that the SDKs can use for commands, files and interactive processes.

3. The Core Sandbox Resource ​

yaml
apiVersion: agents.x-k8s.io/v1beta1
kind: Sandbox
metadata:
  name: py-session-42           # also the Pod name; ≤ 63 chars when spec.service is true
  namespace: agents
spec:
  podTemplate:
    metadata:
      labels:
        team.example.com/owner: data-science
    spec:
      runtimeClassName: gvisor   # isolation comes from the runtime, not from Agent Sandbox
      automountServiceAccountToken: false
      containers:
      - name: runtime
        image: <your-registry>/python-runtime:<tag>
        ports:
        - containerPort: 8888
        resources:
          requests: { cpu: 250m, memory: 512Mi }
          limits:   { cpu: "1",  memory: 1Gi }
  volumeClaimTemplates:          # immutable after creation
  - metadata:
      name: workspace
    spec:
      accessModes: [ReadWriteOnce]
      storageClassName: gp3
      resources:
        requests:
          storage: 5Gi
  service: true                  # create a headless Service named after the Sandbox
  operatingMode: Running         # or Suspended
  shutdownTime: "2026-10-14T00:00:00Z"
  shutdownPolicy: Delete         # default Retain

Field behavior in v1beta1:

FieldBehavior
podTemplateRequired. Labels and annotations are propagated to the Pod, except system-reserved keys under agents.x-k8s.io/ and extensions.agents.x-k8s.io/, which the controller filters out.
volumeClaimTemplatesPVCs created per Sandbox. Immutable (CEL rule).
serviceUnset: no new Service is created (existing ones are kept for backward compatibility). true: headless Service named after the Sandbox. false: Service removed.
operatingModeRunning (default) keeps a Pod; Suspended deletes the Pod but keeps the Sandbox object and its PVCs.
shutdownTimeAbsolute expiry. At that time the Pod and Service are deleted.
shutdownPolicyRetain (default) keeps the Sandbox object with Ready=False, reason=SandboxExpired; Delete removes it.

Status conditions follow Gateway API conventions:

ConditionMeaning
ReadyTrue only when the Pod is Running and Ready with an IP (and the Service exists, if required). False reasons include DependenciesNotReady, SandboxSuspended, SandboxExpired, InvalidConfiguration, ReconcilerError.
SuspendedProgress of a suspension: PodTerminating, then PodTerminated; NotSuspended once running again.
PodScheduledMirrors the Pod's PodScheduled condition (for example Unschedulable), so you do not need to read the Pod.
FinishedSet when the Pod reaches Succeeded or Failed.

status also carries serviceFQDN, podIPs and nodeName.

v1.0.6 action item: a CEL rule now rejects a Sandbox whose name exceeds 63 characters while spec.service is true (a Service name is a DNS-1035 label). Existing objects are not exempt, so such a Sandbox fails every update, including status updates, until you unset spec.service or recreate it with a shorter name.


4. Extensions: Template, Warm Pool and Claim ​

SandboxTemplate — where platform policy lives ​

yaml
apiVersion: extensions.agents.x-k8s.io/v1beta1
kind: SandboxTemplate
metadata:
  name: python-gvisor
  namespace: agents
spec:
  podTemplate:
    metadata:
      annotations:
        karpenter.sh/do-not-disrupt: "true"   # optional: keep consolidation away from live sessions
    spec:
      runtimeClassName: gvisor
      containers:
      - name: python-runtime
        image: <your-registry>/python-runtime-sandbox:<tag>
        ports:
        - containerPort: 8888
        readinessProbe:
          httpGet: { path: "/", port: 8888 }
          periodSeconds: 1
        resources:
          requests: { cpu: 250m, memory: 512Mi, ephemeral-storage: 512Mi }
          limits:   { cpu: "1",  memory: 1Gi }
  networkPolicyManagement: Managed      # default
  # networkPolicy: omitted -> controller applies its secure default (section 6)
  envVarsInjectionPolicy: Disallowed    # default; Allowed | Overrides
  volumeClaimTemplatesPolicy: Disallowed  # default; Allowed | Overrides

Secure defaults that apply to Sandboxes created through a template (by a warm pool or claim):

  • If the PodSpec does not set automountServiceAccountToken, the controller sets it to false.
  • With networkPolicyManagement: Managed (the default), the controller creates one shared NetworkPolicy per template. Editing its rules changes enforcement for every existing and future Sandbox from that template.
  • Claims cannot inject environment variables or volume templates unless the template allows it.

A bare Sandbox gets none of these defaults. Use admission control (ValidatingAdmissionPolicy, Kyverno or Gatekeeper) if users may create Sandbox objects directly, or grant them RBAC only for SandboxClaim.

SandboxWarmPool — pre-created capacity ​

yaml
apiVersion: extensions.agents.x-k8s.io/v1beta1
kind: SandboxWarmPool
metadata:
  name: python-gvisor-pool
  namespace: agents
spec:
  replicas: 10                 # default 1; scale subresource, so an HPA can own it
  sandboxTemplateRef:
    name: python-gvisor
  updateStrategy:
    type: OnReplenish          # default; Recreate replaces stale unclaimed Sandboxes at once

When the template's blueprint changes, unclaimed Sandboxes become stale. OnReplenish replaces them only as they are claimed or deleted; Recreate deletes them immediately. Sandboxes already claimed are never touched, because ownership moves to the claim.

SandboxClaim — what an agent session asks for ​

yaml
apiVersion: extensions.agents.x-k8s.io/v1beta1
kind: SandboxClaim
metadata:
  name: session-7f3a
  namespace: agents
spec:
  warmPoolRef:
    name: python-gvisor-pool
  lifecycle:
    shutdownTime: "2026-10-13T12:00:00Z"
    shutdownPolicy: Delete       # Delete | DeleteForeground | Retain (default)
    ttlSecondsAfterFinished: 600
  • The claim adopts a ready Sandbox from the pool. If no warm candidate reports a Pod IP within --sandbox-claim-warm-candidate-grace-period (default 2s, added in v1.0.6), it falls back to creating one cold.
  • Setting spec.env or spec.volumeClaimTemplates always forces a cold start, because those values must exist before the Pod is created.
  • additionalPodMetadata labels must use an allowed domain (default sandbox.users.io, configurable through the agent-sandbox-config ConfigMap).
  • status.sandbox reports the bound Sandbox's name, podIPs and serviceFQDN.

5. Isolation on EKS: Choosing a RuntimeClass ​

Agent Sandbox is an orchestrator. Its threat model says container escape is mitigated by running Pods under a stronger runtime selected by runtimeClassName, preferably set in a SandboxTemplate so users cannot drop it. With the default runc, LLM-generated code shares the node's kernel with every other Pod on the node.

Option on EKSIsolation boundaryNode requirementsNotes
runc (default)Linux namespaces and cgroupsAnyNot sufficient for untrusted code on shared nodes
gVisor (runsc)User-space application kernelInstall runsc and containerd-shim-runsc-v1, register handler runsc in containerdWorks on ordinary virtualized instances; some syscalls and workloads behave differently, so test them
Kata ContainersLightweight VM per PodHardware virtualization: bare-metal (*.metal) instances or instances with nested virtualizationStrongest boundary of these options; higher per-Pod overhead
Dedicated nodes per tenantEC2 instanceTaints, tolerations and node selectorsCan be combined with gVisor or Kata

EKS-specific points:

  • EKS Auto Mode: AWS chooses the AMI and is responsible for the container runtime, and the instances are not accessible over SSH, so you cannot add runsc or Kata there. Use managed node groups, self-managed nodes or Karpenter with a custom AMI or user data for sandbox node pools.
  • gVisor: install the binaries in a custom AMI or at boot, and register the runtime handler. On AL2023, nodeadm's NodeConfig accepts inline TOML in spec.containerd.config. containerd 1.x uses config version 2 (plugins."io.containerd.grpc.v1.cri"), while 2.x uses version 3 (plugins."io.containerd.cri.v1.runtime"), so check containerd --version on your AMI before writing the runtime section.
  • Kata and nested virtualization: EC2 supports nested virtualization (KVM or Hyper-V as L1) on M7i, M7i-flex, M8i, M8id, M8i-flex, C7i, C7i-flex, C8i, C8id, C8i-flex, R7i, R7iz, R8i, R8id, R8i-flex, X8i, I7i and I7ie, enabled with the CPU option NestedVirtualization=enabled. AWS recommends bare metal for performance-sensitive workloads.
    • Karpenter v1.13.0 and later expose spec.cpuOptions.nestedVirtualization: enabled on EC2NodeClass, and filter instance types to those reporting nested-virtualization.
    • For managed node groups, the containers-roadmap request (#2784) was closed as completed on October 12, 2026, after users reported that the launch-template setting is respected. Confirm it on a test node (grep -cE 'vmx|svm' /proc/cpuinfo) before relying on it.
  • Fargate runs each Pod in its own VM, but the VPC CNI cannot apply network policies to Fargate Pods, so the template's managed NetworkPolicy would not be enforced there. Check the Fargate considerations before you choose it.

Bind the RuntimeClass to the prepared nodes so a sandbox Pod can never land on a node without the handler:

yaml
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc
scheduling:
  nodeSelector:
    sandbox.example.com/runtime: gvisor
  tolerations:
  - key: sandbox.example.com/untrusted
    operator: Exists
    effect: NoSchedule
---
# Karpenter: a NodeClass for Kata nodes on nested-virtualization instances
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: kata-nested
spec:
  cpuOptions:
    nestedVirtualization: enabled   # Karpenter >= v1.13.0
  # amiSelectorTerms, role, subnetSelectorTerms, securityGroupSelectorTerms,
  # and user data that installs Kata are omitted here.

6. Networking on EKS ​

What the managed default policy does ​

When a template sets no networkPolicy and keeps Managed mode, the controller generates this policy (from buildDefaultNetworkPolicySpec in v1.0.6):

DirectionRule
IngressOnly from Pods labeled app: sandbox-router in namespace agent-sandbox-system
Egress (IPv4)0.0.0.0/0 except 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16
Egress (IPv6)::/0 except fc00::/7, fe80::/10
DNSNot allowed: CoreDNS has a private IP, and the code comment says this is intentional to prevent internal service discovery

Consequences on EKS:

  1. Enforcement needs a policy engine. Enable network policy in the Amazon VPC CNI add-on (version 1.21.0 or later, enableNetworkPolicy: "true"). On Auto Mode, set enable-network-policy-controller: "true" in the amazon-vpc-cni ConfigMap in kube-system; a NodeClass networkPolicy setting is optional. Without enforcement the NetworkPolicy object exists but blocks nothing.
  2. Public hostnames do not resolve by default. Agents that pip install or call public APIs by name fail until you allow DNS or give the Pod a different resolver.
  3. The private-range list is not your VPC's address plan. Check what the default leaves reachable:
    • VPC CIDRs outside RFC1918 (for example 100.64.0.0/10 secondary CIDRs used for VPC CNI custom networking) are not excluded.
    • In an IPv4 cluster, IMDS (169.254.169.254) and the Route 53 Resolver (169.254.169.253) are blocked, which is intended. The EKS Pod Identity Agent (169.254.170.23) is blocked too, so Pod Identity credentials do not work under the default policy.
    • In an IPv6 cluster, the VPC CNI ignores IPv4 rules and enforces only IPv6 ones. The IPv6 addresses of IMDS, the Resolver and the Pod Identity Agent (fd00:ec2::254, fd00:ec2::253, fd00:ec2::23) fall in fc00::/7 and are blocked. Pod and node addresses, however, are global unicast addresses from the VPC's IPv6 CIDR, which the ::/0 rule allows.
    • Also in an IPv6 cluster, the VPC CNI applies policies only to the Pod's primary interface (eth0). With IPv4 egress enabled (ENABLE_V4_EGRESS=true), IPv4 traffic leaves through an extra interface that no policy filters, including traffic to 169.254.169.254 and RFC1918 addresses. Disable IPv4 egress for sandbox nodes if you do not need it, and keep the IMDS hop limit at 1.
    • VPC interface endpoints have private IPs and are blocked. AWS API calls, if any, leave through NAT to public endpoints.
  4. Direct in-cluster connections are blocked. Ingress allows only the router, so an agent Pod that uses an SDK in-cluster mode (Service DNS or Pod IP) needs an explicit ingress rule for its namespace.

A custom policy for an IPv4 cluster whose VPC uses 10.0.0.0/16 plus a 100.64.0.0/16 pod CIDR might look like this. It allows DNS only to CoreDNS, allows the agent namespace to connect directly, and excludes every VPC range from public egress:

yaml
spec:
  networkPolicyManagement: Managed
  networkPolicy:
    ingress:
    - from:
      - namespaceSelector:
          matchLabels: { kubernetes.io/metadata.name: agent-sandbox-system }
        podSelector:
          matchLabels: { app: sandbox-router }
      - namespaceSelector:
          matchLabels: { kubernetes.io/metadata.name: agent-orchestrator }
      ports:
      - { protocol: TCP, port: 8888 }
    egress:
    - to:
      - namespaceSelector:
          matchLabels: { kubernetes.io/metadata.name: kube-system }
        podSelector:
          matchLabels: { k8s-app: kube-dns }
      ports:
      - { protocol: UDP, port: 53 }
      - { protocol: TCP, port: 53 }
    - to:
      - ipBlock:
          cidr: 0.0.0.0/0
          except: [10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, 100.64.0.0/10]

Allowing CoreDNS lets a sandbox resolve internal Service names. If that matters, keep DNS blocked and give the Pod an explicit resolver (dnsPolicy: None with dnsConfig.nameservers set to a resolver you control that is reachable under the egress rules). For FQDN-level egress allow-lists, use a CNI or proxy that supports them; Kubernetes NetworkPolicy matches only IP blocks and selectors. The VPC CNI counts at most 24 port/protocol combinations per CIDR across all policies.

Exposing the router ​

The upstream SDK examples include a "Gateway mode" that sends traffic through a public cloud load balancer. On EKS, keep the data plane private:

CallerPath
Agents in the same clusterSDK in-cluster mode straight to the Pod (add the ingress rule above), or the sandbox-router-svc ClusterIP Service on port 8080
Developer laptop or CISDK tunnel mode (kubectl port-forward to the router Service)
Browser or external clientsCloudFront → CloudFront VPC origin → internal ALB → router Service. The internal ALB's security group admits only the CloudFront VPC-origin security group or the CloudFront managed prefix list; nothing in the path is internet-facing except CloudFront.

The router's default authorizer is AllowAll. Its threat model notes that, without a configured authorizer, rejecting local and metadata IP literals in X-Sandbox-Pod-IP is the only SSRF defense. Before you expose the router beyond the cluster, enable scoped-token v2 authorization (Ed25519, bound to Sandbox UID, port, method and path; Pod-IP overrides are rejected under v2) and enforce rate and connection limits at the ALB or Envoy tier, which the router itself does not do for WebSockets.


7. IAM and Credentials ​

  • Leave automountServiceAccountToken: false (the template default). An agent that can reach the Kubernetes API with a token can try to escalate.
  • Do not give sandbox Pods AWS credentials by default. In an IPv4 cluster the managed policy already blocks IMDS and the Pod Identity Agent, but that does not hold for IPv4 egress from IPv6 clusters (section 6); keep IMDSv2 required with a hop limit of 1 on sandbox nodes as a second barrier.
  • If a sandbox must call AWS, use a dedicated ServiceAccount with the narrowest role you can, scope it to one namespace, and change the NetworkPolicy deliberately (Pod Identity needs port 80 on 169.254.170.23/32, or fd00:ec2::23/128 in an IPv6 cluster; IRSA needs the regional STS endpoint). Record this as a policy exception.
  • Give end users RBAC only for SandboxClaim in their namespace. Platform teams own SandboxTemplate and SandboxWarmPool.

8. Installing and Upgrading ​

bash
export VERSION=v1.0.6
# Core + extensions (recommended; works with Argo CD / Flux as plain manifests)
kubectl apply -f "https://github.com/kubernetes-sigs/agent-sandbox/releases/download/${VERSION}/sandbox-with-extensions.yaml"

kubectl get crd sandboxes.agents.x-k8s.io \
  sandboxclaims.extensions.agents.x-k8s.io \
  sandboxtemplates.extensions.agents.x-k8s.io \
  sandboxwarmpools.extensions.agents.x-k8s.io
kubectl -n agent-sandbox-system get deploy agent-sandbox-controller

# Optional router: apply the manifests from sandbox-router/deploy/ at the same tag,
# and pin the image to registry.k8s.io/agent-sandbox/sandbox-router-go:${VERSION}
  • Release assets per tag: sandbox.yaml (core), extensions.yaml, sandbox-with-extensions.yaml. Controller and router images are published to registry.k8s.io/agent-sandbox/ with matching v1.0.x tags.
  • A Helm chart exists in the repository (helm/, chart version 0.1.2 at v1.0.6) and is installed from a checkout (helm install agent-sandbox ./helm/). No chart repository is published.
  • From earlier than v0.5.0: direct upgrades to v1.x are not supported. Upgrade to v0.5.2 or later, migrate stored objects to v1beta1, confirm every CRD's status.storedVersions lists only v1beta1, then upgrade. Helm users apply helm/crds/ before helm upgrade.
  • Other action items since v1.0.0:
    • v1.0.0 stopped writing the agents.x-k8s.io/pod-name annotation; use .metadata.name.
    • v1.0.2 moved the router manifests from default to agent-sandbox-system and changed the Go Authorizer interface.
    • v1.0.6 added the 63-character name rule and changed the scoped-token v2 and proxy.Lookup contracts.
  • Uninstall: deleting the CRDs cascade-deletes every Sandbox, claim, template and pool in the cluster. List them first.

9. Using the Python SDK ​

bash
pip install k8s-agent-sandbox==1.0.6
python
from k8s_agent_sandbox import SandboxClient
from k8s_agent_sandbox.models import SandboxLocalTunnelConnectionConfig

# Tunnel mode: port-forward to sandbox-router-svc in agent-sandbox-system
client = SandboxClient(connection_config=SandboxLocalTunnelConnectionConfig())

sandbox = client.create_sandbox(warmpool="python-gvisor-pool", namespace="agents")
try:
    result = sandbox.commands.run("python -c 'print(2 + 2)'")
    print(result.stdout)
finally:
    sandbox.terminate()
  • create_sandbox creates a SandboxClaim against the named warm pool. Passing env= forces a cold start.
  • For retry-safe workflows, pass a stable claim_name with adopt_existing=True; a 409 Conflict then adopts the existing claim. shutdown_after_seconds sets an expiry so a crashed client does not leak sandboxes.
  • Other connection configs: SandboxInClusterConnectionConfig (legacy runtime; Pod IP first, then cluster DNS), SandboxdInClusterConnectionConfig (modes in-cluster-service and in-cluster-pod-ip since v1.0.6), SandboxDirectConnectionConfig (explicit URL, optional mTLS), and AsyncSandboxClient for asyncio.
  • Integrations in the repository include LangChain, OpenAI Agents, Deep Agents, NVIDIA NeMo Gym, Gymnasium and Ray RLlib examples, plus an MCP server.

10. Operating at Scale ​

ConcernWhat to do
Claim latencySize warm pools from demand; watch agent_sandbox_claim_controller_startup_latency_ms by launch_type (warm vs cold). If cold fallbacks spike on clusters with slow IPAM, raise --sandbox-claim-warm-candidate-grace-period.
Pool sizingagent_sandbox_warmpool_size (by pool and readiness) and agent_sandboxes gauges. The pool's scale subresource lets an HPA or KEDA drive replicas.
API server loadBurst refills compete with claims. The project documents APF FlowSchema/PriorityLevelConfiguration manifests and controller flags (--api-connections, --sandbox-warm-pool-replenish-delay, write-behind windows) exposed under controller.* in the Helm chart.
Node consolidationKarpenter may consolidate nodes that hold idle warm Pods or live sessions. Add karpenter.sh/do-not-disrupt: "true" in the template's Pod metadata for session Pods, and use a separate NodePool for sandbox nodes.
Suspend and resumeSuspended deletes the Pod and keeps PVCs. EBS volumes are zonal, so a resumed Pod must schedule in the volume's AZ; keep capacity there or use a storage class that matches your resume pattern.
CleanupAlways set shutdownTime (or shutdown_after_seconds in the SDK) and ttlSecondsAfterFinished on claims; Retain leaves objects behind for inspection.
Resource abuseSet requests and limits in the template, and a LimitRange and ResourceQuota per tenant namespace.

11. When to Use It ​

SituationRecommendation
Self-hosted agent platform on EKS that runs untrusted code per sessionAgent Sandbox with templates, gVisor or Kata nodes, private router
RL or evaluation rollouts needing thousands of short-lived isolated environmentsAgent Sandbox warm pools; follow the project's performance-tuning and APF guides
A few long-lived single-Pod services with stable namesA StatefulSet may be simpler; Agent Sandbox helps once you need expiry or suspend
You do not want to operate runtimes and nodes for code executionConsider a managed code-execution service (for example Amazon Bedrock AgentCore Code Interpreter) and compare its isolation, network and data-residency model with your requirements

Pre-production checklist ​

  • [ ] Release pinned (v1.0.6), and each release's action items reviewed before upgrading
  • [ ] Every template sets runtimeClassName; the RuntimeClass carries scheduling for prepared nodes
  • [ ] Users have RBAC for SandboxClaim only; bare Sandbox creation restricted or validated by admission policy
  • [ ] VPC CNI network policy enforcement enabled and tested with a probe Pod (DNS, IMDS, VPC CIDRs, other sandboxes); in IPv6 clusters, the IPv4 egress path checked too
  • [ ] Egress exceptions cover every VPC CIDR, including non-RFC1918 and IPv6 ranges
  • [ ] Router reachable only privately; scoped-token v2 authorization enabled
  • [ ] shutdownTime or SDK expiry on every claim; quotas per namespace
  • [ ] Controller and warm-pool metrics scraped and alerted

References ​