API de intérprete de código con Lizard Sandboxes
Lizard Sandboxes ejecuta código generado por LLM en microVMs de Firecracker, cada una con su propio kernel. Esta guía cubre la API CodeSandbox de Lizard SDK: @lizard-build/sdk para TypeScript y JavaScript, y lizard-sdk para Python. Los ejemplos crean un sandbox en Lizard y devuelven su salida a tu agente.
CodeSandbox aísla el código de tu app y tu computadora. Arranca la plantilla interpreter, que incluye Python y bibliotecas de datos habituales. Python se ejecuta en un kernel de Jupyter que conserva las variables entre llamadas, y cada resultado incluye la salida impresa, el valor de la última expresión, los gráficos como image/png y cualquier error con su traceback.
Ejecutar código con estado
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"Un error del código forma parte del resultado, no es una excepción. Los fallos de la solicitud, como una clave de API incorrecta, sí lanzan una excepción.
¿Qué devuelve runCode?
runCode (Python: run_code) devuelve un Execution:
| Campo | Contenido |
|---|---|
stdout, stderr | Todo lo que imprimió el código |
results | Salida enriquecida: el valor de la última expresión, gráficos de matplotlib e imágenes, cada uno con mime y data |
error | name, message y traceback cuando el código lanzó una excepción |
executionCount | El contador de celdas del kernel (Python: execution_count) |
Cada resultado lleva un solo tipo MIME, el más rico que tenga la salida, en este orden: image/png, image/jpeg, image/svg+xml, text/html, text/markdown, application/json, text/latex, text/plain. Las imágenes llegan en base64. Un número vuelve como text/plain, pero un DataFrame de pandas vuelve solo como text/html.
Pasa onStdout, onStderr, onResult u onError (Python: on_stdout, etc.) para recibir la salida mientras se ejecuta el código.
Úsalo como herramienta de un LLM
Dale al modelo una herramienta, por ejemplo run_python con un único argumento de texto code. Cuando el modelo la llame, ejecuta el código en el sandbox y devuelve el texto como resultado de la herramienta. El ejemplo conserva todos los resultados de texto, HTML incluido, así que un DataFrame también llega al modelo. Usa un mismo sandbox durante toda la conversación para que las variables del modelo se conserven entre llamadas.
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()Aquí la duración del sandbox es de diez minutos. Auméntala para conversaciones más largas con setTimeout (Python: set_timeout), o establece timeoutMs: 0 y detén el sandbox tú mismo.
Gráficos
Cuando el código dibuja un gráfico de matplotlib, results contiene un elemento con mime igual a image/png y la imagen en base64 en 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))Contextos, tiempos de espera y lenguajes
- Contextos.
createContext()(Python:create_context()) inicia un kernel aparte con sus propias variables y su propio directorio de trabajo; pásalo comocontextarunCode.listContexts(),restartContext(ctx)ydeleteContext(ctx)los gestionan. Sin un contexto, cada lenguaje usa su propio contexto predeterminado. - Tiempos de espera.
timeoutMs(Python:timeout_ms) limita una llamada y por defecto es de 60 segundos. Un kernel de Python que lo supera se interrumpe y conserva su estado; elerror.namedel resultado esTimeoutError. - Otros lenguajes. JavaScript y bash se ejecutan como un proceso nuevo en cada llamada, así que no se conserva el estado y
resultsqueda vacío. JavaScript se ejecuta en el Node 22 de la plantilla, que no incluye npm. - Pausa y snapshots. Los kernels se ejecutan dentro del sandbox, así que
pause()yresume()conservan sus variables, ysnapshot()yfork()las copian.
Ejecutar comandos
process.exec inicia un proceso distinto para cada comando, por lo que las variables de Python no persisten entre llamadas. Úsalo para pasos de shell como pip install, y guarda en archivos los resultados que necesites después. Consulta ejecutar un comando y la referencia del SDK.
Código no confiable
Trata todo lo que escribe el modelo como no confiable. No pases lizardToken a menos que el código necesite Lizard CLI. Si lo pasas, el sandbox recibe una clave nueva limitada a su proyecto y que se elimina con el sandbox, así que el código que corre en él puede cambiar ese proyecto. Mantén otros secretos fuera de envs.
Almacenamiento y facturación
Las variables y los archivos duran solo lo que dura el sandbox. Las reglas de facturación y almacenamiento están en almacenamiento y facturación; los tamaños y precios, en límites.
Descripción general de Sandboxes · Inicio rápido · Referencia del SDK · Persistent Volumes · Página de Sandboxes
Actualizado