Skip to main content
Attach a volume to a sandbox to access persistent storage. The volume mounts instantly with lazy loading - no download required at startup.

Basic Usage

from moru import Sandbox, Volume

# Create or get volume
vol = Volume.create(name="my-workspace")

# Create sandbox with volume attached
sbx = Sandbox.create(
    template="base",
    volume_id=vol.volume_id,
    volume_mount_path="/workspace"
)

# Files in /workspace persist to the volume
sbx.commands.run("echo 'Hello' > /workspace/hello.txt")

Mount Path Requirements

The mount path must:
  • Be an absolute path (start with /)
  • Start with one of these prefixes:
    • /workspace/
    • /data/
    • /mnt/
    • /volumes/
# Valid mount paths
Sandbox.create(volume_mount_path="/workspace/data")
Sandbox.create(volume_mount_path="/data/input")
Sandbox.create(volume_mount_path="/mnt/storage")
Sandbox.create(volume_mount_path="/volumes/my-vol")

# Invalid mount paths (will raise error)
Sandbox.create(volume_mount_path="/etc/data")      # Invalid prefix
Sandbox.create(volume_mount_path="workspace/data") # Not absolute
Sandbox.create(volume_mount_path="/workspace/../etc") # No traversal

Data Persistence

Data written to the volume mount path persists across sandbox restarts:
from moru import Sandbox, Volume

vol = Volume.create(name="persistent-data")

# First sandbox - write data
sbx1 = Sandbox.create(
    volume_id=vol.volume_id,
    volume_mount_path="/workspace"
)
sbx1.commands.run("git clone https://github.com/user/repo /workspace")
sbx1.kill()

# Second sandbox - data is still there
sbx2 = Sandbox.create(
    volume_id=vol.volume_id,
    volume_mount_path="/workspace"
)
result = sbx2.commands.run("ls /workspace")
print(result.stdout)  # Shows cloned repo files

Crash Safety

Writes to the volume are crash-safe. If a sandbox crashes or is killed, completed writes are preserved:
from moru import Sandbox, Volume

vol = Volume.create(name="safe-data")
sbx = Sandbox.create(
    volume_id=vol.volume_id,
    volume_mount_path="/data"
)

# Write some data
sbx.commands.run("dd if=/dev/urandom of=/data/file.bin bs=1M count=100")

# Even if sandbox crashes, the file is safe
sbx.kill()

# Verify via API
files = vol.list_files("/")
# file.bin is there with full content

Volume with Other Options

Combine volume attachment with other sandbox options:
from moru import Sandbox, Volume

vol = Volume.create(name="agent-workspace")

sbx = Sandbox.create(
    template="python",
    timeout=3600,  # 1 hour
    volume_id=vol.volume_id,
    volume_mount_path="/workspace",
    envs={
        "WORKSPACE": "/workspace",
        "OPENAI_API_KEY": "sk-..."
    },
    metadata={
        "agent_id": "agent-123",
        "session": "abc"
    }
)

Error Handling

from moru import Sandbox, Volume
from moru.exceptions import NotFoundException, SandboxException

try:
    sbx = Sandbox.create(
        volume_id="vol_nonexistent",
        volume_mount_path="/workspace"
    )
except NotFoundException:
    print("Volume not found")
except ValueError as e:
    print(f"Invalid mount path: {e}")

Limitations

  • One volume per sandbox - Currently only one volume can be attached at a time
  • Mount path is fixed - Cannot change mount path after sandbox creation
  • No concurrent writes - Avoid multiple sandboxes writing to the same files simultaneously

Next Steps