SandboxesOpen beta

A sandbox is a step.

Create microVMs inside your Inngest functions. They retry, resume after a crash, and show up in the trace like every other step. Watch one run:

inngest/create-sandbox.ts
export const createSandbox =
inngest.createFunction(
{ id: "create-sandbox" },
{ event: "playground/create.run" },
async ({ step }) => {
const created = await step.sandbox.create(
"create-sandbox",
{ vcpu: 2, memoryMb: 2048 },
);
const sandbox = await created.waitUntilRunning(
"wait-running",
);
const result = await sandbox.commands.run(
"run-command",
"node --version",
);
await sandbox.destroy("destroy-sandbox");
return result.stdout;
},
);

Want the controls? Pick a command, inject a failure, and read every step’s input and output.

Open the playground

Use cases

Durable machinesfor every agent.

A sandbox is a step. It retries, it shows up on the trace, and the same flow control you already use applies to the run.

  • inngest/analyse-data.ts
    // One machine per run. Commands are steps.
    const sandbox = await step.sandbox.create(
    "create-sandbox",
    {
    name: `analyst-${runId}`,
    vcpu: 1,
    memoryMb: 1024,
    },
    );
    const result = await sandbox.commands.run(
    "run-code",
    ["python3", "-c", code],
    );

    Code interpreter

    Run AI-generated code

    If you ask a question, and your agent writes Python to answer it, that script needs a machine. Each question gets its own sandbox: upload the file, run the code, and the output comes back as the next step.

    Read the docs
  • inngest/score-code.ts
    // Run each case sandboxed. Score after.
    const result = await sandbox.commands.run(
    `case-${i}`,
    'printf %s "$INPUT" | python3 -c "$CODE"',
    {
    environment: {
    CODE: code,
    INPUT: test.stdin,
    },
    timeout: "5s",
    },
    );
    defer("score", {
    function: passRate,
    data: { code, cases },
    experiment: experimentRef,
    });

    Evals

    Score generated code

    A new prompt only counts if the code it writes still passes. Run each case in a sandbox, then score in the background so the result is credited to the prompt that wrote it.

    Read the docs
  • inngest/process-dataset.ts
    // Install once, snapshot, clone per file.
    await builder.commands.run(
    "install",
    "pip install --quiet duckdb",
    { timeout: "5m" },
    );
    const environment = await builder.snapshot(
    "snapshot-environment",
    );
    const worker = await environment.clone(
    `clone-${i}`,
    { name: `dataset-${runId}-${i}` },
    );

    Custom environments

    Heavy jobs, off your servers

    A DuckDB pass, a media batch, or a build will swamp the server handling requests. Install the tools once, snapshot the environment, and clone a worker per file. Each file retries on its own.

    Read the docs

Give the code somewhere to run.

Sandboxes are in open beta. Create one from a function and it shows up on the trace beside every other step.