Skip to content

First sandbox

On this page you create a sandbox, run a command, write and read a file, run Python code with state and destroy the sandbox. Then you reconnect to a sandbox from another process.

First you need the SDK installed (Installation) and the rayito-base image published in your account (Set up AWS):

export AWS_PROFILE=<your-profile> AWS_REGION=us-east-1 RAYITO_TEMPLATE=rayito-base

How to run each example

Save the code to a file and run it: python first.py in Python, npx tsx first.ts in TypeScript. In TypeScript the project needs "type": "module" and a tsconfig.json with "lib": ["ES2022", "ESNext.Disposable"]; the full recipe is in Running the examples.

Create, use and destroy

from rayito import Sandbox

with Sandbox.create(timeout=900) as sbx:  # (1)!
    print(sbx.commands.run("echo hello").stdout)  # "hello\n"
    sbx.files.write("/home/user/a.txt", "content")
    print(sbx.files.read("/home/user/a.txt"))  # "content"
    print(sbx.run_code("x = 40; x + 2").text)  # "42" (2)
  1. timeout is the sandbox's maximum lifetime in seconds (3600 by default, capped at 8 h). with calls kill() on exit.
  2. The kernel keeps state between cells: x still exists in the next run_code call.
import asyncio

from rayito import AsyncSandbox


async def main() -> None:
    async with await AsyncSandbox.create(timeout=900) as sbx:
        print((await sbx.commands.run("echo hello")).stdout)  # "hello\n"
        await sbx.files.write("/home/user/a.txt", "content")
        print(await sbx.files.read("/home/user/a.txt"))  # "content"
        print((await sbx.run_code("x = 40; x + 2")).text)  # "42"


asyncio.run(main())
import { Sandbox } from "rayito";

await using sbx = await Sandbox.create({ timeoutMs: 900_000 }); // (1)!
console.log((await sbx.commands.run("echo hello")).stdout); // "hello\n"
await sbx.files.write("/home/user/a.txt", "content");
console.log(await sbx.files.read("/home/user/a.txt")); // "content"
console.log((await sbx.runCode("x = 40; x + 2")).text); // "42"
  1. In TypeScript, times are in milliseconds (timeoutMs). await using calls kill() when the block exits.
from rayito.e2b import Sandbox  # before: from e2b_code_interpreter import Sandbox

with Sandbox.create(timeout=900) as sbx:
    print(sbx.commands.run("echo hello").stdout)  # "hello\n"
    sbx.files.write("/home/user/a.txt", "content")
    print(sbx.files.read("/home/user/a.txt"))  # "content"
    print(sbx.run_code("x = 40; x + 2").text)  # "42"

The same program written for the E2B 2.x SDK, changing only the import. The shim follows E2B's defaults (timeout=300, no auto-suspend) and requires a 0.3.0 or later image: Migrate from E2B.

What happens underneath:

  1. create() launches a MicroVM from the image (run-microvm) and waits for rayd, the agent inside, to be ready: about 2 s to the agent and 5–6 s to the Python kernel.
  2. Each call travels over gRPC through the AWS proxy, authenticated with a proxy token and with the sandbox's access token.
  3. When the block exits, kill() terminates the MicroVM (terminate-microvm).

Always release the sandbox

Without with / await using, call kill() yourself. A forgotten sandbox keeps billing ≈ $0.126/h (2 GB, Pricing) until its timeout. To find orphans: rayito sandbox list and rayito sandbox kill.

Reconnect from another process

A sandbox does not depend on the process that created it. Save its sandbox_id and its access token and connect from another process, another machine or after a restart:

from rayito import Sandbox

sbx = Sandbox.create()
sandbox_id, token = sbx.sandbox_id, sbx.access_token  # (1)!

again = Sandbox.connect(sandbox_id, access_token=token)
print(again.commands.run("hostname").stdout)
again.kill()
  1. The access token is a secret: store it as you would a password. Without it you cannot talk to the sandbox.
import asyncio

from rayito import AsyncSandbox


async def main() -> None:
    sbx = await AsyncSandbox.create()
    sandbox_id, token = sbx.sandbox_id, sbx.access_token

    again = await AsyncSandbox.connect(sandbox_id, access_token=token)
    print((await again.commands.run("hostname")).stdout)
    await again.kill()


asyncio.run(main())
import { Sandbox } from "rayito";

const sbx = await Sandbox.create();
const { sandboxId, accessToken } = sbx;

const again = await Sandbox.connect(sandboxId, { accessToken });
console.log((await again.commands.run("hostname")).stdout);
await again.kill();

connect() resumes the sandbox if it was paused. Without timeout= it does not extend its deadline; with it, it only extends it (Server-side deadline).

Recap

  • Sandbox.create() launches a MicroVM in your account; with / await using destroys it when done.
  • commands.run runs processes, files reads and writes files and run_code runs code in a kernel with state.
  • sandbox_id + access_token are enough to reconnect from any process with AWS credentials.

Next step

  • Concepts: what runs where, deadlines, tokens and reconnection.
  • Commands, Run code and Files: each feature in detail.
  • Agent in the sandbox: a coding agent (OpenCode or deepagents) inside the sandbox, with a normal create() and sbx.agent.run(...).
  • Migrate from E2B: if you come from e2b_code_interpreter or @e2b/code-interpreter.
  • Pricing: what each operation costs, measured.