On Runtime pandas, NumPy and matplotlib are already installed, and the analysis pays for the CPU it uses. A 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while the model thinks, and $0.08 an hour with both CPUs busy. Every analysis can have a machine of its own.
The short answer
The agent loop has three parts: upload the data, run the model's cells, and return the results.
TypeScriptimport { writeFile } from "node:fs/promises";import { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ network: { internet: false }, timeoutSeconds: 1800 });await sbx.files.write("/workspace/orders.csv", "region,amount\nwest,120\neast,90\nwest,40\n");// Each cell is code the model wrote; variables carry over between cells.await sbx.interpreter.run("import pandas as pd\ndf = pd.read_csv('orders.csv')");const table = await sbx.interpreter.run("df.groupby('region')['amount'].sum()");console.log(table.results[0]?.data["text/plain"]);const chart = await sbx.interpreter.run( "import matplotlib.pyplot as plt\ndf.groupby('region')['amount'].sum().plot.bar()\nplt.show()",);const png = chart.results.find((r) => r.data["image/png"])?.data["image/png"];if (typeof png === "string") await writeFile("chart.png", Buffer.from(png, "base64"));Pythonimport base64from withruntime import Sandboxwith Sandbox.create(network={"internet": False}, timeout_seconds=1800) as sbx: sbx.files.write("/workspace/orders.csv", "region,amount\nwest,120\neast,90\nwest,40\n") # Each cell is code the model wrote; variables carry over between cells. sbx.interpreter.run("import pandas as pd\ndf = pd.read_csv('orders.csv')") table = sbx.interpreter.run("df.groupby('region')['amount'].sum()") print(table["results"][0]["data"]["text/plain"]) chart = sbx.interpreter.run( "import matplotlib.pyplot as plt\ndf.groupby('region')['amount'].sum().plot.bar()\nplt.show()" ) for result in chart["results"]: if "image/png" in result["data"]: with open("chart.png", "wb") as file: file.write(base64.b64decode(result["data"]["image/png"]))Give the model one tool, run_python(code), that calls interpreter.run and
returns the cell's stdout, its error and its text results. Keep the images
for the user; send the model a line saying a chart was made.
Why the interpreter and not python3 script.py
A script starts with no saved state each time, so the agent reloads a large file on every step. The interpreter keeps the data frame in memory between cells, as a notebook does:
| Step the agent takes | Script per step | Interpreter session |
|---|---|---|
| Load a 500 MB CSV | Every step | Once |
| Inspect columns, then clean them | Two programs, two loads | Two cells on the same df |
| Make a chart | Save to a file, then read it | Returned as a PNG result |
| Show a data frame | Print text | Returned as a table |
| An exception | Exit code and stderr | Error name, value and traceback |
The interpreter also runs R, JavaScript, TypeScript, Java, Bash and Go. R plots come back as PNG, and R data frames come back as tables. R installs the first time a sandbox uses it, which takes about 90 seconds once per sandbox. To skip that wait, build R into an image.
Bring your own libraries
Build an image once with the packages your analyses need, then create every sandbox from it:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "analysis", recipe: { pip: ["polars", "duckdb", "scikit-learn", "seaborn"] },});await using sbx = await runtime.sandboxes.create({ image: "analysis", network: { internet: false },});const cell = await sbx.interpreter.run("import duckdb\nduckdb.sql('select 42').fetchall()");console.log(cell.results[0]?.data["text/plain"]);Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="analysis", recipe={"pip": ["polars", "duckdb", "scikit-learn", "seaborn"]})with runtime.sandboxes.create(image="analysis", network={"internet": False}) as sbx: cell = sbx.interpreter.run("import duckdb\nduckdb.sql('select 42').fetchall()") print(cell["results"][0]["data"]["text/plain"])Building an image is free; a stored one is charged at $0.08 per GB per 30-day month, and an account without credit stores its first three images free (custom images).
Large and private data
- Big files:
files.writeandfiles.uploadsend large files in parallel 1 MiB chunks, each checked by SHA-256, and resume after a dropped connection. Under/workspacethere is no size limit beyond the disk, so ask for more withdiskMiB. - Data in a bucket: mount your own S3, R2 or Google Cloud Storage bucket as a directory; the sandbox never holds the bucket's key (mount your own bucket).
- A database the agent should query: store its API key as a secret. The sandbox sees a placeholder, and the host's proxy adds the value only on HTTPS requests to the hosts you name.
- Nothing leaves: with
network: { internet: false }the model's code cannot send the data anywhere, and root in the guest cannot turn it back on.
What a data analysis agent needs
| Need | How Runtime covers it |
|---|---|
| Python data tools | NumPy, pandas and matplotlib in the default image; Python 3.12 |
| State across steps | Interpreter variables persist between cells |
| Charts and tables | matplotlib as PNG; pandas data frames as tables; display for files |
| Isolation per user | A Firecracker microVM with its own kernel for every sandbox |
| Keep the data in | Internet off, or an allow list, enforced on the host |
| Code that runs too long | timeoutMs per cell; timeoutSeconds bounds the sandbox |
| Coming back tomorrow | Sandbox.getOrCreate(name) and idlePauseSeconds: pause keeps memory, so the data frame is still loaded |
What it costs
Take 1,000 analyses a month, each keeping a 2 vCPU, 4 GiB sandbox running for 3 minutes, with the cells using 40 CPU-seconds:
- CPU
- 1,000 × 40 s / 3,600 × $0.025
- $0.28
- Memory
- 1,000 × 180 s / 3,600 × 4 GiB × $0.0075
- $1.50
- Total
- $1.78
Runtime charges $0.025 per vCPU-hour of measured CPU, with a floor of a twentieth of a vCPU, and $0.0075 per GiB-hour of memory (pricing). A new account gets 100 free hours of a 1 GB machine in its first 30 days without a card.
Start
Terminalnpx withruntime sandboxes run -- python3 -c 'import pandas; print(pandas.__version__)'The first run prints a link to approve in your browser. From a shell,
runtime sandboxes run-code <id> analysis.py --out-dir charts runs a file as a
cell and saves its charts as PNG (CLI).
Related: code interpreter for chatbots, what a code interpreter is, egress control, run untrusted LLM code safely.
Facts on this page were checked on 26 October 2026.