Sandbox-API- und SDK-Referenz
Lizard SDK ist der Client für Sandboxes auf Lizard (lizard.build): @lizard-build/sdk auf npm für TypeScript und JavaScript und lizard-sdk auf PyPI für Python, importiert als lizard. Beide rufen dieselbe HTTP-API auf. Diese Seite listet jeden Sandbox-Aufruf mit seinem Namen in TypeScript und Python auf, mit Beispielen in beiden Sprachen. Für den ersten Aufruf folgen Sie dem Schnellstart; was Sandboxes sind, erklärt der Überblick.
Installation und Anmeldung
npm install @lizard-build/sdk
pip install lizard-sdk
export LIZARD_API_KEY="<your-api-key>"Erstellen Sie unter Settings → API keys oder mit lizard keys create <name> einen API-Schlüssel. Das SDK liest LIZARD_API_KEY; übergeben Sie apiKey (Python: api_key), um einen anderen Schlüssel zu verwenden. Jede Sandbox braucht ein Projekt. Übergeben Sie projectId (Python: project_id) oder ID, Slug oder Name über project.
Erstellungsoptionen
| 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"},
)- Das erste Argument ist eine Vorlage aus dem Katalog unter Laufzeit und Vorlagen. Ohne Angabe startet das SDK
base. sizeist'mini','small','medium'oder'large': 1 vCPU / 2 GB, 2 vCPU / 4 GB, 4 vCPU / 8 GB (Standard) oder 8 vCPU / 16 GB; siehe Größen und Preise.'mini'startet nur aus den Vorlagenbase,claude,codexundinterpreter, ohne Volume. In der Testphase ist'small'die Standardgröße, es läuft höchstens eine'medium'zur selben Zeit, und nur US-Regionen funktionieren;'large', eine zweite Medium-Sandbox oder eine andere Region löstAuthenticationErrormit HTTP 403 aus. Für eine aus einem Snapshot wiederhergestellte Sandbox giltsizenicht; sie läuft in der Größe ihrer Quelle.timeoutMsbeträgt standardmäßig 300000, also fünf Minuten.0deaktiviert den Ablauf. Siehe Ressourcen und Laufzeit.- Geben Sie bei Bedarf eine Region an; ein Katalogeintrag garantiert keine freie Kapazität. Lassen Sie
regionleer, wenn Sie ein Volume anhängen: Die Sandbox läuft dort, wo das Volume liegt. metadatasind Ihre eigenen Labels;getInfo()gibt sie zurück,list()nicht.lizardTokennimmt einen Ihrerliz_-API-Schlüssel und meldetlizardin der Sandbox an. Ihr Schlüssel autorisiert nur die Anfrage: Die Sandbox erhält einen eigenen neuen Schlüssel, der auf das Projekt der Sandbox beschränkt ist und mit der Sandbox gelöscht wird.lizardkann dort also nur auf dieses Projekt zugreifen. Die Vorlagebaseenthält keinlizard.
Methoden
| TypeScript | Python | Was es tut |
|---|---|---|
Sandbox.create(template, options) | Sandbox.create(template, ...) | Aus einer Katalogvorlage in einem Projekt erstellen. |
Sandbox.connect(sandboxId) | Sandbox.connect(sandbox_id) | Mit bestehender Sandbox verbinden; kein Resume. |
Sandbox.list({ projectId }) | Sandbox.list(project_id=...) | Zugängliche Sandboxes auflisten; Status prüfen. |
sandbox.getInfo() | sandbox.get_info() | Status, Laufzeitumgebung und Metadaten abrufen. |
sandbox.process.exec(cmd, opts) | sandbox.process.exec_(cmd, ...) | Shell-Befehl oder argv-Array ausführen; stdout, stderr und den Exit-Code liefern. |
sandbox.process.list() | sandbox.process.list() | Mit exec gestartete Prozesse auflisten. |
sandbox.process.kill(pid, signal) | sandbox.process.kill(pid, signal) | Ein Signal an einen Prozess und seine Kindprozesse senden; standardmäßig SIGTERM. |
sandbox.fs.write(path, data) | sandbox.fs.write(path, data) | Text oder Bytes schreiben; übergeordnete Verzeichnisse erstellen. |
sandbox.fs.read(path) | sandbox.fs.read(path) | UTF-8-Text lesen. |
sandbox.fs.readBytes(path) | sandbox.fs.read_bytes(path) | Dateibytes lesen. |
sandbox.fs.list(path) | sandbox.fs.list(path) | Verzeichniseinträge auflisten. |
sandbox.fs.stat(path) | sandbox.fs.stat(path) | Typ, Größe, Modus, Eigentümer und Änderungszeit zurückgeben. |
sandbox.fs.makeDir(path) | sandbox.fs.make_dir(path) | Verzeichnis und fehlende übergeordnete Verzeichnisse erstellen. |
sandbox.fs.move(from, to) | sandbox.fs.move(src, dst) | Datei oder Verzeichnis verschieben. |
sandbox.fs.remove(path) | sandbox.fs.remove(path) | Datei oder Verzeichnis entfernen. |
sandbox.exposePort(port) | sandbox.expose_port(port) | Einen Port veröffentlichen; url, hostname und das Zugriffstoken zurückgeben. |
sandbox.getHost(port) | sandbox.get_host(port) | Einen Port veröffentlichen und seinen Hostnamen zurückgeben; Anfragen benötigen sandbox.accessToken. |
sandbox.unexpose(port) | sandbox.unexpose(port) | Einen veröffentlichten Port entfernen. |
sandbox.setTimeout(ms) | sandbox.set_timeout(ms) | Verbleibende Laufzeit setzen, mindestens 1000 ms. |
sandbox.pause() / sandbox.resume() | sandbox.pause() / sandbox.resume() | Pause oder Fortsetzen einreihen und sofort zurückkehren. |
sandbox.pause({ fast: true }) | sandbox.pause(fast=True) | Pausiert und behält nur die Dateien, in etwa einer Sekunde bei jeder Speichergröße; Prozesse enden und das Fortsetzen startet die Sandbox neu. |
sandbox.waitForStatus(status) | sandbox.wait_for_status(status) | Auf paused oder running warten; einen Fehler auslösen, wenn die Pause scheitert. |
sandbox.fork({ count }) | sandbox.fork(count=...) | Eine laufende Sandbox 1- bis 100-mal kopieren, einschließlich Arbeitsspeicher und Prozessen; jede Kopie zählt zu Ihrem Limit laufender Sandboxes. |
sandbox.snapshot(name) | sandbox.snapshot(name) | Arbeitsspeicher, Prozesse und jede Datei als Snapshot speichern. Er lässt sich nur im Projekt und in der Region dieser Sandbox wiederherstellen. |
Sandbox.waitForSnapshot(snapshotId) | Sandbox.wait_for_snapshot(snapshot_id) | Warten, bis ein Snapshot bereit ist. |
Sandbox.restore(snapshotId, { projectId, volumeId, timeoutMs }) | Sandbox.restore(snapshot_id, project_id=..., volume_id=..., timeout_ms=...) | Neue Sandbox aus einem Snapshot starten, im Projekt und in der Region des Snapshots. Jede andere projectId löst AuthenticationError mit HTTP 403 und code gleich SNAPSHOT_SCOPE aus. |
Sandbox.snapshots(projectId) | Sandbox.snapshots(project_id) | Die in einem Projekt erstellten Snapshots auflisten. |
Sandbox.mySnapshots() | Sandbox.my_snapshots() | Alle Snapshots auflisten, die Sie erstellt haben, in all Ihren Workspaces. |
Sandbox.deleteSnapshot(snapshotId) | Sandbox.delete_snapshot(snapshot_id) | Einen Snapshot löschen; daraus wiederhergestellte Sandboxes laufen weiter. |
sandbox.kill() | sandbox.kill() | Sandbox stoppen und Volume trennen. |
Befehle ausführen
process.exec (Python: exec_) führt einen Befehl aus und wartet, bis er endet. Übergeben Sie onStdout oder onStderr (Python: on_stdout, on_stderr), um Ausgaben schon während der Ausführung zu erhalten, eine Zeile pro Aufruf ohne den abschließenden Zeilenumbruch; der Aufruf liefert am Ende trotzdem das vollständige Ergebnis. Übergeben Sie statt eines Strings ein argv-Array, um die Shell zu umgehen; so übergeben Sie nicht vertrauenswürdigen Text sicher als Argument.
const result = await sandbox.process.exec('npm test', {
workdir: '/app',
envs: { NODE_ENV: 'test' },
timeoutMs: 120_000,
onStdout: (line) => console.log(line),
});
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=print,
)
if result.exit_code != 0:
raise RuntimeError(result.stderr)
sandbox.process.exec_(["grep", "-rn", "--", user_query, "/workspace"])Befehlsergebnisse enthalten stdout, stderr und den Exit-Code. Ein Exit-Code ungleich null ist ein Ergebnis, das Sie prüfen; fehlgeschlagene Anfragen lösen eine Exception aus. timeoutMs (Python: timeout_ms) legt fest, wie lange ein Befehl laufen darf, von 1 bis 600 Sekunden. Ohne diese Angabe stoppt der Server den Befehl nach 150 Sekunden, und das TypeScript-SDK hört nach 60 Sekunden auf zu warten und löst eine DOMException mit dem Namen TimeoutError aus. Übergeben Sie timeoutMs für jeden Befehl, der länger als eine Minute laufen kann. process.exec akzeptiert envs, workdir und user; Befehle laufen als root, sofern Sie kein user übergeben. envs bei der Erstellung gelten für jeden Befehl.
Dateien
fs.write schreibt Text oder Bytes; fs.read liest Text. Für binäre Dateien schreiben Sie Bytes und lesen sie mit fs.readBytes (Python: read_bytes) zurück. Verwenden Sie absolute Pfade. Ein fehlender Pfad löst NotFoundError aus.
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")Eine Pause oder ein Snapshot behält jede Datei auf der Festplatte, egal wo Sie sie geschrieben haben. Nach einem Stopp (Kill oder Ablauf) sind Dateien außerhalb eines Volumes aus Persistent Volumes unter /workspace verloren, es sei denn, Sie haben vorher einen Snapshot erstellt.
Ports
Starten Sie in der Sandbox einen Server auf 0.0.0.0 und veröffentlichen Sie dann seinen Port. Jede Anfrage braucht das Zugriffstoken, als Header X-Lizard-Access-Token oder einmalig als ?lizard_token= im Browser. Siehe Vorschau-URLs.
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)Pause, Snapshot und Fork
Diese Aufrufe behalten Arbeitsspeicher, laufende Prozesse und Dateien. Der Schnellstart erklärt, was jeder Aufruf behält, wer einen Snapshot wiederherstellen kann, wie Wiederherstellungen abgerechnet werden und was fehlschlagen kann.
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 liefert einen Eintrag pro Kopie: die neue Sandbox oder einen Fehler, etwa wegen des Sandbox-Limits des Kontos. Jede Kopie wird wie ihre Quelle abgerechnet.
Code mit Zustand ausführen
CodeSandbox startet die Vorlage interpreter und führt Code mit runCode (Python: run_code) aus. In dieser Vorlage läuft Python pro Kontext in einem persistenten Jupyter-Kernel, sodass Variablen zwischen Aufrufen erhalten bleiben und Ergebnisse Diagramme als image/png enthalten können. JavaScript und Bash laufen bei jedem Aufruf als neuer Prozess. Siehe Code Interpreter.
Volumes
Hängen Sie ein Volume aus Persistent Volumes über seinen Namen an, um /workspace zwischen Sandboxes zu behalten:
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")Nicht unterstützte APIs
Dateiüberwachung ist noch nicht verfügbar. sandbox.fork() gibt 409 zurück, wenn ein Volume angehängt ist. Sandbox.connect setzt keine pausierte oder gestoppte Sandbox fort; rufen Sie für eine pausierte resume() auf. Zugriff über das SSH-Protokoll gibt es nicht; lizard sandbox ssh öffnet eine interaktive Shell mit Ihren CLI-Zugangsdaten.
Fehler
Fehlgeschlagene API-Aufrufe lösen diese Fehler aus (Python: raise). Jeder enthält den HTTP-Status und, wenn die API einen sendet, einen code.
| Fehler | Bedeutung |
|---|---|
PaymentRequiredError | HTTP 402: Das Konto muss Pro starten oder eine Rechnung bezahlen, bevor es etwas erstellen kann. url ist die Seite, die Sie öffnen. |
AuthenticationError | HTTP 401 oder 403: ungültiger Schlüssel oder kein Zugriff. In der Testphase gibt auch eine zweite gleichzeitig laufende Medium-Sandbox oder eine Region außerhalb der USA 403 zurück, mit code gleich TRIAL_MEDIUM_RUNNING oder TRIAL_SANDBOX_REGION; eine Large-Sandbox gibt 403 mit SANDBOX_SIZE_NOT_ALLOWED zurück, ob beim Erstellen, Fortsetzen oder Forken. |
NotFoundError | HTTP 404: Die Sandbox, Datei oder der Snapshot existiert nicht oder ist abgelaufen. |
ConflictError | HTTP 409: widersprüchlicher Zustand, etwa beim Forken einer Sandbox mit Volume. |
LimitExceededError | HTTP 429: zu viele vCPU an Sandboxes gleichzeitig oder zu viele Starts. code nennt das Limit, etwa SANDBOX_LIMIT_REACHED oder SANDBOX_RATE_LIMITED. Bei SANDBOX_LIMIT_REACHED sind limit und running in vCPU angegeben, unit sagt das (vcpu), und needed sind die vCPU, die die abgelehnte Sandbox braucht. retryAfterS (Python: retry_after_s) sagt, wann Sie es erneut versuchen können. |
TimeoutError | HTTP 408 oder 504. Das eigene 60-Sekunden-Warten des TypeScript-SDK bei process.exec löst stattdessen eine DOMException mit dem Namen TimeoutError aus. |
LizardError | Andere API-Fehler, einschließlich nicht unterstützter Operationen. |
Die Zahlen hinter HTTP 429 stehen unter Kontolimits.
HTTP-API
Das SDK ruft die REST-API von Lizard unter https://lizard.build auf. Senden Sie Ihren API-Schlüssel als Authorization: Bearer liz_... oder im Header X-API-Key.
| Aufruf | Anfrage |
|---|---|
| Erstellen | POST /api/sandboxes mit template, projectId, size, timeoutMs, envs, metadata, region, volumeName; gibt 201 mit sandboxId zurück |
| Status abrufen | GET /api/sandboxes/{id} |
| Auflisten | GET /api/sandboxes oder GET /api/projects/{projectId}/sandboxes für ein Projekt |
| Befehl ausführen | POST /api/sandboxes/{id}/exec mit cmd, envs, workdir, user, timeoutMs; gibt stdout, stderr, exitCode zurück |
| Laufzeit ändern | POST /api/sandboxes/{id}/timeout mit timeoutMs |
| Pausieren oder fortsetzen | POST /api/sandboxes/{id}/pause, POST /api/sandboxes/{id}/resume |
| Port veröffentlichen | POST /api/sandboxes/{id}/expose/{port}; DELETE auf demselben Pfad entfernt ihn |
| Beenden | DELETE /api/sandboxes/{id} |
| Limits prüfen | GET /api/sandboxes/limits; gibt tier, unit, limits, running und runningVcpu zurück |
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}'Die direkte API erstellt eine Sandbox ohne Ablauf, sofern Sie kein timeoutMs übergeben.
Speicher und Abrechnung
Abrechnung, ausgehender Traffic und was einen Stopp übersteht, sind an einer Stelle beschrieben: unter Speicher und Abrechnung. Größen und Stundenpreise stehen unter Limits.
Aktualisiert