← Sandbox SDK / sandbox
Мост песочницы
Мост песочницы представляет собой эталонную реализацию Worker Cloudflare, которая предоставляет Sandbox SDK как HTTP API. Любой HTTP-клиент (Python-скрипт, сервис на Node.js, CI-пайплайн) может создавать sandbox и управлять ими без написания Worker. Вы развёртываете Worker в ваш аккаунт. Это не общий API, размещённый на стороне Cloudflare.
Зачем использовать мост
Sandbox SDK предназначен для использования внутри Cloudflare Workers. Если ваше приложение работает вне экосистемы Workers, оно не может напрямую взаимодействовать с песочницами.
Мост предоставляет Sandbox SDK в виде стандартного HTTP API, поэтому вы можете создавать песочницы и управлять ими на любом языке и любой платформе.
Ключ Методы Sandbox SDK сопоставляются с отдельными HTTP-эндпоинтами. Мост добавляет аутентификацию, проверку входных данных, ограничение пути рабочей области и опциональный тёплый пул для мгновенного запуска контейнера.
Развернуть
Разверните bridge Worker в своём аккаунте Cloudflare:
Кнопка разворачивает Worker и создаёт SANDBOX_API_KEY секрет для аутентификации. После завершения развертывания запишите URL Worker и API-ключ: они используются во всех примерах на этой странице.
Ручное развёртывание
Если вы предпочитаете разворачивать поэтапно, создайте структуру проекта и разверните его вручную.
Предварительные требования:
- A Аккаунт Cloudflare ↗ с включённым Containers / Sandbox beta.
- Node.js ↗ и npm.
- Docker ↗ локальный запуск:
wrangler deployсобирает образ контейнера из bridgeDockerfile.
Шаги:
-
Создайте каркас проекта моста:
npm create cloudflare -- sandbox-bridge --template=cloudflare/sandbox-sdk/bridge/worker cd sandbox-bridge -
Аутентификация в Cloudflare:
npx wrangler login -
Задайте секрет с API-ключом. Выберите любое надёжное значение токена: клиенты должны передавать его в виде Bearer-токена:
openssl rand -hex 32 | tee /dev/stderr | npx wrangler secret put SANDBOX_API_KEYКлюч выводится в ваш терминал и передаётся через конвейер в Wrangler. Сохраните его: он понадобится для аутентификации запросов к API.
-
Разверните Worker:
npx wrangler deploy -
Проверьте развёртывание:
curl https://cloudflare-sandbox-bridge.<your-subdomain>.workers.dev/healthВы должны увидеть
{"ok":true}.
Образ контейнера
Мост Dockerfile расширяет cloudflare/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 пакет. Чтобы получить последние улучшения:
-
Обновите зависимость SDK:
npm update @cloudflare/sandbox -
Разверните заново:
npx wrangler deploy
Проверьте релизы sandbox-sdk ↗ при изменениях в Dockerfile или конфигурацию моста, которая может потребовать ручного обновления.
Исходный код и примеры
Исходный код моста и примеры доступны на GitHub:
- Исходный код Bridge ↗ : Worker, Dockerfile, скрипт развёртывания и схема OpenAPI.
- Пример чата рабочей области ↗ : full-stack чат-приложение с боковой панелью файлового браузера.
- Базовый пример ↗ : одноразовый агент для написания кода на Python на базе OpenAI Agents SDK.
Дополнительные материалы
- Справочник по HTTP API : полный справочник по маршрутам bridge API.
- Начало работы : создание первого приложения на основе песочницы прямо в Workers.
- Архитектура : как Sandbox SDK выстраивает слои поверх Workers, Durable Objects и Containers.
- Справочник по API : полный справочник по методам Sandbox SDK.
- руководство OpenAI Agents SDK : создание агента для написания кода на Python с помощью bridge.