On Runtime an eight-hour agent run costs about 26 cents on a 2 vCPU, 4 GiB sandbox that spends most of its time waiting on its model, because Runtime bills the CPU the agent's commands use, not the CPUs it holds. At the rates in effect on 25 October 2026, that sandbox costs $0.03125 an hour while it waits and $0.08 an hour with both CPUs busy. A busy sandbox is not paused by a timer. If credit or a spending cap runs out, the default is to pause, so the agent's memory and processes are kept rather than lost.
The short answer
Create a paid sandbox with a spending cap and no time limit. Copy the agent into it, and start it as a background process. Save the two ids. They are all you need to come back:
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.create({ name: "agent-run-981", // No timeoutSeconds: it runs while the agent works, however long that is. maxTotalCostMicros: 5_000_000, // never more than $5 over its life diskMiB: 8192, labels: { kind: "long-agent", run: "981" },});await sbx.files.upload("./agent", "/workspace/agent");const agent = await sbx.spawn("python3 main.py --task 'Port the test suite to Vitest'", { cwd: "/workspace/agent",});console.log(sbx.id, agent.id); // keep these in your databasePythonfrom withruntime import Sandboxsbx = Sandbox.create( name="agent-run-981", # No timeout_seconds: it runs while the agent works, however long that is. max_total_cost_micros=5_000_000, # never more than $5 over its life disk_mib=8192, labels={"kind": "long-agent", "run": "981"},)sbx.files.upload("./agent", "/workspace/agent")agent = sbx.spawn("python3 main.py --task 'Port the test suite to Vitest'", cwd="/workspace/agent")print(sbx.id, agent.id) # keep these in your databaseA process started with spawn belongs to the sandbox, not to your
connection. Your server can restart, deploy or crash, and the agent keeps
working.
Come back to it later
Any process that has the ids can reattach, read progress and follow the output from the first byte:
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.connect(process.env.SANDBOX_ID!);const agent = await sbx.processes.get(process.env.PROCESS_ID!);console.log(agent.info.state);for await (const event of agent.output({ cursor: 0 })) { if (event.type === "stdout") process.stdout.write(event.data); if (event.type === "exit") console.log("agent finished with", event.exitCode);}Pythonimport osfrom withruntime import Sandboxsbx = Sandbox.connect(os.environ["SANDBOX_ID"])agent = sbx.process(os.environ["PROCESS_ID"])print(agent.info["state"])for event in agent.output(cursor=0): if event["type"] == "stdout": print(event["data"], end="") elif event["type"] == "exit": print("agent finished with", event["exitCode"])The sandbox keeps the latest 1 MiB of each process's output. An agent that
talks for hours should also append its steps to a file, such as
/workspace/progress.jsonl, which files.readText reads at any time.
What decides how long it runs
| Setting | Effect | Suits |
|---|---|---|
| Nothing (the default) | Runs while it works; pauses after 300 seconds idle | Almost every agent run |
idlePauseSeconds |
Waits longer, or 0 for never, before an idle pause | An agent that sits quiet between bursts |
persistent: true (paid) |
Runs until you stop it, idle or not, while credit lasts | A bot or server nobody watches |
timeoutSeconds |
A fixed end, 60 to 86,400 seconds; extend moves it |
A task that must end on time, busy or not |
A single exec can run for up to 24 hours, and a timeout comes back as a
result with the output so far, not an exception. Without credit, a sandbox
runs the same way within the account's free usage;
persistent needs paid credit.
Pause while it waits for a person
Long agents often stop to ask for approval. Pause the sandbox at that point. Compute billing ends once its processors stop. When the answer arrives, the agent is exactly where it was:
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.connect(process.env.SANDBOX_ID!);await sbx.pause(); // files, memory and the agent process are kept// ... hours later, when the reviewer answers:await sbx.wake();await sbx.files.write("/workspace/agent/approval.txt", "approved");A paid pause is kept while your account has credit. While paused it pays only for the disk and memory blocks it alone owns, at $0.08 per GB per 30-day month.
Know when it ends
Ask for a webhook when a sandbox stops, so a crashed or finished agent never goes unnoticed. Also read its CPU and memory while it runs:
TypeScriptimport { Runtime, Sandbox } from "withruntime";const runtime = new Runtime();await runtime.webhooks.create({ url: "https://example.com/hooks/runtime", events: ["sandbox.stopped", "sandbox.start_failed"],});const sbx = await Sandbox.connect(process.env.SANDBOX_ID!);const { latest } = await sbx.metrics({ range: "1h" });console.log(latest?.cpuPercent);stopReason on the sandbox.stopped event says why it stopped
(metrics and webhooks).
What an hours-long agent needs
| Need | How Runtime covers it |
|---|---|
| Run past any one connection | spawn processes live in the sandbox; processes.get(id) finds them again |
| Run for hours | No time limit by default; credit or a cap running out ends in a pause |
| A bounded bill | maxTotalCostMicros per sandbox and a daily spending limit per key |
| Cheap waiting | Billed on measured CPU, with a floor of a twentieth of a vCPU |
| Waiting days for a human | Pause keeps memory and processes while you have credit |
| No output lost on reconnect | output({ cursor }) replays from any byte of the kept 1 MiB |
| A full machine for the agent | Ubuntu 24.04, sudo, Python 3.12, Node.js 24, Docker with sudo enable-docker |
What it costs
Take one run of 8 hours on 2 vCPU and 4 GiB, where the agent's commands use on average 0.1 of a vCPU because most of the time goes on model calls:
- CPU
- 8 h × 0.1 vCPU × $0.025
- $0.02
- Memory
- 8 h × 4 GiB × $0.0075
- $0.24
- Total
- $0.26
A hundred such runs a month cost about $26. Runtime charges $0.025 per vCPU-hour of measured CPU and $0.0075 per GiB-hour of memory while running, with no plan fee (pricing).
Start
Terminalnpx withruntime sandboxes run --keep -- python3 --versionApprove the link it prints in your browser, then follow the process of a
running agent from a terminal with runtime sandboxes logs <id> <pid> -f
(CLI).
Related: background agents, agent memory that persists, pause and resume a sandbox, coding agent sandbox.
Facts on this page were checked on 26 October 2026.