$npx -y skills add digitalocean-labs/do-app-platform-skills --skill sandboxCreate and manage isolated container sandboxes for AI agent code execution. Use when you need ephemeral environments to run untrusted code, execute agent workflows, or test in isolation. NOT for debugging existing apps (use troubleshooting skill).
| 1 | # Sandbox Skill |
| 2 | |
| 3 | Isolated execution environments for AI agents and testing workflows. |
| 4 | |
| 5 | ## Philosophy |
| 6 | |
| 7 | ``` |
| 8 | Lambda/Functions: Fast cold start, 15-min limit, stateless, per-ms billing |
| 9 | App Platform Sandbox: 30s cold start (or instant with pool), unlimited duration, stateful, per-hour billing |
| 10 | |
| 11 | Sweet spot: Long-running, stateful, iterative workflows where agents need to |
| 12 | install packages, run code, check results, modify, repeat. |
| 13 | ``` |
| 14 | |
| 15 | ## Quick Decision |
| 16 | |
| 17 | ``` |
| 18 | ┌─────────────────────────────────────────────────────────────┐ |
| 19 | │ Need isolated execution environment? │ |
| 20 | └─────────────────────────────────────────────────────────────┘ |
| 21 | │ |
| 22 | Is this for debugging an EXISTING app? |
| 23 | │ |
| 24 | ┌───────────────┴───────────────┐ |
| 25 | │ │ |
| 26 | YES NO |
| 27 | │ │ |
| 28 | ▼ ▼ |
| 29 | ┌─────────────────┐ ┌─────────────────┐ |
| 30 | │ troubleshooting │ │ Need real-time │ |
| 31 | │ skill │ │ streaming or │ |
| 32 | │ │ │ port exposure? │ |
| 33 | │ Sandbox.get_ │ │ │ |
| 34 | │ from_id() │ └────────┬────────┘ |
| 35 | └─────────────────┘ │ |
| 36 | ┌───────────────┴───────────────┐ |
| 37 | │ │ |
| 38 | YES NO |
| 39 | │ │ |
| 40 | ▼ ▼ |
| 41 | ┌─────────────────┐ ┌─────────────────┐ |
| 42 | │ SERVICE MODE │ │ Is low latency │ |
| 43 | │ exec_stream() │ │ critical? │ |
| 44 | │ expose_port() │ │ │ |
| 45 | └─────────────────┘ └────────┬────────┘ |
| 46 | │ |
| 47 | ┌───────────────┴───────────────┐ |
| 48 | │ │ |
| 49 | YES NO |
| 50 | │ │ |
| 51 | ▼ ▼ |
| 52 | ┌─────────────────┐ ┌─────────────────┐ |
| 53 | │ HOT POOL │ │ COLD SANDBOX │ |
| 54 | │ SandboxManager │ │ Sandbox.create()│ |
| 55 | │ ~50ms acquire │ │ ~30s startup │ |
| 56 | └─────────────────┘ └─────────────────┘ |
| 57 | ``` |
| 58 | |
| 59 | --- |
| 60 | |
| 61 | ## Prerequisites |
| 62 | |
| 63 | ```bash |
| 64 | # Verify doctl is installed and authenticated |
| 65 | doctl auth whoami |
| 66 | |
| 67 | # Install the SDK (choose one) |
| 68 | uv pip install do-app-sandbox |
| 69 | # OR |
| 70 | pip install do-app-sandbox |
| 71 | |
| 72 | # For Spaces support (large file transfers) |
| 73 | pip install "do-app-sandbox[spaces]" |
| 74 | ``` |
| 75 | |
| 76 | **Requirements:** |
| 77 | - Python 3.10.12+ |
| 78 | - `doctl` CLI installed and authenticated |
| 79 | - DigitalOcean account with App Platform access |
| 80 | |
| 81 | --- |
| 82 | |
| 83 | ## Quick Start: Cold Sandbox |
| 84 | |
| 85 | Single sandbox creation with ~30s startup time: |
| 86 | |
| 87 | ```python |
| 88 | from do_app_sandbox import Sandbox |
| 89 | |
| 90 | # Create sandbox with Python image |
| 91 | sandbox = Sandbox.create( |
| 92 | image="python", # or "node" |
| 93 | name="my-sandbox", |
| 94 | region="nyc", |
| 95 | instance_size="apps-s-1vcpu-1gb" |
| 96 | ) |
| 97 | |
| 98 | # Execute code |
| 99 | result = sandbox.exec("python3 -c 'import sys; print(sys.version)'") |
| 100 | print(result.stdout) |
| 101 | |
| 102 | # File operations |
| 103 | sandbox.filesystem.write_file("/tmp/script.py", "print('hello')") |
| 104 | result = sandbox.exec("python3 /tmp/script.py") |
| 105 | |
| 106 | # Clean up |
| 107 | sandbox.delete() |
| 108 | ``` |
| 109 | |
| 110 | **Full guide**: See [cold-sandbox.md](reference/cold-sandbox.md) |
| 111 | |
| 112 | --- |
| 113 | |
| 114 | ## Quick Start: Hot Pool |
| 115 | |
| 116 | Pre-warmed sandboxes for instant acquisition: |
| 117 | |
| 118 | ```python |
| 119 | import asyncio |
| 120 | from do_app_sandbox import SandboxManager, PoolConfig |
| 121 | |
| 122 | async def main(): |
| 123 | # 1. Configure pool |
| 124 | manager = SandboxManager( |
| 125 | pools={"python": PoolConfig(target_ready=3)}, |
| 126 | ) |
| 127 | |
| 128 | # 2. Start and warm up (blocks until pool is ready) |
| 129 | await manager.start() |
| 130 | await manager.warm_up(timeout=180) |
| 131 | |
| 132 | # 3. Acquire instantly (~500ms from pool vs 30s cold start) |
| 133 | sandbox = await manager.acquire(image="python") |
| 134 | result = sandbox.exec("python3 -c 'print(2+2)'") |
| 135 | print(result.stdout) |
| 136 | |
| 137 | # 4. Delete when done - YOUR responsibility! |
| 138 | sandbox.delete() |
| 139 | |
| 140 | # 5. Shutdown (cleans up pool, not acquire |