Sandboxes クイックスタート
このクイックスタートでは、Lizard SDK で sandbox を作成し、その中で Python を実行し、ファイルを書き込み、ポートを公開して、後片付けを行います。各ステップには TypeScript と Python のコードがあります。Pro またはトライアル中の Lizard (lizard.build) アカウント、API キー、プロジェクトが必要です。まず Sandboxes とは何かを知りたい場合は、概要 を読んでください。
インストールと認証
Lizard SDK をインストールし、Settings → API keys で、または lizard keys create <name> で API キーを作成します。LIZARD_API_KEY に保存してください。すべての sandbox はプロジェクトに属します。例ではその ID を projectId(Python では project_id)として渡しています。project には slug や名前も指定できます。
npm install @lizard-build/sdk
pip install lizard-sdk
export LIZARD_API_KEY="<your-api-key>"コマンドの実行
Sandbox.create はテンプレートから sandbox を起動します。ここでは、Python と一般的なデータ処理ライブラリを含む interpreter を使っています。timeoutMs は有効期間を設定します。SDK の既定は 5 分です。
import { Sandbox } from '@lizard-build/sdk';
const sandbox = await Sandbox.create('interpreter', {
projectId: 'proj_123', timeoutMs: 300_000,
});
try {
const result = await sandbox.process.exec("python -c 'print(2 ** 10)'");
console.log(result.stdout, result.stderr, result.exitCode);
} finally {
await sandbox.kill();
}from lizard import Sandbox
sandbox = Sandbox.create("interpreter", project_id="proj_123", timeout_ms=300_000)
try:
result = sandbox.process.exec_("python -c 'print(2 ** 10)'")
print(result.stdout, result.stderr, result.exit_code)
finally:
sandbox.kill()0 以外の終了コードはエラーではなく結果です: exitCode(Python では exit_code)を自分で確認してください。
ファイル
テキストまたはバイトは fs.write で書き込み、テキストは fs.read で、バイトは fs.readBytes(Python では read_bytes)で読み取ります。ファイルは sandbox が存在する間だけ残ります。ただし、/workspace の Persistent Volumes に書き込んだファイルは例外です。
await sandbox.fs.write("/tmp/task.py", "print(42)\n");
const result = await sandbox.process.exec("python /tmp/task.py");
console.log(result.stdout);sandbox.fs.write("/tmp/task.py", "print(42)\n")
result = sandbox.process.exec_("python /tmp/task.py")
print(result.stdout)公開ポート
0.0.0.0 で待ち受けるサーバーを起動し、exposePort(port)(Python では expose_port)を呼び出します。url、hostname、accessToken が返されます。ポートは非公開です。ブラウザで url を開く(?lizard_token= が付いています)か、X-Lizard-Access-Token ヘッダーでトークンを送信してください。トークンのないリクエストには 401 が返されます。sandbox を停止するとポートは応答しなくなります。エージェントが作った 開発サーバーについては、プレビュー URL を参照してください。
await sandbox.process.exec(
"nohup python -m http.server 3000 --bind 0.0.0.0 --directory /tmp >/tmp/http.log 2>&1 </dev/null &",
);
const { url, hostname, accessToken } = await sandbox.exposePort(3000);
console.log(url); // open in a browser
const res = await fetch(`https://${hostname}/`, {
headers: { 'X-Lizard-Access-Token': accessToken },
});sandbox.process.exec_(
"nohup python -m http.server 3000 --bind 0.0.0.0 --directory /tmp >/tmp/http.log 2>&1 </dev/null &"
)
exposed = sandbox.expose_port(3000)
print(exposed.url) # open in a browser実行中の sandbox への再接続
sandbox ID(sandbox.sandboxId、Python では sandbox.sandbox_id)を保持しておき、別のプロセスや後のリクエストから Sandbox.connect(id) を呼び出すと、同じ sandbox のハンドルを取得できます。connect は sandbox が存在するかどうかを確認するだけです: 一時停止中の sandbox を再開せず、sandbox が停止するか期限切れになった後は NotFoundError を投げます。
const connected = await Sandbox.connect(sandbox.sandboxId);
console.log(await connected.getInfo());connected = Sandbox.connect(sandbox.sandbox_id)
print(connected.get_info())一時停止、再開、スナップショット
pause() は sandbox のメモリと実行中のプロセスを保存し、/workspace をそのノードに残します。一時停止が完了すると計算料金は止まりますが、Persistent Volumes のストレージ料金は引き続き発生します。resume() は同じ ID で sandbox を復元し、計算料金を再開します。どちらも処理をキューに入れてすぐに戻るため、成功を確認するには paused または running を待ってください。
await sandbox.pause();
await sandbox.waitForStatus('paused');
await sandbox.resume();
await sandbox.waitForStatus('running');- 一時停止すると、開いているネットワーク接続は閉じられます。再開後、sandbox 内のプログラムは再接続する必要があります。
- プロセスを保存できない場合、sandbox は実行を続け、
waitForStatusが理由付きのエラーを投げます。再開に失敗した場合、sandbox はチェックポイントを保持したまま一時停止状態に残ります。resume()を再度呼び出してください。 - 一時停止中は有効期間の期限が止まり、再開後に続きから進みます。一時停止中の sandbox は実行数の上限に数えられません。
- 一時停止中の sandbox は同じノードで再開します。そのノードが故障すると一時停止した状態は失われます。必要なファイルはエクスポートしてください。
スナップショットは、実行中の sandbox のメモリと /workspace のファイルを、プロジェクト専用のテンプレートとして保存します。restore するたびに、スナップショットと同じリージョンで新しい sandbox が起動します。取得前にクライアントとターミナルを閉じ、/workspace への書き込みを止めてください。接続中の Persistent Volumes は保存されません。
const saved = await sandbox.snapshot('my-app', { poolSize: 5 });
await Sandbox.waitForSnapshot(saved.id);
const copy = await Sandbox.restore(saved.id);Firecracker の sandbox のスナップショットは、呼び出しが戻った時点で準備が完了し、ディスクから restore されるため、poolSize は適用されません。restore のたびに元の sandbox と同じサイズで実行され、そのサイズの時間単価で課金されます。pod の sandbox のスナップショットは待機中のコピーを保持します (既定で 5 つ、1〜10 で変更可能)。待機中のコピーがないときは、プールが補充されるまで restore が HTTP 503 を返すことがあり、復元した sandbox は実測使用量で課金されます。どちらの場合も、restore には size は適用されません。CLI では lizard sandbox pause <id>、lizard sandbox resume <id>、lizard sandbox snapshot <id> --name my-app、lizard sandbox restore <snapshot-id> を使います。
後片付けと次のステップ
タスクが終わったら、例の finally のように kill() を呼び出します。Python では、with Sandbox.create(...) as sandbox: を使うと、ブロックを抜けるときに sandbox が停止します。停止し忘れた sandbox は期限に達すると停止します。別の有効期間を設定しない限り、作成から 5 分後です。リソースと有効期間 を参照してください。
- すべての呼び出し、オプション、エラー: Sandbox API と SDK リファレンス。
- 呼び出し間で状態を保持する、LLM が書いたコード: コードインタープリター。
- sandbox の終了後も残るファイル: Persistent Volumes。
- sandbox 内のコーディングエージェント: Claude Code または OpenCode。
- ターミナルから同じ手順を実行:
lizard sandbox。ブラウザーでは: Sandboxes ダッシュボード。 - サイズ、料金、同時に実行できる sandbox の数: 制限。製品の概要と比較: Sandboxes。
更新日