SandboxesEjecutar Python

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:

CampoContenido
stdout, stderrTodo lo que imprimió el código
resultsSalida enriquecida: el valor de la última expresión, gráficos de matplotlib e imágenes, cada uno con mime y data
errorname, message y traceback cuando el código lanzó una excepción
executionCountEl 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 como context a runCode. listContexts(), restartContext(ctx) y deleteContext(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; el error.name del resultado es TimeoutError.
  • Otros lenguajes. JavaScript y bash se ejecutan como un proceso nuevo en cada llamada, así que no se conserva el estado y results queda 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() y resume() conservan sus variables, y snapshot() y fork() 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