SandboxesSDK-Referenz

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

TypeScriptPython
projectId / projectproject_id / project
timeoutMstimeout_ms
regionregion
volumeName / volumeIdvolume_name / volume_id
sizesize
snapshotIdsnapshot_id
envsenvs
metadatametadata
lizardTokenlizard_token
apiKeyapi_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.
  • size ist '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 Vorlagen base, claude, codex und interpreter, 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öst AuthenticationError mit HTTP 403 aus. Für eine aus einem Snapshot wiederhergestellte Sandbox gilt size nicht; sie läuft in der Größe ihrer Quelle.
  • timeoutMs beträgt standardmäßig 300000, also fünf Minuten. 0 deaktiviert den Ablauf. Siehe Ressourcen und Laufzeit.
  • Geben Sie bei Bedarf eine Region an; ein Katalogeintrag garantiert keine freie Kapazität. Lassen Sie region leer, wenn Sie ein Volume anhängen: Die Sandbox läuft dort, wo das Volume liegt.
  • metadata sind Ihre eigenen Labels; getInfo() gibt sie zurück, list() nicht.
  • lizardToken nimmt einen Ihrer liz_-API-Schlüssel und meldet lizard in 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. lizard kann dort also nur auf dieses Projekt zugreifen. Die Vorlage base enthält kein lizard.

Methoden

TypeScriptPythonWas 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.

FehlerBedeutung
PaymentRequiredErrorHTTP 402: Das Konto muss Pro starten oder eine Rechnung bezahlen, bevor es etwas erstellen kann. url ist die Seite, die Sie öffnen.
AuthenticationErrorHTTP 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.
NotFoundErrorHTTP 404: Die Sandbox, Datei oder der Snapshot existiert nicht oder ist abgelaufen.
ConflictErrorHTTP 409: widersprüchlicher Zustand, etwa beim Forken einer Sandbox mit Volume.
LimitExceededErrorHTTP 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.
TimeoutErrorHTTP 408 oder 504. Das eigene 60-Sekunden-Warten des TypeScript-SDK bei process.exec löst stattdessen eine DOMException mit dem Namen TimeoutError aus.
LizardErrorAndere 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.

AufrufAnfrage
ErstellenPOST /api/sandboxes mit template, projectId, size, timeoutMs, envs, metadata, region, volumeName; gibt 201 mit sandboxId zurück
Status abrufenGET /api/sandboxes/{id}
AuflistenGET /api/sandboxes oder GET /api/projects/{projectId}/sandboxes für ein Projekt
Befehl ausführenPOST /api/sandboxes/{id}/exec mit cmd, envs, workdir, user, timeoutMs; gibt stdout, stderr, exitCode zurück
Laufzeit ändernPOST /api/sandboxes/{id}/timeout mit timeoutMs
Pausieren oder fortsetzenPOST /api/sandboxes/{id}/pause, POST /api/sandboxes/{id}/resume
Port veröffentlichenPOST /api/sandboxes/{id}/expose/{port}; DELETE auf demselben Pfad entfernt ihn
BeendenDELETE /api/sandboxes/{id}
Limits prüfenGET /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