Skip to content
Runtime

How to run OpenHands in a cloud sandbox

Install the OpenHands CLI with uv tool install openhands in a Linux microVM, pass the model by environment and run openhands --headless.

Runtime is the isolated machine that OpenHands' headless mode assumes, and the LLM key never reaches it. The OpenHands docs state that headless mode always runs in always-approve mode. Every action the agent chooses runs with no confirmation. On Runtime, each run gets a Firecracker microVM with its own kernel, Ubuntu 24.04 and Python 3.12, the exact Python version the openhands package requires. The key is a Runtime secret, so LLM_API_KEY inside the sandbox is only a placeholder. A 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while the agent waits on the model. The CLI was at version 1.16.0 on PyPI on 25 October 2026.

Question Answer on Runtime
Where do OpenHands' commands run? In the sandbox's own Linux, not on your runner
Where does the LLM key live? On Runtime's servers; the sandbox holds a placeholder
What can the agent reach? The hosts you allow, such as the model API and PyPI
Can OpenHands on a laptop use sandboxes? Yes, through Runtime's MCP server

Store the key under OpenHands' variable

The CLI reads its model settings from three variables when you pass --override-with-envs: LLM_MODEL, LLM_API_KEY and, optionally, LLM_BASE_URL. Without the flag, the CLI ignores them and reads ~/.openhands/settings.json. Store the key under LLM_API_KEY, bound to the provider's host. For Anthropic:

Terminalprintf %s "$ANTHROPIC_API_KEY" | npx withruntime secrets set LLM_API_KEY --host api.anthropic.com

Every sandbox then has LLM_API_KEY set to a placeholder. The proxy replaces it with the real key in HTTPS requests to api.anthropic.com. Anywhere else, the placeholder is useless (secrets sandboxes never see). LLM_MODEL is not sensitive, so it goes in the command's environment.

Run a task headless

TypeScriptimport { writeFile } from "node:fs/promises";import { Sandbox } from "withruntime";const repo = "https://github.com/your-org/your-repo";const task =  "Issue #212: the retry decorator ignores max_attempts. Reproduce it with a test, then fix it.";await using sbx = await Sandbox.create({ diskMiB: 10240, timeoutSeconds: 3600 });const setup = { check: true, timeoutMs: 900_000 } as const;await sbx.exec("uv tool install openhands --python 3.12", setup);await sbx.exec(["git", "clone", "--depth", "1", repo, "/workspace/app"], setup);await sbx.files.write("/workspace/task.md", task);await sbx.network.set({  internet: true,  allow: ["api.anthropic.com", "pypi.org", "files.pythonhosted.org"],});const run = await sbx.exec(  ["openhands", "--headless", "--override-with-envs", "--json", "-f", "/workspace/task.md"],  {    cwd: "/workspace/app",    env: { LLM_MODEL: "anthropic/claude-sonnet-4-5-20250929" },    timeoutMs: 2_400_000,    onStderr: (text) => process.stderr.write(text),  },);const events = run.stdout.split("\n").filter((line) => line.startsWith("{"));console.log(run.exitCode, `${events.length} events`);await sbx.exec("git add -A && git diff --cached > /workspace/openhands.patch", {  cwd: "/workspace/app",  check: true,});await writeFile("openhands.patch", await sbx.files.readText("/workspace/openhands.patch"));
Pythonimport sysfrom withruntime import Sandboxrepo = "https://github.com/your-org/your-repo"task = "Issue #212: the retry decorator ignores max_attempts. Reproduce it with a test, then fix it."with Sandbox.create(disk_mib=10240, timeout_seconds=3600) as sbx:    sbx.exec("uv tool install openhands --python 3.12", check=True, timeout_ms=900_000)    sbx.exec(["git", "clone", "--depth", "1", repo, "/workspace/app"],             check=True, timeout_ms=900_000)    sbx.files.write("/workspace/task.md", task)    sbx.network.set(internet=True,                    allow=["api.anthropic.com", "pypi.org", "files.pythonhosted.org"])    run = sbx.exec(        ["openhands", "--headless", "--override-with-envs", "--json",         "-f", "/workspace/task.md"],        cwd="/workspace/app",        env={"LLM_MODEL": "anthropic/claude-sonnet-4-5-20250929"},        timeout_ms=2_400_000,        on_stderr=sys.stderr.write,    )    events = [line for line in run.stdout.splitlines() if line.startswith("{")]    print(run.exit_code, len(events), "events")    sbx.exec("git add -A && git diff --cached > /workspace/openhands.patch",             cwd="/workspace/app", check=True)    with open("openhands.patch", "w") as file:        file.write(sbx.files.read_text("/workspace/openhands.patch"))

Reading the code:

  • uv tool install openhands --python 3.12 is the install that OpenHands recommends. uv ships in the sandbox image and finds its Python 3.12. The openhands command lands in /workspace/.local/bin, which is first on PATH.
  • A bigger disk. The package brings its SDK and tools with it. 10 GiB leaves room for them and for the project's own dependencies.
  • The task goes in a file. It reaches the CLI through -f, so a long issue description with code blocks arrives intact. -t "<text>" works for short tasks.
  • --headless runs with no UI and approves every action. It needs -t or -f. --json streams the run's events as JSON Lines.
  • --override-with-envs makes the CLI read LLM_MODEL and the placeholder in LLM_API_KEY. The model string uses LiteLLM's provider/model form.
  • The working directory is the checkout. The CLI works where it is started, or in OPENHANDS_WORK_DIR when that is set.
  • The patch comes back as a file, so a large change is never cut at the 64 KiB result limit.

PyPI stays on the allow list because the agent usually installs the project's dependencies to run its tests. For a project whose dependencies are already installed, remove it. The agent can then reach the model and nothing else (turn off sandbox internet).

CLI flags for automation

From the OpenHands CLI docs and its 1.16.0 source, 25 October 2026:

Flag Meaning
--headless No UI, every action approved; needs -t or -f
-t, --task "<text>" Task text
-f, --file <path> Task from a file
--json JSONL events, with --headless only
--override-with-envs Read LLM_MODEL, LLM_API_KEY, LLM_BASE_URL
--resume <id>, --last Carry on an earlier conversation
--always-approve, --llm-approve Interactive approval modes, for runs outside headless

The CLI saves conversations under ~/.openhands/conversations in the sandbox. So --resume works on a sandbox you keep. Pause the sandbox between tasks. The checkout, the history and any running services stay, and compute billing stops.

Point OpenHands at Runtime's tools

When OpenHands runs on your own machine, Runtime's MCP server gives it sandboxes to run code in. The CLI's mcp add command takes the command, then its arguments after --:

Terminalopenhands mcp add runtime --transport stdio npx -- -y withruntime mcp

The same entry by hand, in ~/.openhands/mcp.json:

JSON{  "mcpServers": {    "runtime": { "command": "npx", "args": ["-y", "withruntime", "mcp"] }  }}

The first Runtime call returns a link and a code. Approve Connect agent in the browser, and every tool appears. The file holds no key (MCP). Scripts and CI set RUNTIME_API_KEY from a secret manager instead.

Tool What OpenHands can do
runtime_sandboxes_create Start a microVM for a risky command or a test run
runtime_sandboxes_exec Run it and read exit code, stdout and stderr
runtime_sandboxes_process Follow a long job started in the background
runtime_volumes Keep a cache disk between sandboxes
runtime_sandboxes_manage Stop the sandbox when the job is done

Cost of a headless run

Runtime charges $0.025 per vCPU-hour for CPU actually used, with a floor of a twentieth of a vCPU. It charges $0.0075 per GiB-hour for reserved memory. At 2 vCPUs and 4 GiB, a run costs $0.03125 an hour while OpenHands reasons, and $0.08 an hour with both cores building (pricing). The LLM provider bills tokens on your key. Every account has 100 free hours of a 1 GB machine in the first 30 days, with no card:

Terminalnpx withruntime sandboxes run -- python3 --version

To score many headless runs side by side, see agent evals and SWE-bench. Similar setups: Aider and Goose.

Sources

Checked 25 October 2026.

Facts on this page were checked on 25 October 2026.

Related.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card