Skip to content

adobe/aio-lib-sandbox-python

App Builder Sandbox SDK (Python)

PyPI Downloads/week Python CI License Codecov Coverage Status

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.

Pre-requisites

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.

Install

pip install --pre aio-lib-sandbox

Quickstart

Inside 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()}

Configuration

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",
)

Usage

Create 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"},
)

Get Status

sandbox = await Sandbox.get(sandbox.id)
print("status:", sandbox.status)

Exec

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 /workspace directory by default, this is not configurable

Detached Commands

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.

File Management

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)

Exec a File

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)

Write to Stdin

Command start

result = await sandbox.exec(
    "python process_csv.py",
    stdin="col1,col2\nval1,val2\n",
    timeout=10_000,
)
print("stdout:", result.stdout.strip())

Running command

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())

Destroy

await sandbox.destroy()

Preview URLs

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.net

Network Policies

Sandboxes 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/**"},
                    ],
                },
            ]
        }
    },
)

Development

Install development dependencies:

pip install -e ".[dev]"

To run the same checks used by CI:

hatch run test

Linting is powered by Ruff:

hatch run lint
hatch run lint-fix

About

Python SDK for Adobe App Builder Sandboxes.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages