storages3volumesai-agentsagent-sandbox

Mount an S3 Bucket in an AI Agent Sandbox

Sandbox0 Team·

Sometimes the right persistent workspace is not a new workspace at all.

Your data may already live in S3.

A data agent might need to read a customer's object prefix, write transformed files back beside the inputs, and leave the bucket as the source of truth. A coding agent might generate build artifacts that another pipeline already consumes from object storage. A workflow agent might need to inspect an existing S3-compatible bucket without first copying the whole prefix into a separate sandbox volume.

For those cases, Sandbox0 now supports an s3 backend for Sandbox Volumes.

It lets a Sandbox mount an existing S3-compatible bucket prefix as a filesystem path. The agent reads and writes files through the mounted path, while the bucket remains the durable source of truth.

That sounds close to Mountpoint for Amazon S3, and the mental model is similar: object keys are projected into a directory-like tree. The important Sandbox0 difference is where that mount lives. The bucket is mounted through Sandbox0's volume portal, so it can be bound to a Sandbox claim the same way other Sandbox Volumes are bound.

When to Use the S3 Backend#

Use the s3 backend when the bucket prefix already matters outside Sandbox0.

Good fits include:

  • a data pipeline where input and output objects stay in S3
  • an agent that needs to inspect customer-owned object storage
  • a workflow where another system watches a bucket prefix
  • a migration task that should write directly back to object storage
  • a self-hosted deployment that uses S3-compatible storage such as AWS S3, Aliyun OSS, or Cloudflare R2

This is different from the default s0fs backend.

s0fs is Sandbox0-managed persistent filesystem state. It is the right backend for agent workspaces that need direct file APIs without a running sandbox, snapshots, restore, forks, and small-file write-heavy behavior.

The s3 backend is for an existing object prefix. The bucket owns the namespace. Sandbox0 projects that namespace into a Sandbox mount.

Create an S3 Backend Volume#

An S3 backend Volume is created with backend: "s3" and an s3 config block.

The bucket must already exist. The access key and secret key are per-Volume credentials for that bucket or prefix. Sandbox0 stores those credentials as encrypted encrypted_pg payloads and does not return them in API responses.

bash
curl -sS -X POST "$SANDBOX0_API_URL/api/v1/sandboxvolumes" \ -H "Authorization: Bearer $SANDBOX0_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "backend": "s3", "access_mode": "RWO", "s3": { "provider": "aws", "bucket": "agent-data", "prefix": "teams/acme/run-42", "region": "us-east-1", "access_key": "'"$AWS_ACCESS_KEY_ID"'", "secret_key": "'"$AWS_SECRET_ACCESS_KEY"'" } }'

For AWS, provide region or an S3-compatible endpoint_url. For Aliyun OSS and Cloudflare R2, set provider to ali or r2 and provide endpoint_url.

If you use temporary credentials, include session_token in the s3 object.

Mount the Bucket into a Sandbox#

Sandbox0 mounts Volumes through template-declared mount points. The operator-managed default template declares /workspace, so the simplest claim binds the new S3 backend Volume there.

bash
curl -sS -X POST "$SANDBOX0_API_URL/api/v1/sandboxes" \ -H "Authorization: Bearer $SANDBOX0_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "template": "default", "mounts": [ { "sandboxvolume_id": "'"$S3_VOLUME_ID"'", "mount_point": "/workspace" } ] }'

After the claim completes, the agent can use /workspace like a mounted filesystem path:

bash
cat /workspace/input/events.jsonl mkdir -p /workspace/results printf '%s\n' '{"status":"done"}' > /workspace/results/summary.json sync

The written file is uploaded to the configured S3 prefix when the file handle is closed or flushed.

What the Agent Sees#

Inside the Sandbox, object keys are projected as paths.

If the bucket contains:

text
teams/acme/run-42/input/events.jsonl teams/acme/run-42/input/users.jsonl teams/acme/run-42/results/

and the Volume prefix is teams/acme/run-42, the Sandbox sees:

text
/workspace/input/events.jsonl /workspace/input/users.jsonl /workspace/results/

Common prefixes appear as directories. Zero-byte marker objects ending in / are treated as directory markers. External object changes become visible through the mounted path on later lookup, read, or list operations.

That last point is the reason to use this backend. The bucket stays live. The agent and external systems can coordinate through object storage instead of copying data in and out of a separate workspace.

What This Is Not#

The S3 backend is not a full POSIX filesystem and is not a replacement for s0fs.

It follows mount-s3-like object semantics:

  • writable opens replace the target object
  • writes must be sequential
  • append writes are not supported
  • random in-place overwrites are not supported
  • rename is not supported for general-purpose buckets
  • hard links, symlinks, xattrs, locks, fallocate, and copy_file_range are not supported

Sandbox0 also rejects RWX mounts for S3 backend Volumes. Use RWO for a writable sandbox mount or ROX for a read-only mount.

Snapshots, restore, and Volume fork are s0fs backend features. They are not available for s3 backend Volumes because the external bucket prefix remains the source of truth.

S3 Backend vs S0FS#

The choice is about ownership.

QuestionUse s3 backendUse s0fs backend
Where is the source of truth?Existing bucket prefixSandbox0-managed Volume
Does another system already read/write the data?YesUsually no
Should external object changes appear in the Sandbox?YesNo
Need snapshots, restore, or fork?NoYes
Need direct Volume file API without an active mount?NoYes
Need small-file workspace behavior for source trees and package caches?Usually noYes

If the agent is working on a repository, installing dependencies, running tests, and taking snapshots before risky edits, use s0fs.

If the agent is processing objects that already belong in a bucket, use s3.

Credential Boundary#

The sandbox process does not need to receive the bucket access key and secret key as environment variables.

The credentials are submitted when the Volume is created. Sandbox0 stores them encrypted so ctld can mount the bucket prefix later. API responses omit access_key, secret_key, and session_token.

This keeps the object store credentials on the platform side of the mount boundary. The agent sees files under /workspace. It does not need to know the bucket endpoint, bucket name, or object prefix unless your application chooses to tell it.

You should still scope the credentials narrowly. For production use, prefer credentials limited to the bucket and prefix the agent actually needs.

A Practical Pattern#

A common pattern is:

  1. Create an S3 backend Volume for a bucket prefix owned by the workflow.
  2. Claim a Sandbox with that Volume mounted at /workspace.
  3. Let the agent read inputs and write outputs through normal filesystem paths.
  4. Let downstream systems consume the resulting S3 objects directly.

That keeps the agent interface simple while preserving the bucket as the integration point.

The point is not to pretend S3 is a perfect local filesystem. It is to make the common object-storage workflow natural inside an isolated agent runtime.

Next Steps#

Read the Volume Backends documentation for the compatibility matrix and SDK examples, then see Volume Mounts for the claim-time mount model.