Python SDK for Adobe Runtime Sandboxes.
A sandbox is an ephemeral, isolated compute environment. You create one, run commands and read/write files inside it over a WebSocket session, then destroy it.
Warning
Alpha. This SDK is in active alpha development. The API surface and authentication model may change without notice. Pin exact versions; install only with --pre.
To use this library, you must have Sandboxes enabled for your Runtime namespace. Please contact Michael Goberling (mgoberling@adobe.com) or Cosmin Stanciu (stanciu@adobe.com) to request this.
pip install --pre aio-lib-sandboxInside a Runtime action, no configuration is needed to use the SDK as credentials are read automatically from the environment.
from aio_lib_sandbox import Sandbox
async def main(params):
sandbox = await Sandbox.create(name="my-sandbox")
result = await sandbox.exec("python --version", timeout=10_000)
await sandbox.destroy()
return {"stdout": result.stdout.strip()}When running inside a Runtime action, the SDK reads credentials from the environment automatically:
| Variable | Description |
|---|---|
__OW_API_HOST |
Runtime API host |
__OW_NAMESPACE |
Runtime namespace |
__OW_API_KEY |
Runtime API key (basic auth) |
You can override any of these by passing them explicitly to Sandbox.create() or Sandbox.get():
sandbox = await Sandbox.create(
api_host="https://adobeioruntime.net",
namespace="my-namespace",
auth="my-api-key",
name="my-sandbox",
)from aio_lib_sandbox import Sandbox
sandbox = await Sandbox.create(
name="my-sandbox",
type="cpu:default",
max_lifetime=3600,
ports=[3000, 8080],
envs={"API_KEY": "your-api-key"},
)sandbox = await Sandbox.get(sandbox.id)
print("status:", sandbox.status)result = await sandbox.exec("ls -al", timeout=10_000)
print("stdout:", result.stdout.strip())
print("exit code:", result.exit_code)Note: Commands run in the
/workspacedirectory by default, this is not configurable
Pass detached=True to run a long-lived background process.
# Start a background server
handle = await sandbox.exec("python server.py", detached=True)
# Wait for it to exit (e.g. after you stop it)
result = await handle.wait()
print("exit code:", result.exit_code)
# Send a signal to stop it
await handle.kill()If the process is still running and you need a handle to it from a different context, use get_command() to re-attach by exec_id:
handle = await sandbox.get_command(exec_id, on_output=lambda data, stream: print(data, end=""))
await handle.wait()Note: Only 5 background processes are allowed to run at once currently.
script = "console.log('hello from sandbox script', process.version)\n"
await sandbox.write_file("hello.js", script)
content = await sandbox.read_file("hello.js")
print("read_file content:", content.strip())
entries = await sandbox.list_files(".")
print("list_files entries:", entries)result = await sandbox.exec("node hello.js", timeout=10_000)
print("stdout:", result.stdout.strip())
print("stderr:", result.stderr.strip())
print("exit code:", result.exit_code)result = await sandbox.exec(
"python process_csv.py",
stdin="col1,col2\nval1,val2\n",
timeout=10_000,
)
print("stdout:", result.stdout.strip())task = sandbox.exec("cat -n", timeout=10_000)
await sandbox.write_stdin(task.exec_id, "line 1\n")
await sandbox.write_stdin(task.exec_id, "line 2\n")
await sandbox.close_stdin(task.exec_id)
result = await task
print("stdout:", result.stdout.strip())await sandbox.destroy()Ports that should be publicly accessible must be declared at creation time via the ports list.
sandbox = await Sandbox.create(
name="web-sandbox",
ports=[3000, 8080],
)
# Start a server inside the sandbox on the declared port
await sandbox.exec("python -m http.server 3000 &", timeout=5_000)
# Retrieve the pre-provisioned preview URL — synchronous, no network call
url = sandbox.get_url(3000)
print("preview:", url)
# https://sb-abc123-va6-0-xK3mPq2nAeB-3000.sandbox-adobeioruntime.netSandboxes are default-deny. All outbound traffic is blocked unless explicitly allowed.
Pass a policy.network.egress array at creation time to allowlist outbound endpoints, paths, or HTTP verbs.
sandbox = await Sandbox.create(
name="policy-sandbox",
max_lifetime=300,
policy={
"network": {
"egress": [
{"host": "httpbin.org", "port": 443},
{
"host": "api.github.com",
"port": 443,
"rules": [
{"methods": ["GET"], "pathPattern": "/repos/**"},
],
},
]
}
},
)Install development dependencies:
pip install -e ".[dev]"To run the same checks used by CI:
hatch run testLinting is powered by Ruff:
hatch run lint
hatch run lint-fix