Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

Sandbox ブリッジ

最終更新 Markdown で表示Agent セットアップ

sandbox ブリッジは、Sandbox SDK を HTTP API として公開する、リファレンス実装の Cloudflare Worker です。任意の HTTP クライアント(Python スクリプト、Node.js サービス、CI パイプライン)が、Worker を書かずにサンドボックスを作成・制御できます。Worker は 自分の アカウントにデプロイします。Cloudflare がホストする共有 API ではありません。

ブリッジを使う理由

Sandbox SDK は Cloudflare Workers 内での利用を想定しています。アプリケーションが Workers エコシステムの外で動く場合、サンドボックスと直接やり取りできません。

ブリッジは Sandbox SDK を標準 HTTP API として公開するので、任意の言語やプラットフォームからサンドボックスを作成・制御できます。

主要な Sandbox SDK のメソッド は、個別の HTTP エンドポイントに対応します。ブリッジは認証、入力検証、ワークスペースパスの封じ込め、即時コンテナ起動向けの任意の ウォームプール を追加します。

デプロイ

ブリッジ Worker を自分の Cloudflare アカウントにデプロイします。

Deploy to Cloudflare

ボタンは Worker をデプロイし、認証用の SANDBOX_API_KEY シークレットを生成します。デプロイが終わったら、Worker の URL と API キーを控えます。このページの例では、それらを使います。

手動デプロイ

手順を追ってデプロイしたい場合は、プロジェクトを足場から作り、手動でデプロイします。

前提条件:

手順:

  1. ブリッジプロジェクトを足場から作ります。

    npm create cloudflare -- sandbox-bridge --template=cloudflare/sandbox-sdk/bridge/worker
    cd sandbox-bridge
  2. Cloudflare に認証します。

    npx wrangler login
  3. API キーのシークレットを設定します。強いトークン値を選びます。クライアントはこの値を Bearer トークンとして送る必要があります。

    openssl rand -hex 32 | tee /dev/stderr | npx wrangler secret put SANDBOX_API_KEY

    キーはターミナルに表示され、Wrangler にパイプされます。保存してください。API リクエストの認証に使います。

  4. Worker をデプロイします。

    npx wrangler deploy
  5. デプロイを確認します。

    curl https://cloudflare-sandbox-bridge.<your-subdomain>.workers.dev/health

    {"ok":true} が表示されます。

コンテナイメージ

ブリッジの Dockerfilecloudflare/sandbox ベースイメージを拡張し、よく使うエージェント向けツールを事前インストールします。

  • 言語: Python 3.13、Node.js、Bun
  • ツール: git、ripgrep、curl、wget、jq、tar、sed、gawk、procps

ワークロードに必要な言語、システムパッケージ、ツールを追加するには、Dockerfile をカスタマイズします。

使い方

すべての例では、次の環境変数が設定済みだとします。

export SANDBOX_API_URL=https://cloudflare-sandbox-bridge.<your-subdomain>.workers.dev
export SANDBOX_API_KEY=<your-token>

サンドボックスを作成してコマンドを実行する

# Create a sandbox
SANDBOX_ID=$(curl -s -X POST "$SANDBOX_API_URL/v1/sandbox" \
  -H "Authorization: Bearer $SANDBOX_API_KEY" | jq -r '.id')

echo "Sandbox ID: $SANDBOX_ID"

# Run a command
curl -s -X POST "$SANDBOX_API_URL/v1/sandbox/$SANDBOX_ID/exec" \
  -H "Authorization: Bearer $SANDBOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"argv": ["sh", "-lc", "echo hello from the sandbox"], "timeout_ms": 10000}'

# Destroy the sandbox when done
curl -s -X DELETE "$SANDBOX_API_URL/v1/sandbox/$SANDBOX_ID" \
  -H "Authorization: Bearer $SANDBOX_API_KEY"
const API_URL = process.env.SANDBOX_API_URL;
const API_KEY = process.env.SANDBOX_API_KEY;

const headers = {
  Authorization: `Bearer ${API_KEY}`,
  "Content-Type": "application/json",
};

// Create a sandbox
const { id } = await fetch(`${API_URL}/v1/sandbox`, {
  method: "POST",
  headers,
}).then((r) => r.json());

console.log(`Sandbox ID: ${id}`);

// Run a command
// Response is a text/event-stream with the following SSE events:
//   event: stdout  — data is a base64-encoded output chunk
//   event: stderr  — data is a base64-encoded error chunk
//   event: exit    — data is JSON: {"exit_code": 0}
//   event: error   — data is JSON: {"error": "...", "code": "..."}
const execRes = await fetch(`${API_URL}/v1/sandbox/${id}/exec`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    argv: ["sh", "-lc", "echo hello from the sandbox"],
    timeout_ms: 10000,
  }),
});

console.log(await execRes.text());

// Destroy the sandbox when done
await fetch(`${API_URL}/v1/sandbox/${id}`, {
  method: "DELETE",
  headers,
});
# /// script
# dependencies = ["httpx"]
# ///
import os
import httpx

API_URL = os.environ["SANDBOX_API_URL"]
API_KEY = os.environ["SANDBOX_API_KEY"]

headers = {"Authorization": f"Bearer {API_KEY}"}

# Create a sandbox
resp = httpx.post(f"{API_URL}/v1/sandbox", headers=headers)
sandbox_id = resp.json()["id"]
print(f"Sandbox ID: {sandbox_id}")

# Run a command
# Response is a text/event-stream with the following SSE events:
#   event: stdout  — data is a base64-encoded output chunk
#   event: stderr  — data is a base64-encoded error chunk
#   event: exit    — data is JSON: {"exit_code": 0}
#   event: error   — data is JSON: {"error": "...", "code": "..."}
exec_resp = httpx.post(
    f"{API_URL}/v1/sandbox/{sandbox_id}/exec",
    headers=headers,
    json={
        "argv": ["sh", "-lc", "echo hello from the sandbox"],
        "timeout_ms": 10000,
    },
)
print(exec_resp.text)

# Destroy the sandbox when done
httpx.delete(f"{API_URL}/v1/sandbox/{sandbox_id}", headers=headers)

ファイルの書き込みと読み取り

# Write a file
curl -s -X PUT "$SANDBOX_API_URL/v1/sandbox/$SANDBOX_ID/file/workspace/hello.py" \
  -H "Authorization: Bearer $SANDBOX_API_KEY" \
  --data-binary 'print("hello world")'

# Read a file
curl -s "$SANDBOX_API_URL/v1/sandbox/$SANDBOX_ID/file/workspace/hello.py" \
  -H "Authorization: Bearer $SANDBOX_API_KEY"
// Write a file
await fetch(`${API_URL}/v1/sandbox/${id}/file/workspace/hello.py`, {
  method: "PUT",
  headers,
  body: 'print("hello world")',
});

// Read a file
const content = await fetch(
  `${API_URL}/v1/sandbox/${id}/file/workspace/hello.py`,
  { headers },
).then((r) => r.text());

console.log(content);
# /// script
# dependencies = ["httpx"]
# ///
import os
import httpx

API_URL = os.environ["SANDBOX_API_URL"]
API_KEY = os.environ["SANDBOX_API_KEY"]
SANDBOX_ID = os.environ["SANDBOX_ID"]  # from the "Create a sandbox" step
headers = {"Authorization": f"Bearer {API_KEY}"}

# Write a file
httpx.put(
    f"{API_URL}/v1/sandbox/{SANDBOX_ID}/file/workspace/hello.py",
    headers=headers,
    content=b'print("hello world")',
)

# Read a file
content = httpx.get(
    f"{API_URL}/v1/sandbox/{SANDBOX_ID}/file/workspace/hello.py",
    headers=headers,
).text
print(content)

ブリッジを最新に保つ

ブリッジのロジックの大半は @cloudflare/sandbox パッケージにあります。最新の改善を取り込むには、次の手順を行います。

  1. SDK の依存関係を更新します。

    npm update @cloudflare/sandbox
  2. 再デプロイします。

    npx wrangler deploy

Dockerfile やブリッジ設定の変更で手動更新が必要な場合があるので、sandbox-sdk のリリース を確認してください。

ソースコードと例

ブリッジのソースコードと例は GitHub にあります。

関連リソース

役に立ちましたか?