All Products
Search
Document Center

Function Compute:Use OpenClaw Sandbox

Last Updated:Sep 18, 2026

OpenClaw is an open-source agent framework that supports CLI-based programmatic invocation and a Gateway Web UI. This article focuses on real-world task scenarios: deploying Gateway, Agent CLI, custom-domain browser access, security mode and operations, and Skill extension. For image addresses, building a Template, and environment and capability notes, see OpenClaw Template.

Prerequisites

  • Completed SDK integration (E2B API Key, api_url, and domain)

  • Built a Template in the ready state as described in OpenClaw Template, and recorded the template name (referred to as TEMPLATE_NAME below) and the OPTS in the build example

  • Prepared a model API Key, which is injected through envs when you create a sandbox. The image does not include pre-configured keys

Deploy Gateway

Start the OpenClaw Gateway and interact with the Agent in a browser. The complete workflow is: Create a Sandbox → Configure → Start the Gateway → Get the access URL. For server-side programmatic invocation, see Agent CLI.

import time

from e2b_code_interpreter import Sandbox

# Gateway authentication token: set any string you want. You do not need to obtain it from an API.
# Pass it to openclaw gateway --token on startup, and pass it as the ?token= URL parameter for browser access.
# The official OpenClaw documentation also supports the OPENCLAW_APP_TOKEN environment variable, which works the same way.
TOKEN = "my-gateway-token"
PORT = 18789

BAILIAN_API_KEY = "<YOUR-BAILIAN-API-KEY>"
BAILIAN_BASE_URL = "[workspace-id].[region].maas.aliyuncs.com"
BAILIAN_MODEL = "qwen3.8-max"

# 1. Create a Sandbox
sandbox = Sandbox.create(
    template=TEMPLATE_NAME,
    timeout=3600,
    envs={
        "ANTHROPIC_AUTH_TOKEN": BAILIAN_API_KEY,
        "ANTHROPIC_BASE_URL": BAILIAN_BASE_URL,
        "ANTHROPIC_MODEL": BAILIAN_MODEL,
    },
    **OPTS,
)

# Register the Model Studio provider
sandbox.commands.run(
    "openclaw onboard --non-interactive --accept-risk --skip-health "
    "--auth-choice custom-api-key "
    f"--custom-api-key {BAILIAN_API_KEY} "
    f"--custom-base-url {BAILIAN_BASE_URL} "
    "--custom-compatibility anthropic "
    f"--custom-model-id {BAILIAN_MODEL} "
    "--custom-provider-id bailian",
    timeout=120,
)

# 2. Set the default model
sandbox.commands.run(
    f"openclaw config set agents.defaults.model.primary bailian/{BAILIAN_MODEL}"
)

# 3. Configure the Control UI (required for public network access to the sandbox)
origin = f"https://{sandbox.get_host(PORT)}"
sandbox.commands.run(
    f"openclaw config set gateway.controlUi.allowedOrigins '[\"{origin}\"]'"
)

# 4. Start the Gateway (in the background)
sandbox.commands.run(
    f"bash -lc 'openclaw config set gateway.controlUi.allowInsecureAuth true && "
    f"openclaw config set gateway.controlUi.dangerouslyDisableDeviceAuth true && "
    f"openclaw gateway --allow-unconfigured --bind lan --auth token "
    f"--token {TOKEN} --port {PORT}'",
    background=True,
)

# 5. Wait until the Gateway is ready
for _ in range(45):
    probe = sandbox.commands.run(
        f'bash -lc \'ss -ltn | grep -q ":{PORT} " && echo ready || echo waiting\''
    )
    if probe.stdout.strip() == "ready":
        break
    time.sleep(1)

url = f"https://{sandbox.get_host(PORT)}/?token={TOKEN}"
print(f"Gateway: {url}")

Agent CLI

Invoke the Agent programmatically on the server side without starting the Gateway.

If you have already created a Sandbox as described in Deploy Gateway, run the following commands on the same sandbox. You do not need to create another one.

If you only need the CLI without starting the Gateway:

from e2b_code_interpreter import Sandbox

BAILIAN_API_KEY = "<YOUR-BAILIAN-API-KEY>"
BAILIAN_BASE_URL = "[workspace-id].[region].maas.aliyuncs.com"
BAILIAN_MODEL = "qwen3.8-max"

sandbox = Sandbox.create(
    template=TEMPLATE_NAME,
    timeout=3600,
    envs={
        "ANTHROPIC_AUTH_TOKEN": BAILIAN_API_KEY,
        "ANTHROPIC_BASE_URL": BAILIAN_BASE_URL,
        "ANTHROPIC_MODEL": BAILIAN_MODEL,
    },
    **OPTS,
)

# Register the Model Studio provider
sandbox.commands.run(
    "openclaw onboard --non-interactive --accept-risk --skip-health "
    "--auth-choice custom-api-key "
    f"--custom-api-key {BAILIAN_API_KEY} "
    f"--custom-base-url {BAILIAN_BASE_URL} "
    "--custom-compatibility anthropic "
    f"--custom-model-id {BAILIAN_MODEL} "
    "--custom-provider-id bailian",
    timeout=120,
)

result = sandbox.commands.run(
    f'openclaw agent --local --agent main --model bailian/{BAILIAN_MODEL} '
    '-m "What is 2+2? Reply with just the number."',
    timeout=120,
)
print(result.stdout)

Browser access (FC Agent Sandbox)

To open the Gateway Control UI of FC Agent Sandbox in a browser, you must bind a custom domain first. The default platform domain (*.sandbox.aliyuncs.com) triggers a download instead of opening the page. After you bind a custom domain, the page loads normally. For the complete steps on adding a domain in the console, DNS resolution, HTTPS certificates, and SDK configuration, see Cloud Sandbox Custom Domains.

Configure a custom domain

Step 1: Configure the domain in the console. In the Function Compute console, bind a custom domain for FC Agent Sandbox, and configure the certificate and DNS records (api.<YOUR-CUSTOM-DOMAIN> / *.<YOUR-CUSTOM-DOMAIN>).

Step 2: Update OPTS in the SDK. The default OPTS in OpenClaw Template:

OPTS = {
    "api_key": "<YOUR-E2B-API-KEY>",
    "api_url": "https://api.cn-beijing.sandbox.aliyuncs.com",
    "domain": "cn-beijing.sandbox.aliyuncs.com",
}

Replace the values with the custom domain that matches the console configuration (the api_key must belong to the same account that bound the custom domain):

OPTS = {
    "api_key": "<YOUR-E2B-API-KEY>",
    "api_url": "https://api.<YOUR-CUSTOM-DOMAIN>",
    "domain": "<YOUR-CUSTOM-DOMAIN>",
}

Step 3: Pass OPTS throughout the workflow. Template.build(..., **OPTS), Sandbox.create(..., **OPTS), and all other SDK calls in this topic use the preceding OPTS. No additional parameters are needed.

After the configuration takes effect, sandbox.get_host(PORT) returns {PORT}-sbx-{sandbox_id}.<YOUR-CUSTOM-DOMAIN>. Use this host for the Gateway allowedOrigins, the browser address bar, and the <host> in the curl command below.

Open the Control UI

After you configure the custom domain and deploy the Gateway, public network access also requires authentication:

Authentication

Source

Purpose

How to Pass

Gateway Token

The TOKEN that you set in the code

OpenClaw Control UI

?token= URL parameter

  1. Run the preceding script and record the Gateway URL in the output

  2. Open the Gateway URL (the URL already contains ?token=)

Verify the result with curl first:

curl -sI "https://<host>/?token=<Gateway Token>"

The expected response contains 200. If the Content-Type response header is text/html, the Gateway works as expected.

If "browser origin not allowed" is displayed, make sure that allowedOrigins exactly matches the origin in the address bar (https://{sandbox.get_host(PORT)}, without a trailing /), and restart the Gateway after the change.

Security mode

During testing, you can disable device pairing (the preceding example already sets dangerouslyDisableDeviceAuth true). If security mode is enabled, approve the pending device after you open the URL:

import json

for _ in range(30):
    try:
        res = sandbox.commands.run(
            f"openclaw devices list --json --url ws://127.0.0.1:{PORT} --token {TOKEN}"
        )
        data = json.loads(res.stdout)
        if data.get("pending"):
            rid = data["pending"][0]["requestId"]
            sandbox.commands.run(
                f"openclaw devices approve {rid} --token {TOKEN} "
                f"--url ws://127.0.0.1:{PORT}"
            )
            print(f"Device approved: {rid}")
            break
    except Exception:
        pass
    time.sleep(2)

Restart Gateway

After you change the model or configuration, run the following in the current Sandbox:

origin = f"https://{sandbox.get_host(PORT)}"
sandbox.commands.run(
    f"openclaw config set gateway.controlUi.allowedOrigins '[\"{origin}\"]'"
)

sandbox.commands.run(
    """bash -lc 'for p in "[o]penclaw gateway" "[o]penclaw-gateway"; do
for pid in $(pgrep -f "$p" || true); do kill "$pid" 2>/dev/null || true; done
done'"""
)
time.sleep(1)

sandbox.commands.run(
    f"openclaw gateway --allow-unconfigured --bind lan --auth token "
    f"--token {TOKEN} --port {PORT}",
    background=True,
)

for _ in range(45):
    probe = sandbox.commands.run(
        f'bash -lc \'ss -ltn | grep -q ":{PORT} " && echo ready || echo waiting\''
    )
    if probe.stdout.strip() == "ready":
        break
    time.sleep(1)

Disable insecure settings

sandbox.commands.run(
    "bash -lc 'openclaw config set gateway.controlUi.allowInsecureAuth false && "
    "openclaw config set gateway.controlUi.dangerouslyDisableDeviceAuth false'"
)

sandbox.commands.run(
    """bash -lc 'for p in "[o]penclaw gateway" "[o]penclaw-gateway"; do
for pid in $(pgrep -f "$p" || true); do kill "$pid" 2>/dev/null || true; done
done'"""
)

sandbox.commands.run(
    f"openclaw gateway --allow-unconfigured --bind lan --auth token "
    f"--token {TOKEN} --port {PORT}",
    background=True,
)

Extend capabilities with Skills

OpenClaw extends Agent capabilities through Skills (a directory plus SKILL.md). Both the Gateway and the Agent CLI can use Skills. For more information, see OpenClaw Skills.

The following examples assume that you have created a sandbox as described above (by using the Gateway or the Agent CLI). The image does not preload custom Skills. You can run openclaw skills list to view the loaded Skills (including bundled ones). For path conventions, see OpenClaw Template.

The following example uses Model Studio (BAILIAN_MODEL is defined above).

Write a Managed Skill:

sandbox.files.write(
    "/home/user/.openclaw/skills/summarize-changes/SKILL.md",
    """---
name: summarize-changes
description: Summarizes uncommitted changes and flags risks. Use when reviewing diffs or writing commit messages.
user-invocable: true
---

## Instructions
1. Run `git diff HEAD` and summarize changes in 2–3 bullets.
2. List risks such as missing error handling or hardcoded values.
3. If the diff is empty, say there are no uncommitted changes.
""",
)

# Verify that the skill is in the list
print(sandbox.commands.run("openclaw skills list").stdout)

result = sandbox.commands.run(
    f'openclaw agent --local --agent main --model bailian/{BAILIAN_MODEL} '
    '--message "/summarize-changes"',
    timeout=0,
)
print(result.stdout)

Write a Workspace Skill:

sandbox.files.write(
    "/home/user/.openclaw/workspace/skills/api-conventions/SKILL.md",
    """---
name: api-conventions
description: API design conventions. Use when adding or changing HTTP endpoints or /healthz.
user-invocable: true
---

When writing API endpoints:
- Use RESTful naming
- Return consistent error formats
- Include request validation
""",
)

result = sandbox.commands.run(
    f'openclaw agent --local --agent main --model bailian/{BAILIAN_MODEL} '
    '--message "/api-conventions Add a /healthz endpoint"',
    timeout=0,
)
print(result.stdout)

Upload a multi-file Skill directory from your local machine:

If a Skill contains additional files such as scripts/ and references/, use files.write_files to write them in a single batch:

from pathlib import Path

def upload_skill_dir(sandbox, local_dir: str, remote_root: str) -> None:
    local = Path(local_dir).resolve()
    entries = []
    for path in local.rglob("*"):
        if path.is_file():
            rel = path.relative_to(local).as_posix()
            entries.append({
                "path": f"{remote_root.rstrip('/')}/{rel}",
                "data": path.read_bytes(),
            })
    sandbox.files.write_files(entries)

# Example local directory structure:
# ./my-skills/echo-marker/SKILL.md
# ./my-skills/echo-marker/scripts/marker.txt
upload_skill_dir(
    sandbox,
    "./my-skills/echo-marker",
    "/home/user/.openclaw/skills/echo-marker",  # Managed. For a Workspace Skill, use workspace/skills/...
)

print(sandbox.commands.run("openclaw skills list").stdout)

result = sandbox.commands.run(
    f'openclaw agent --local --agent main --model bailian/{BAILIAN_MODEL} '
    '--message "/echo-marker"',
    timeout=0,
)
print(result.stdout)
About Template.copy: presetting files with .copy("local-dir", "/home/user/.openclaw/skills/...") during Template.build is not supported. To add custom Skills, use the runtime files.write / files.write_files methods described above.

Install from ClawHub (optional):

Sandboxes have outbound Internet access by default, so you can search for and install community Skills directly (browse clawhub.ai):

# Search
result = sandbox.commands.run("openclaw skills search calendar", timeout=120)
print(result.stdout)

# Install
sandbox.commands.run("openclaw skills install ws-calendar", timeout=180)

Parameters

Step

Description

--bind lan

The Gateway listens on 0.0.0.0 so that E2B can proxy the port

--auth token

Authenticate with the ?token= URL parameter

Open the URL in a browser

The Gateway provides the UI, and the browser establishes a WebSocket connection

code=1008 pairing required

In security mode, approve the device first

devices approve

Approve the browser device fingerprint

Reconnect the browser

The WebSocket connection succeeds, and the UI is available

Cleanup

Release resources when the task is complete:

sandbox.kill()

Billing

A Sandbox is billed based on its CPU and memory specifications and running duration. Fees for model API calls are billed separately by the model service. For more information, see Billing Overview.

FAQ

Issue

Solution

The agent does not respond

Verify that envs contains the model Key. In the China-site Model Studio scenario, verify that onboard is complete

The Gateway cannot be opened in a browser

Verify that the Gateway URL contains ?token= (the value is the Gateway Token set in the script)

The browser downloads a file instead of opening the page

Bind a custom domain. For more information, see Cloud Sandbox Custom Domains and Browser access (FC Agent Sandbox)

sandbox account mismatch

The API Key and Cloud Sandbox Custom Domains must belong to the same account

Origin not allowed

allowedOrigins exactly matches the origin in the address bar (without a trailing /). Restart the Gateway

Template build fails

Verify that FROM_IMAGE matches the region. Do not use the openclaw-v* prefix for name. For more information, see OpenClaw Template

Other SDK or build issues

See Template management

References