Code-Interpreter-API mit Lizard Sandboxes
Lizard Sandboxes führen LLM-generierten Code in Firecracker-MicroVMs mit jeweils eigenem Kernel aus. Diese Anleitung beschreibt die CodeSandbox-API von Lizard SDK: @lizard-build/sdk für TypeScript und JavaScript sowie lizard-sdk für Python. Die Beispiele erstellen eine Sandbox auf Lizard und geben ihre Ausgabe an Ihren Agenten zurück.
CodeSandbox isoliert den Code von Ihrer App und Ihrem Rechner. Es startet die Vorlage interpreter, die Python und gängige Datenbibliotheken enthält. Python läuft in einem Jupyter-Kernel, der Variablen zwischen Aufrufen behält, und jedes Ergebnis enthält die Konsolenausgabe, den Wert des letzten Ausdrucks, Diagramme als image/png und einen etwaigen Fehler mit Traceback.
Code mit Zustand ausführen
import { CodeSandbox } from '@lizard-build/sdk';
const sandbox = await CodeSandbox.create({ projectId: 'proj_123', timeoutMs: 300_000 });
try {
await sandbox.runCode('import pandas as pd\ndf = pd.DataFrame({"x": [1, 2, 3]})');
const run = await sandbox.runCode('df.x.sum()');
console.log(run.results[0]?.data); // "np.int64(6)"
const bad = await sandbox.runCode('1/0');
console.log(bad.error?.name); // "ZeroDivisionError"
} finally {
await sandbox.kill();
}from lizard import CodeSandbox
with CodeSandbox.create(project_id="proj_123", timeout_ms=300_000) as sandbox:
sandbox.run_code('import pandas as pd\ndf = pd.DataFrame({"x": [1, 2, 3]})')
run = sandbox.run_code("df.x.sum()")
print(run.results[0].data) # "np.int64(6)"
print(sandbox.run_code("1/0").error.name) # "ZeroDivisionError"Ein Fehler im Code ist Teil des Ergebnisses, keine Exception. Fehlgeschlagene Anfragen, etwa wegen eines ungültigen API-Schlüssels, lösen eine Exception aus.
Was gibt runCode zurück?
runCode (Python: run_code) gibt eine Execution zurück:
| Feld | Inhalt |
|---|---|
stdout, stderr | Alles, was der Code ausgegeben hat |
results | Formatierte Ausgabe: der Wert des letzten Ausdrucks, matplotlib-Diagramme und Bilder, jeweils mit mime und data |
error | name, message und traceback, wenn der Code eine Exception ausgelöst hat |
executionCount | Der Zellenzähler des Kernels (Python: execution_count) |
Jedes Ergebnis hat genau einen MIME-Typ, den reichhaltigsten, den die Ausgabe bietet, in dieser Reihenfolge: image/png, image/jpeg, image/svg+xml, text/html, text/markdown, application/json, text/latex, text/plain. Bilder kommen als base64. Eine Zahl kommt als text/plain zurück, ein pandas-DataFrame dagegen nur als text/html.
Übergeben Sie onStdout, onStderr, onResult oder onError (Python: on_stdout usw.), um Ausgaben schon während der Ausführung zu erhalten.
Als LLM-Tool verwenden
Geben Sie dem Modell ein Tool, zum Beispiel run_python mit einem einzigen String-Argument code. Wenn das Modell es aufruft, führen Sie den Code in der Sandbox aus und senden den Text als Tool-Ergebnis zurück. Das Beispiel behält jedes Text-Ergebnis, auch HTML, damit auch ein DataFrame beim Modell ankommt. Behalten Sie eine Sandbox für das gesamte Gespräch, damit die Variablen des Modells zwischen Aufrufen erhalten bleiben.
import { CodeSandbox } from '@lizard-build/sdk';
const sandbox = await CodeSandbox.create({ projectId: 'proj_123', timeoutMs: 600_000 });
// Call this when the model asks to run Python. Return the text to send back to it.
async function runPython(code: string): Promise<string> {
const run = await sandbox.runCode(code, { timeoutMs: 30_000 });
if (run.error) return `${run.error.name}: ${run.error.message}\n${run.error.traceback}`;
const values = run.results.flatMap((r) =>
r.type === 'result' && r.mime.startsWith('text/') ? [r.data] : [],
);
return [run.stdout, ...values].filter(Boolean).join('\n');
}
// When the conversation ends:
await sandbox.kill();from lizard import CodeSandbox
sandbox = CodeSandbox.create(project_id="proj_123", timeout_ms=600_000)
def run_python(code: str) -> str:
"""Call this when the model asks to run Python. Return the text to send back to it."""
run = sandbox.run_code(code, timeout_ms=30_000)
if run.error:
return f"{run.error.name}: {run.error.message}\n{run.error.traceback}"
values = [r.data for r in run.results if r.mime.startswith("text/")]
return "\n".join(filter(None, [run.stdout, *values]))
# When the conversation ends:
sandbox.kill()Die Laufzeit der Sandbox beträgt hier zehn Minuten. Verlängern Sie sie für längere Gespräche mit setTimeout (Python: set_timeout), oder setzen Sie timeoutMs: 0 und beenden Sie die Sandbox selbst.
Diagramme
Wenn der Code ein matplotlib-Diagramm zeichnet, enthält results einen Eintrag mit mime gleich image/png und dem Bild als base64 in data:
import base64
from pathlib import Path
run = sandbox.run_code("import matplotlib.pyplot as plt\nplt.plot([1, 4, 9])\nplt.show()")
png = next(r.data for r in run.results if r.mime == "image/png")
Path("chart.png").write_bytes(base64.b64decode(png))Kontexte, Timeouts und Sprachen
- Kontexte.
createContext()(Python:create_context()) startet einen separaten Kernel mit eigenen Variablen und eigenem Arbeitsverzeichnis; übergeben Sie ihn alscontextanrunCode.listContexts(),restartContext(ctx)unddeleteContext(ctx)verwalten sie. Ohne Kontext verwendet jede Sprache ihren eigenen Standardkontext. - Timeouts.
timeoutMs(Python:timeout_ms) begrenzt einen Aufruf und beträgt standardmäßig 60 Sekunden. Ein Python-Kernel, der länger läuft, wird unterbrochen und behält seinen Zustand;error.nameim Ergebnis istTimeoutError. - Andere Sprachen. JavaScript und Bash laufen bei jedem Aufruf als neuer Prozess, daher bleibt kein Zustand erhalten und
resultsbleibt leer. JavaScript läuft auf Node 22 aus der Vorlage, ohne npm. - Pause und Snapshots. Kernel laufen in der Sandbox, daher behalten
pause()undresume()ihre Variablen, undsnapshot()undfork()kopieren sie.
Befehle ausführen
process.exec startet für jeden Befehl einen eigenen Prozess; Python-Variablen bleiben daher zwischen Aufrufen nicht erhalten. Verwenden Sie es für Shell-Schritte wie pip install und speichern Sie Ergebnisse, die Sie später brauchen, in Dateien. Siehe Befehl ausführen und die SDK-Referenz.
Nicht vertrauenswürdiger Code
Behandeln Sie alles, was das Modell schreibt, als nicht vertrauenswürdig. Übergeben Sie lizardToken nur, wenn der Code Lizard CLI braucht. Tun Sie es, erhält die Sandbox einen neuen Schlüssel, der auf ihr Projekt beschränkt ist und mit der Sandbox gelöscht wird; Code darin kann also dieses Projekt ändern. Halten Sie andere Secrets aus envs heraus.
Speicher und Abrechnung
Variablen und Dateien bleiben nur so lange erhalten wie die Sandbox. Die Regeln für Abrechnung und Speicher stehen unter Speicher und Abrechnung; Größen und Preise unter Limits.
Sandboxes-Überblick · Schnellstart · SDK-Referenz · Persistent Volumes · Sandboxes-Produktseite
Aktualisiert