Справочник по Sandbox API и SDK
С Lizard SDK вы управляете Sandboxes в Lizard (lizard.build) из кода: @lizard-build/sdk в npm для TypeScript и JavaScript и lizard-sdk в PyPI для Python, который импортируется как lizard. Оба клиента вызывают один и тот же HTTP API. На этой странице перечислены все вызовы для sandbox с именами в TypeScript и Python и примерами на обоих языках. Для первого запуска по шагам используйте быстрый старт; что такое Sandboxes, описано в обзоре.
Установка и вход
npm install @lizard-build/sdk
pip install lizard-sdk
export LIZARD_API_KEY="<your-api-key>"Создайте API-ключ в Settings → API keys или командой lizard keys create <name>. SDK читает LIZARD_API_KEY; чтобы использовать другой ключ, передайте apiKey (в Python: api_key). Каждому sandbox нужен проект: передайте projectId (в Python: project_id) или ID, slug либо имя через project.
Параметры создания
| TypeScript | Python |
|---|---|
projectId / project | project_id / project |
timeoutMs | timeout_ms |
region | region |
volumeName / volumeId | volume_name / volume_id |
size | size |
snapshotId | snapshot_id |
envs | envs |
metadata | metadata |
lizardToken | lizard_token |
apiKey | api_key |
import { Sandbox } from '@lizard-build/sdk';
const sandbox = await Sandbox.create('base', {
projectId: 'proj_123',
size: 'small',
timeoutMs: 10 * 60 * 1000,
envs: { MODE: 'test' },
metadata: { task: 'report-42' },
});from lizard import Sandbox
sandbox = Sandbox.create(
"base",
project_id="proj_123",
size="small",
timeout_ms=10 * 60 * 1000,
envs={"MODE": "test"},
metadata={"task": "report-42"},
)- Первым аргументом передайте шаблон из каталога в разделе runtime и шаблоны. Без него SDK запускает
base. sizeпринимает'small','medium'или'large': 2 vCPU / 4 GB, 4 vCPU / 8 GB (по умолчанию) или 8 vCPU / 16 GB; см. размеры и цены. Для sandbox, восстановленного из снимка,sizeне действует: он работает с размером источника.timeoutMsпо умолчанию равен 300000, то есть пяти минутам.0отключает истечение срока. См. ресурсы и сроки жизни.- При необходимости укажите регион явно; наличие региона в каталоге не гарантирует свободные ресурсы. Не задавайте
region, если подключаете том: sandbox запустится там, где находится том. - В
metadataукажите свои метки; их возвращаютgetInfo()иlist(). lizardTokenзаписывает в sandbox API-ключliz_, чтобы внутри работалlizard. Этот ключ может прочитать всё, что работает в sandbox, поэтому передавайте ключ с доступом только к рабочему пространству.
Методы
| TypeScript | Python | Что делает |
|---|---|---|
Sandbox.create(template, options) | Sandbox.create(template, ...) | Создать в проекте из шаблона каталога. |
Sandbox.connect(sandboxId) | Sandbox.connect(sandbox_id) | Подключиться к существующему sandbox без возобновления. |
Sandbox.list({ projectId }) | Sandbox.list(project_id=...) | Получить список доступных Sandboxes; проверяйте их статус. |
sandbox.getInfo() | sandbox.get_info() | Получить статус, runtime и сведения. |
sandbox.process.exec(cmd, opts) | sandbox.process.exec_(cmd, ...) | Выполнить shell-команду или массив argv; вернуть stdout, stderr и код завершения. |
sandbox.process.list() | sandbox.process.list() | Получить список процессов, запущенных через exec. |
sandbox.process.kill(pid, signal) | sandbox.process.kill(pid, signal) | Отправить сигнал процессу и его дочерним процессам; по умолчанию SIGTERM. |
sandbox.fs.write(path, data) | sandbox.fs.write(path, data) | Записать текст или байты; создать родительские папки. |
sandbox.fs.read(path) | sandbox.fs.read(path) | Прочитать текст UTF-8. |
sandbox.fs.readBytes(path) | sandbox.fs.read_bytes(path) | Прочитать байты файла. |
sandbox.fs.list(path) | sandbox.fs.list(path) | Получить список файлов и папок. |
sandbox.fs.stat(path) | sandbox.fs.stat(path) | Вернуть тип, размер, права, владельца и время изменения. |
sandbox.fs.makeDir(path) | sandbox.fs.make_dir(path) | Создать папку и недостающие родительские папки. |
sandbox.fs.move(from, to) | sandbox.fs.move(src, dst) | Переместить файл или папку. |
sandbox.fs.remove(path) | sandbox.fs.remove(path) | Удалить файл или папку. |
sandbox.exposePort(port) | sandbox.expose_port(port) | Опубликовать порт; вернуть url, hostname и токен доступа. |
sandbox.getHost(port) | sandbox.get_host(port) | Опубликовать порт и вернуть его имя хоста; для запросов нужен sandbox.accessToken. |
sandbox.unexpose(port) | sandbox.unexpose(port) | Убрать опубликованный порт. |
sandbox.setTimeout(ms) | sandbox.set_timeout(ms) | Задать оставшийся срок жизни, минимум 1000 мс. |
sandbox.pause() / sandbox.resume() | sandbox.pause() / sandbox.resume() | Поставить паузу или возобновление в очередь и сразу вернуть ответ. |
sandbox.waitForStatus(status) | sandbox.wait_for_status(status) | Дождаться paused или running; выбросить ошибку, если пауза не удалась. |
sandbox.fork({ count }) | sandbox.fork(count=...) | Скопировать работающий sandbox от 1 до 10 раз вместе с памятью и процессами. |
sandbox.snapshot(name, { poolSize }) | sandbox.snapshot(name, pool_size=...) | Сохранить память и файлы /workspace в приватный снимок. |
Sandbox.waitForSnapshot(snapshotId) | Sandbox.wait_for_snapshot(snapshot_id) | Дождаться готовности снимка. |
Sandbox.restore(snapshotId) | Sandbox.restore(snapshot_id) | Запустить новый sandbox из снимка. |
Sandbox.deleteSnapshot(snapshotId) | Sandbox.delete_snapshot(snapshot_id) | Удалить снимок; sandbox, восстановленные из него, продолжают работать. |
sandbox.kill() | sandbox.kill() | Остановить sandbox и отключить том. |
Запуск команд
process.exec (в Python: exec_) запускает команду и ждёт её завершения. Передайте onStdout или onStderr (в Python: on_stdout, on_stderr), чтобы получать вывод, пока команда выполняется; вызов всё равно вернёт полный результат в конце. Передайте массив argv вместо строки, чтобы обойти оболочку: так безопасно передавать недоверенный текст как аргумент.
const result = await sandbox.process.exec('npm test', {
workdir: '/app',
envs: { NODE_ENV: 'test' },
timeoutMs: 120_000,
onStdout: (chunk) => process.stdout.write(chunk),
});
if (result.exitCode !== 0) throw new Error(result.stderr);
await sandbox.process.exec(['grep', '-rn', '--', userQuery, '/workspace']);result = sandbox.process.exec_(
"npm test",
workdir="/app",
envs={"NODE_ENV": "test"},
timeout_ms=120_000,
on_stdout=lambda chunk: print(chunk, end=""),
)
if result.exit_code != 0:
raise RuntimeError(result.stderr)
sandbox.process.exec_(["grep", "-rn", "--", user_query, "/workspace"])Результат команды содержит stdout, stderr и код завершения. Ненулевой код завершения возвращается в результате; проверяйте его сами. Сбои запроса выбрасывают исключение. Таймаут команды составляет от 1 до 600 секунд. process.exec принимает envs, workdir и user; команды выполняются от root, если не передать user. Параметр envs, заданный при создании, доступен каждой команде в sandbox на Firecracker; sandbox в виде pod его игнорирует, поэтому там передавайте переменные в каждой команде.
Файлы
fs.write записывает текст или байты, а fs.read читает текст. Для двоичных файлов записывайте байты и читайте их обратно через fs.readBytes (в Python: read_bytes). Используйте абсолютные пути. Если пути нет, выбрасывается NotFoundError.
await sandbox.fs.write('/app/data.csv', 'x,y\n1,2\n');
const text = await sandbox.fs.read('/app/data.csv');
const entries = await sandbox.fs.list('/app');
const png = await sandbox.fs.readBytes('/app/chart.png');sandbox.fs.write("/app/data.csv", "x,y\n1,2\n")
text = sandbox.fs.read("/app/data.csv")
entries = sandbox.fs.list("/app")
png = sandbox.fs.read_bytes("/app/chart.png")Файлы вне тома Persistent Volumes в /workspace пропадают после остановки sandbox.
Порты
Запустите сервер на 0.0.0.0 внутри sandbox, затем опубликуйте его порт. Каждому запросу нужен токен доступа: в заголовке X-Lizard-Access-Token или один раз как ?lizard_token= в браузере. См. URL предпросмотра.
const { url, hostname, accessToken } = await sandbox.exposePort(3000);
console.log(url); // open in a browser; it carries the token
await fetch(`https://${hostname}/api`, { headers: { 'X-Lizard-Access-Token': accessToken } });
await sandbox.unexpose(3000);import httpx
exposed = sandbox.expose_port(3000)
print(exposed.url) # open in a browser; it carries the token
httpx.get(f"https://{exposed.hostname}/api", headers={"X-Lizard-Access-Token": exposed.access_token})
sandbox.unexpose(3000)Пауза, снимки и fork
Эти вызовы сохраняют память и запущенные процессы, а не только файлы. В быстром старте описано, что сохраняет каждый из них, как оплачиваются восстановленные sandbox и что может не сработать.
await sandbox.pause();
await sandbox.waitForStatus('paused');
await sandbox.resume();
await sandbox.waitForStatus('running');
const saved = await sandbox.snapshot('ready-env');
const copy = await Sandbox.restore(saved.id);
for (const f of await sandbox.fork({ count: 2 })) {
if (f.sandbox) await f.sandbox.process.exec('echo hi');
else console.warn('fork failed:', f.error);
}sandbox.pause()
sandbox.wait_for_status("paused")
sandbox.resume()
sandbox.wait_for_status("running")
saved = sandbox.snapshot("ready-env")
copy = Sandbox.restore(saved["id"])
for f in sandbox.fork(count=2):
if f.sandbox:
f.sandbox.process.exec_("echo hi")
else:
print("fork failed:", f.error)fork возвращает по одной записи на каждую копию: новый sandbox или ошибку, например из-за лимита sandbox в аккаунте. Каждая копия оплачивается так же, как источник.
Запуск кода с сохранением состояния
CodeSandbox запускает шаблон interpreter и выполняет код через runCode (в Python: run_code). В этом шаблоне Python работает в постоянном ядре Jupyter для каждого контекста, поэтому переменные сохраняются между вызовами, а результаты могут включать графики в виде image/png. JavaScript и bash при каждом вызове запускаются как новый процесс. См. интерпретатор кода.
Тома
Подключите том Persistent Volumes по имени, чтобы сохранять /workspace между sandbox:
import { Sandbox, Volume } from '@lizard-build/sdk';
await Volume.getOrCreate('proj_123', 'agent-workdir', { sizeGb: 10 });
const sandbox = await Sandbox.create('base', { projectId: 'proj_123', volumeName: 'agent-workdir' });from lizard import Sandbox, Volume
Volume.get_or_create("proj_123", "agent-workdir", size_gb=10)
sandbox = Sandbox.create("base", project_id="proj_123", volume_name="agent-workdir")Недоступные API
Наблюдение за файлами пока недоступно. sandbox.fork() возвращает 409, если подключён том, и 501 для sandbox, работающего как pod. Sandbox.connect не возобновляет приостановленный или остановленный sandbox; для приостановленного вызовите resume(). Доступа по протоколу SSH нет; lizard sandbox ssh открывает интерактивную оболочку с учётными данными CLI.
Ошибки
При сбоях API SDK выбрасывает эти ошибки (в Python: исключения). У каждой есть HTTP-статус и code, если API его передал.
| Ошибка | Значение |
|---|---|
PaymentRequiredError | HTTP 402: аккаунту нужно подключить Pro или оплатить счёт, прежде чем что-то создавать. В url указан адрес страницы, которую нужно открыть. |
AuthenticationError | HTTP 401 или 403: неверный ключ или нет доступа. |
NotFoundError | HTTP 404: sandbox, файл или снимок не существует либо его срок истёк. |
ConflictError | HTTP 409: конфликт состояния, например fork sandbox с томом. |
TimeoutError | HTTP 408 или 504. |
LizardError | Другие сбои API, включая неподдерживаемые операции. |
Если одновременно работает слишком много sandbox или запусков слишком много, API возвращает HTTP 429; см. лимиты аккаунта.
HTTP API
SDK обращается к REST API Lizard по адресу https://lizard.build. Передавайте API-ключ как Authorization: Bearer liz_... или в заголовке X-API-Key.
| Вызов | Запрос |
|---|---|
| Создание | POST /api/sandboxes с template, projectId, size, timeoutMs, envs, metadata, region, volumeName; возвращает 201 с sandboxId |
| Статус | GET /api/sandboxes/{id} |
| Список | GET /api/sandboxes или GET /api/projects/{projectId}/sandboxes для одного проекта |
| Запуск команды | POST /api/sandboxes/{id}/exec с cmd, envs, workdir, user, timeoutMs; возвращает stdout, stderr, exitCode |
| Изменение срока жизни | POST /api/sandboxes/{id}/timeout с timeoutMs |
| Пауза или возобновление | POST /api/sandboxes/{id}/pause, POST /api/sandboxes/{id}/resume |
| Публикация порта | POST /api/sandboxes/{id}/expose/{port}; DELETE по тому же пути убирает его |
| Остановка | DELETE /api/sandboxes/{id} |
curl -X POST https://lizard.build/api/sandboxes \
-H "Authorization: Bearer $LIZARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"template": "base", "projectId": "proj_123", "timeoutMs": 300000}'Прямой API создаёт sandbox без срока жизни, если не передать timeoutMs.
Хранение и оплата
Оплата, исходящий трафик и то, что сохраняется после остановки, описаны в разделе хранение и оплата. Размеры и почасовые цены смотрите в лимитах.
Обновлено