Ejecutar código¶
run_code ejecuta una celda en un kernel Jupyter con estado dentro del
sandbox, como un notebook: las variables, los imports y los ficheros
abiertos siguen ahí en la siguiente llamada.
Cuándo usarlo¶
- El caso típico de un agente: generar Python, ejecutarlo y leer el resultado, la salida o la traza del error.
- Análisis de datos con pandas y gráficos con matplotlib: los gráficos vuelven como PNG y como datos estructurados.
- Cuándo no: para procesos de sistema o servidores, usa comandos. Para bash, JavaScript o TypeScript, mira Lenguajes y kernels.
Ejemplo rápido¶
from rayito import Sandbox
with Sandbox.create() as sbx:
sbx.run_code("x = 42")
print(sbx.run_code("x").text) # "42": el kernel tiene estado
failed = sbx.run_code("1/0")
print(failed.error.name if failed.error else None) # "ZeroDivisionError" (1)
- Un error del código es un dato de la
Execution, nunca una excepción de Python.
import asyncio
from rayito import AsyncSandbox
async def main() -> None:
async with await AsyncSandbox.create() as sbx:
await sbx.run_code("x = 42")
print((await sbx.run_code("x")).text) # "42"
failed = await sbx.run_code("1/0")
print(failed.error.name if failed.error else None) # "ZeroDivisionError"
asyncio.run(main())
Paso a paso¶
Qué devuelve: Execution¶
| Campo | Qué es |
|---|---|
text |
el text/plain del resultado principal (el valor de la última expresión), o None |
results |
lista de Result, uno por cada salida rica (display(), gráficos, la última expresión) |
logs.stdout, logs.stderr |
listas con lo que la celda imprimió |
error |
ExecutionError(name, value, traceback) si la celda lanzó, o None |
execution_count |
el contador del kernel |
Cada Result trae las representaciones que produjo el kernel: text,
html, markdown, svg, png, jpeg, pdf, latex, json,
javascript, chart (datos del gráfico) y data. formats() dice cuáles
hay, is_main_result (TypeScript: isMainResult) marca el valor de la
última expresión y extra guarda los tipos MIME que no tienen campo propio
(y el aviso rayito/omitted de un resultado
demasiado grande).
Gráficos¶
import base64
from rayito import Sandbox
with Sandbox.create() as sbx:
plot = sbx.run_code("import matplotlib.pyplot as plt; plt.plot([1, 2, 3]); plt.show()")
chart = plot.results[0]
print(chart.formats()) # incluye 'png' y 'chart'
with open("grafico.png", "wb") as out:
out.write(base64.b64decode(chart.png or "")) # (1)!
pngllega en base64, como en Jupyter.
import asyncio
import base64
from rayito import AsyncSandbox
async def main() -> None:
async with await AsyncSandbox.create() as sbx:
plot = await sbx.run_code("import matplotlib.pyplot as plt; plt.plot([1, 2, 3]); plt.show()")
chart = plot.results[0]
print(chart.formats()) # incluye 'png' y 'chart'
with open("grafico.png", "wb") as out:
out.write(base64.b64decode(chart.png or ""))
asyncio.run(main())
import { writeFile } from "node:fs/promises";
import { Sandbox } from "rayito";
await using sbx = await Sandbox.create();
const plot = await sbx.runCode("import matplotlib.pyplot as plt; plt.plot([1, 2, 3]); plt.show()");
const chart = plot.results[0];
console.log(chart?.formats()); // incluye "png" y "chart"
await writeFile("grafico.png", Buffer.from(chart?.png ?? "", "base64"));
Salida en streaming¶
on_stdout, on_stderr, on_result y on_error reciben cada salida
mientras la celda corre, sin esperar al final:
Contextos¶
Cada contexto es un kernel independiente con su propio estado. El contexto
default existe siempre; create_code_context() crea otros (con un tope
por sandbox, ver Límites), con su cwd, su language, sus
envs y, opcionalmente, sus secrets. Devuelve un
CodeContext (id, language, cwd); run_code(context=),
restart_code_context() y remove_code_context() aceptan el objeto o su
id.
from rayito import Sandbox
with Sandbox.create() as sbx:
sbx.run_code("x = 1")
ctx = sbx.create_code_context(cwd="/tmp")
print(sbx.run_code("x", context=ctx).error) # NameError: otro kernel
print([c.id for c in sbx.list_code_contexts()]) # ['default', 'ctx-…']
sbx.restart_code_context(ctx) # vacía su estado
sbx.remove_code_context(ctx)
import asyncio
from rayito import AsyncSandbox
async def main() -> None:
async with await AsyncSandbox.create() as sbx:
await sbx.run_code("x = 1")
ctx = await sbx.create_code_context(cwd="/tmp")
print((await sbx.run_code("x", context=ctx)).error) # NameError
await sbx.remove_code_context(ctx)
asyncio.run(main())
import { Sandbox } from "rayito";
await using sbx = await Sandbox.create();
await sbx.runCode("x = 1");
const ctx = await sbx.createCodeContext({ cwd: "/tmp" });
console.log((await sbx.runCode("x", { context: ctx })).error?.name); // "NameError"
console.log((await sbx.listCodeContexts()).map((c) => c.id));
await sbx.restartCodeContext(ctx);
await sbx.removeCodeContext(ctx);
Timeouts¶
timeout (300 s por defecto) lo impone el agente: al vencer interrumpe el
kernel y la Execution vuelve con error.name == "ExecutionTimeout". El
kernel sigue utilizable en la siguiente celda; si no se recupera en 5 s, el
agente reinicia ese contexto (y su estado se pierde).
Opciones de run_code¶
| Python | TypeScript | Por defecto | Qué hace |
|---|---|---|---|
code |
code |
— | el código de la celda |
language |
language |
"python" |
bash, javascript/js, typescript/ts en rayito-base-poly (Kernels) |
context |
context |
default |
contexto (objeto o id); excluyente con language |
on_stdout, on_stderr |
onStdout, onStderr |
— | cada línea impresa, como OutputMessage |
on_result, on_error |
onResult, onError |
— | cada Result y el error |
envs |
envs |
— | variables de entorno sólo durante esta celda (contextos Python) |
timeout |
timeoutMs |
300 s / 300 000 ms | límite del agente; None / 0 sin límite |
request_timeout |
requestTimeoutMs |
60 s | plazo de la llamada |
secrets |
secrets |
— | secretos en el entorno de la celda (opcional, con coste) |
Errores y solución de problemas¶
| Situación | Python | TypeScript | Qué hacer |
|---|---|---|---|
| el código lanza | execution.error (no es una excepción) |
execution.error |
lee error.name, error.value y error.traceback |
la celda tarda más que timeout |
error.name == "ExecutionTimeout" |
igual | sube timeout |
language y context a la vez, envs en un kernel no Python, code de más de 1 MiB |
InvalidArgumentException |
InvalidArgumentError |
elige uno; para código grande, escríbelo a un fichero y ejecútalo |
kernel que la imagen no trae (bash en rayito-base) |
UnimplementedError |
UnimplementedError |
usa rayito-base-poly |
| demasiados contextos (Límites) | RateLimitException |
RateLimitError |
borra contextos con remove_code_context |
| una celda silenciosa se suspende a mitad | (el SDK se reengancha solo) | igual | sube max_idle_seconds (Pausar y reanudar) |
Diferencias con E2B¶
- La misma API:
rayito.e2b(Python y TypeScript) llama alrun_codenativo y devuelve la mismaExecution. Dos detalles del shim: unlanguageque no existe (r,java) esUnimplementedErrorsin llamar al agente, como en E2B, y en Pythontimeout=Noneson los 300 s por defecto (en el nativo,Nonees sin límite). En el shim de Python,secrets=y losenvsdecreate_code_contextsólo están en el nativo (sbx.native). - Lenguajes: Python siempre; bash, JavaScript y TypeScript en
rayito-base-poly; R y Java no existen.
Ver también¶
- Lenguajes y kernels
- Comandos
- Servidor MCP:
run_codecomo herramienta de un agente - Referencia: Python y TypeScript