On Runtime, a research agent's machine costs $0.03125 an hour while the model reads and writes, for 2 vCPUs and 4 GiB. Its fetches run inside the sandbox. So whatever a fetched page tries to make the agent do happens on a disposable machine, not on your server.
What a research agent does that a chatbot does not
A research agent answers a question by working. It searches, opens sources, downloads a dataset, computes results from it, checks a claim, and writes up what it found with citations. Three things run on its behalf:
- Fetching arbitrary URLs, chosen by a model, from pages written by anyone.
- Running code to parse, count and chart what it downloaded.
- Keeping state across dozens of steps: downloaded files, notes, a draft.
Each one is a risk on your own infrastructure. A fetch from your API server can reach internal addresses. Code the agent writes after it reads a hostile page can do what that page told it. A sandbox runs all three in a Firecracker microVM with its own kernel. The host refuses private and internal addresses there, and the machine can be discarded at the end.
The core loop
Create the sandbox and give the agent shell and file tools. It reads the web
with curl inside the sandbox, and keeps what it read under
/workspace/sources/.
TypeScriptimport { Sandbox } from "withruntime";import { sandboxTools } from "withruntime/tools";await using sbx = await Sandbox.create({ timeoutSeconds: 3600, idlePauseSeconds: 600, labels: { agent: "research", question: "q-311" },});// Shell and files for fetching, analysis and notes.const tools = sandboxTools(sbx); // runtime_exec, runtime_read_file, runtime_write_file, runtime_list_filesconsole.log(tools.map((t) => t.name));// ... the model's tool-calling loop runs here ...const report = await sbx.files.readText("/workspace/report.md");console.log(report);Pythonfrom withruntime import Sandboxfrom withruntime.tools import sandbox_toolswith Sandbox.create( timeout_seconds=3600, idle_pause_seconds=600, labels={"agent": "research", "question": "q-311"},) as sbx: run, read, write, ls = sandbox_tools(sbx) # give these to the model # ... the model's tool-calling loop runs here ... print(sbx.files.read_text("/workspace/report.md"))Tell the model in its system prompt to save every source it uses under
/workspace/sources/, and to write its answer to /workspace/report.md. Your
code then reads the report. It can check that every cited file exists before it
shows anything to a user.
Search keys that cannot leak
A search provider's API key is stored once as a Runtime secret, for that provider's hosts. The sandbox sees only a placeholder. The host's proxy adds the real value to requests bound for those hosts. So a page that tricks the model into printing its environment gets nothing it can use (secrets sandboxes never see).
Research that takes hours or days
A sandbox has no time limit, so a long question is never cut off. Two settings make the waiting cheap:
idlePauseSecondspauses the sandbox after that many seconds with nothing happening in it. The default is 300 unless you set another value. The pause keeps files, memory and processes. A paused sandbox pays no compute.- A name.
Sandbox.getOrCreate("q-311")returns the same sandbox from any process tomorrow, woken if it was paused. So a queue worker can pick the question up where another left it.
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.getOrCreate("research-q-311", { idlePauseSeconds: 900 });const notes = await sbx.exec("ls sources | wc -l", { cwd: "/workspace" });console.log(sbx.info.reused, notes.stdout.trim(), "sources so far");A paused sandbox is billed as storage at $0.08 per decimal GB per 30-day month (pricing).
Narrowing what it can reach
By default, a paid sandbox reaches any public host. For a research agent that
should read only certain sites, such as a company's own docs, a standards body or
a statistics office, pass an allow list at create. Or change it mid-task with
sbx.network.set({ internet: true, allow: [...] }). A rule applies immediately,
including to open connections. Root in the guest cannot remove it
(the sandbox environment).
What the agent's sandbox covers
| Need | How Runtime covers it |
|---|---|
| Fetching URLs a model picked | The host refuses private and internal addresses, for every sandbox |
| Analysis of what it downloaded | Python 3.12 with pandas, NumPy and matplotlib; Node.js 24; sudo apt |
| Search keys that cannot leak | The host's proxy injects secrets; they are never present in the guest |
| Pauses for human review | Pause keeps memory and processes while you have credit |
| Many questions at the same time | 100 sandboxes at the same time on a paid account |
| Knowing what it did | Lifecycle events and per-minute CPU and memory readings |
What it costs
Take 500 research tasks a month. Each keeps a 2 vCPU, 4 GiB sandbox running for 20 minutes. Its fetches, parsing and charts use 90 CPU-seconds in all:
- CPU
- 500 × 90 s / 3,600 × $0.025
- $0.31
- Memory
- 500 × 1,200 s / 3,600 × 4 GiB × $0.0075
- $5.00
- Total
- $5.31
About a cent each, at Runtime's rates of $0.025 per vCPU-hour of measured CPU and $0.0075 per GiB-hour (pricing). You pay for model tokens to your model provider, not to Runtime. A new account gets 100 free hours of a 1 GB machine in its first 30 days, about 75 such tasks, with no card.
Start
Terminalclaude mcp add --scope user runtime -- npx -y withruntime mcpThat gives Claude Code, or any MCP client, Runtime's own tools. Approve the link it shows once in your browser. For your own agent, install the JavaScript or Python SDK and start from the loop above.
Related: browser automation agent, what MCP is, egress control, pause and resume a sandbox, AI data pipelines.
Facts on this page were checked on 26 October 2026.