This document provides reference implementations for managing storage for Agent Sandboxes tailored to your agents' data lifecycle needs.
Depending on your agents' data lifecycle needs, choose one of the following configurations:
- Configure a stateful workspace
- Configure a point-in-time restore and ownership transfer
- Configure an ephemeral workspace
For more information about choosing a storage solution, see Choose storage for AI agentic workloads.
The following document uses the dynamic-rwo StorageClass for automated disk type
selection
to provision disks compatible with machine types of nodes where Agent Sandbox
Pods are scheduled. To help ensure that GKE provisions
Hyperdisk Balanced volumes for your agents' storage, you must
schedule your Agent Sandboxes on the nodes of compatible machine
families, such
as N4; otherwise, GKE falls back to pd-balanced.
This document implements the Private Isolated Workspace data access mode by using
ReadWriteOnce (RWO) access. In this mode, an agent starts up with a private
isolated storage directory it has sole read and write access to.
Unless otherwise specified, the reference implementations in this document use direct sandbox creation, which is applicable to agents that tolerate multi-second startup latency. To achieve sub-second startup latency for stateful or point-in-time restore workspaces, you must use GKE Agent Sandbox Warm Pools. Binding storage to a claimed Warm Pool Pod requires custom scripting and a privileged DaemonSet. For a reference implementation, see this GitHub example.
Alternative access modes
To support alternative access modes, you can modify the volume and snapshot definitions in the configurations:
- Collaborative workspace: change the
accessModestoReadWriteManyand use an RWX-capable StorageClass, such as Filestore Multishares (Enterprise) (enterprise-multishare-rwx). - Exploration branching workspace: mount the
template folder as read-only and providing a separate writable scratchpad.
For the base template, you must use storage supporting multiple read-only
attachments, such as Hyperdisk ML with
ReadOnlyMany(ROX) access mode or Filestore Multishares with RWX access mode.
Before you begin
Enable Agent Sandbox in your cluster.
Configure a stateful workspace
Use this pattern to preserve the latest state of an agent's files. It is useful when your agent must preserve the state when the agent session is paused or terminated (Agent Sandbox is deleted) and restore the data from the latest state when the agent session is activated (Agent Sandbox is re-created).
The reference implementation in this section uses direct sandbox creation and is applicable to agents that tolerate multi-second startup latency.
This approach uses standard GKE PersistentVolumeClaim (PVC) resources to link a sandbox to a pre-existing PVC containing a user's data.
The stateful workspace pattern follows this sequence of events:
- Provisioning: the administrator or orchestrator manually provisions a
private PVC for each agent session using a deterministic identifier (for example,
pvc-agent-1). - Referencing: in the Sandbox resource, you use the
persistentVolumeClaimfield within thevolumesblock to specify the exactclaimNameof the existing volume. - Latency: when the sandbox is created, GKE must dynamically attach the Compute Engine disk to the node VM, which incurs a standard multi-second delay.
- Persistence: on session termination (deleting the Sandbox), GKE detaches the disk but does not destroy the PVC, which helps to ensure that the latest state is preserved for the next session.
To configure a stateful workspace that preserves data between sessions, complete the steps in the following subsections.
Provision a persistent workspace (PVC)
Create a private PersistentVolumeClaim (PVC) that uses a deterministic identifier,
such as pvc-agent-1.
Save the following manifest as
pvc-agent-1.yaml:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-agent-1 # Derived directly from the deterministic assignment ID namespace: default spec: accessModes: - ReadWriteOnce storageClassName: dynamic-rwo # Selects disk type compatible with the node machine family resources: requests: storage: 10GiApply the manifest:
kubectl apply -f pvc-agent-1.yaml
Because the storage class uses dynamic volume binding, the disk is not
attached to any node yet. It remains in a Pending state until a Pod requesting it is
scheduled.
Deploy the Agent Sandbox
Deploy the Sandbox custom resource, referencing the deterministic PVC.
Save the following manifest as
sandbox-agent-1.yaml:apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: sandbox-agent-1 # Traceable sandbox name namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor # Required automountServiceAccountToken: false # Required securityContext: runAsNonRoot: true # Required runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor # Required tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" # Required containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: workspace-disk mountPath: /workspace # Mounts the private disk into the container resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumes: - name: workspace-disk persistentVolumeClaim: claimName: pvc-agent-1 # Binds this specific Sandbox to Agent 1's PVC restartPolicy: OnFailureApply the manifest:
kubectl apply -f sandbox-agent-1.yaml
GKE verifies node capacity and attaches the disk, which takes a few seconds. The container initializes inside a userspace gVisor kernel.
Write data from the agent
Simulate an active AI agent executing file modifications inside its workspace by writing a text file to the mounted disk.
# Set the active Pod name
POD_NAME=sandbox-agent-1
# Write a state file to the persistent directory
kubectl exec $POD_NAME -- sh -c "echo 'Workspace State Saved - Agent 1' > /workspace/modified_data.txt"
# Confirm the file exists on the disk
kubectl exec $POD_NAME -- cat /workspace/modified_data.txt
End the agent session
To simulate scaling down or terminating the session when the agent goes idle, delete the Sandbox resource but preserve the underlying storage.
kubectl delete sandbox sandbox-agent-1
GKE unmounts and detaches the disk. The pvc-agent-1 PVC
remains, preserving the data.
Reactivate the agent session
To reactivate the session, redeploy a fresh Sandbox resource that references the same PVC.
kubectl apply -f sandbox-agent-1.yaml
The disk is re-attached (incurring the attachment delay), and the container boots up.
Verify data preservation
Inspect the newly created sandbox container to verify that the previous session data was preserved.
# Set the active Pod name of the new session
NEW_POD_NAME=sandbox-agent-1
# Read the file from the newly booted sandbox
kubectl exec -it $NEW_POD_NAME -- cat /workspace/modified_data.txt
The output should show Workspace State Saved - Agent 1.
Clean up resources
Delete the Agent Sandbox and the associated persistent volume claim:
kubectl delete sandbox sandbox-agent-1
kubectl delete pvc pvc-agent-1
Configure a point-in-time restore and ownership transfer
Use this pattern to clone datasets for running parallel experiments, debugging, or independent work. An agent's workspace is initialized from a historical dataset (or shared state), saving subsequent modifications to a separate, private writable layer without modifying the base template.
The reference implementation in this section uses direct sandbox creation and is applicable to agents that tolerate multi-second startup latency. This approach relies on the orchestrator to dynamically provision new PersistentVolumeClaims (PVCs) from historical VolumeSnapshots before launching a fresh sandbox session.
Create the VolumeSnapshotClass
Create a VolumeSnapshotClass that specifies the CSI driver and deletion policy.
For Hyperdisk, use the pd.csi.storage.gke.io driver.
Save the following manifest as
1-snapshot-class.yaml:apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshotClass metadata: name: standard-rwo-snapshot driver: pd.csi.storage.gke.io deletionPolicy: DeleteApply the manifest:
kubectl apply -f 1-snapshot-class.yaml
Provision the initial workspace
Create a volume where the agent will perform its initial work.
Save the following manifest as
2-source-pvc.yaml:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: agent-source-pvc spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo resources: requests: storage: 10GiApply the manifest:
kubectl apply -f 2-source-pvc.yaml
Generate state data
Deploy a sandbox Pod to write data to the volume.
Save the following manifest as
3-source-sandbox.yaml:apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: agent-session-v1 namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false # Required securityContext: runAsNonRoot: true # Required runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor # Required tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" # Required containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: workspace mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumes: - name: workspace persistentVolumeClaim: claimName: agent-source-pvc restartPolicy: OnFailureApply the manifest:
kubectl apply -f 3-source-sandbox.yamlWait for the Pod to be running, then write a state file:
POD_NAME=agent-session-v1 kubectl exec $POD_NAME -- sh -c "echo 'Point-in-Time Snapshot - v1' > /workspace/state.txt"
Archive the historical state (CSI VolumeSnapshot)
Trigger a CSI VolumeSnapshot to freeze the current state. When taking a snapshot, follow the best practices for disk snapshots.
Save the following manifest as
4-volume-snapshot.yaml:apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshot metadata: name: agent-session-v1-snapshot spec: volumeSnapshotClassName: standard-rwo-snapshot source: persistentVolumeClaimName: agent-source-pvcApply the manifest:
kubectl apply -f 4-volume-snapshot.yaml
Restore the volume from the snapshot
Deploy a new PVC with its dataSource pointing to the CSI VolumeSnapshot.
Save the following manifest as
5-restored-pvc.yaml:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: agent-restored-pvc spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo dataSource: name: agent-session-v1-snapshot kind: VolumeSnapshot apiGroup: snapshot.storage.k8s.io resources: requests: storage: 10GiApply the manifest:
kubectl apply -f 5-restored-pvc.yaml
Launch the restored Agent Sandbox session
Provision a fresh Sandbox resource that references the newly restored PVC.
Save the following manifest as
6-restored-sandbox.yaml:apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: agent-session-v2-restored namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false # Required securityContext: runAsNonRoot: true # Required runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor # Required tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" # Required containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: workspace mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumes: - name: workspace persistentVolumeClaim: claimName: agent-restored-pvc restartPolicy: OnFailureApply the manifest:
kubectl apply -f 6-restored-sandbox.yaml
Verify persistence and restoration
Verify that the agent can read the historical data.
NEW_POD_NAME=agent-session-v2-restored
kubectl exec $NEW_POD_NAME -- cat /workspace/state.txt
Expected Output: Point-in-Time Snapshot - v1
Clean up resources
Delete the Agent Sandboxes, PVCs, and the VolumeSnapshot:
kubectl delete sandbox agent-session-v1
kubectl delete sandbox agent-session-v2-restored
kubectl delete pvc agent-source-pvc
kubectl delete pvc agent-restored-pvc
kubectl delete volumesnapshot agent-session-v1-snapshot
kubectl delete volumesnapshotclass standard-rwo-snapshot
Configure an ephemeral workspace
Use the ephemeral workspace pattern when an agent needs a storage volume for storing temporary files while the agent is active. No data needs to be preserved on Agent Sandbox deletion.
Configure with sub-second startup
Use Agent Sandbox Warm Pools to pre-provision empty volumes in the background.
Define the SandboxTemplate
Define the ephemeral storage backing within the volumeClaimTemplate block.
Save the following manifest as
stateless-template.yaml:apiVersion: extensions.agents.x-k8s.io/v1alpha1 kind: SandboxTemplate metadata: name: stateless-sandbox-template namespace: default spec: podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: ephemeral-disk mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumeClaimTemplates: - metadata: name: ephemeral-disk spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo # Selects disk type compatible with node machine family resources: requests: storage: 10Gi
Launch the Sandbox Warm Pool
Save the following manifest as
stateless-warmpool.yaml:apiVersion: extensions.agents.x-k8s.io/v1alpha1 kind: SandboxWarmPool metadata: name: stateless-warmpool namespace: default spec: replicas: 5 # Keep five standby Pods with pre-attached empty disks sandboxTemplateRef: name: stateless-sandbox-templateApply both manifests:
kubectl apply -f stateless-template.yaml kubectl apply -f stateless-warmpool.yaml
Claim the Sandbox
Define a SandboxClaim that triggers when a user starts a session.
Save the following manifest as
stateless-sandbox-claim.yaml:apiVersion: extensions.agents.x-k8s.io/v1alpha1 kind: SandboxClaim metadata: name: agent-1-claim spec: sandboxTemplateRef: name: stateless-sandbox-templateApply the manifest:
kubectl apply -f stateless-sandbox-claim.yaml
Verify sub-second execution
Capture the Agent Sandbox Pod name and verify that the /workspace directory is
mounted and ready for immediate use:
export POD_NAME=$(kubectl get sandboxclaim agent-1-claim -o jsonpath='{.status.sandbox.name}')
kubectl exec $POD_NAME -- ls -la /workspace
Terminate the agent session
To end the agent session and release the claimed Sandbox, delete the SandboxClaim resource:
kubectl delete sandboxclaim agent-1-claim
Clean up resources
Delete the Sandbox Warm Pool and the Sandbox template:
kubectl delete sandboxwarmpool stateless-warmpool
kubectl delete sandboxtemplate stateless-sandbox-template
Configure with multi-second startup
To implement an ephemeral workspace that tolerates multi-second latency, use direct Agent Sandbox creation without a Warm Pool.
Define a stateless Agent Sandbox
Save the following manifest as
sandbox-direct-stateless.yaml:apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: sandbox-direct-stateless namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: ephemeral-disk mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required restartPolicy: OnFailure volumeClaimTemplates: - metadata: name: ephemeral-disk spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo resources: requests: storage: 10Gi
Deploy the Agent Sandbox
To dynamically provision the disk and attach it to the scheduled node, apply the manifest:
kubectl apply -f sandbox-direct-stateless.yaml
Verify startup latency and execution
Monitor the Pod status to observe the attachment delay before the Pod
transitions to the Running state:
kubectl get pods -w
After the Pod is running, capture the Pod name and verify that the /workspace
directory is available:
POD_NAME=sandbox-direct-stateless
kubectl exec $POD_NAME -- ls -la /workspace
Terminate agent session
Delete the Sandbox resource to automatically terminate the Pod and destroy its ephemeral storage:
kubectl delete sandbox sandbox-direct-stateless
What's next
- Learn more about GKE Agent Sandbox.
- Learn more about isolating AI code execution with Agent Sandbox.
- Learn how to Save and restore Agent Sandbox environments with Pod snapshots.