Skip to content
Runtime

How to run an agent's pytest suite in an isolated sandbox

Upload the project to a microVM, install its requirements, run pytest there, and download the JUnit XML and coverage report.

It bills only the CPU the tests use. That start time runs from create request to first Python result. A 2 vCPU, 4 GiB sandbox costs $0.08 an hour with both CPUs busy. A five-minute suite that keeps them busy costs under a cent. Code an agent wrote runs behind its own Linux kernel, never on your CI runner or your laptop.

Run the suite and bring the reports back

The project folder is uploaded as one compressed archive. Install the requirements first. Then cut the network, so the tests themselves reach nothing:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ timeoutSeconds: 1800 });await sbx.files.upload("./project", "/workspace/project");await sbx.exec("cd project && pip install -q -r requirements.txt pytest==9.1.1 pytest-cov==7.1.0", {  check: true,  timeoutMs: 600_000,});await sbx.network.set({ internet: false });const run = await sbx.exec(  "cd project && python3 -m pytest -q --junitxml=report.xml --cov=. --cov-report=html",  { timeoutMs: 1_200_000, onStdout: (text) => process.stdout.write(text) },);await sbx.files.download("/workspace/project/report.xml", "./report.xml");await sbx.files.download("/workspace/project/htmlcov", "./htmlcov");process.exitCode = run.exitCode ?? 1;
Pythonimport sysfrom withruntime import Sandboxwith Sandbox.create(timeout_seconds=1800) as sbx:    sbx.files.upload("./project", "/workspace/project")    sbx.exec("cd project && pip install -q -r requirements.txt pytest==9.1.1 pytest-cov==7.1.0",             check=True, timeout_ms=600_000)    sbx.network.set(internet=False)    run = sbx.exec("cd project && python3 -m pytest -q --junitxml=report.xml --cov=. --cov-report=html",                   timeout_ms=1_200_000, on_stdout=sys.stdout.write)    sbx.files.download("/workspace/project/report.xml", "report.xml")    sbx.files.download("/workspace/project/htmlcov", "htmlcov")sys.exit(1 if run.exit_code is None else run.exit_code)
  • Streaming: onStdout prints each line as pytest writes it. The result then keeps the whole output, not only the first 64 KiB.
  • Timeouts: a command gets 60 seconds unless you pass timeoutMs. A suite that runs longer returns timedOut: true with the output so far. It never throws.
  • Coverage: --cov-report=html writes the htmlcov folder. One download call returns it.

Why the network goes off after the install

Tests written by a model sometimes call real services, read environment variables or download fixtures. After network.set({ internet: false }) runs, every outbound connection is refused. A test that depends on the internet therefore fails in the report instead of quietly reaching it. The host enforces the rule. sudo inside the sandbox cannot undo it (turn off sandbox internet).

If the suite needs one service, such as a package index or your staging API, use an allow list instead of switching the internet off: network.set({ internet: true, allow: ["staging.example.com"] }).

Read the result from the exit code

pytest's exit code says what happened without parsing any output. Pass it to the agent with the failing tests from report.xml:

Exit code pytest's meaning What to tell the agent
0 All tests collected and passed Done
1 Tests ran and some failed Fix the failures listed in the report
2 Execution was interrupted Rerun; check for a hung test
3 Internal error, or a plugin raised while importing Fix the environment, not the code
4 Usage error, or a conftest.py that fails to import Fix the command or the conftest
5 No tests were collected The agent wrote no tests, or misnamed them
6 Too many warnings (--max-warnings) Clean up warnings

Exit code 5 matters for agents. A model asked to "make the tests pass" can delete every test. pytest then reports 5, not 0.

Use more than one CPU

pytest-xdist spreads tests over worker processes with -n auto. Set the vCPU count to match when you create the sandbox:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ vcpu: 4, memoryMiB: 8192, timeoutSeconds: 1800 });await sbx.files.upload("./project", "/workspace/project");await sbx.exec(  "cd project && pip install -q -r requirements.txt pytest==9.1.1 pytest-xdist==3.8.0",  {    check: true,    timeoutMs: 600_000,  },);await sbx.exec("cd project && python3 -m pytest -n auto -q", {  timeoutMs: 1_200_000,  onStdout: (text) => process.stdout.write(text),});

CPU is billed on what the workers use. Four workers that finish in a quarter of the time cost about the same CPU as one worker that runs four times longer. Sandboxes without credit go up to 2 vCPU and 4 GiB.

Skip the install on every run

When the same dependencies install for every run, build them into a custom image. Building is free. Each later sandbox starts with pytest and the project's packages already in place:

Pythonfrom withruntime import Runtimeruntime = Runtime()with open("project/requirements.txt") as handle:    requirements = [line.strip() for line in handle if line.strip() and not line.startswith("#")]runtime.images.build(    name="pytest-env",    recipe={"pip": ["pytest==9.1.1", "pytest-cov==7.1.0", "pytest-xdist==3.8.0", *requirements]},    on_log=lambda line: print(line["text"]),)with runtime.sandboxes.create(image="pytest-env") as sbx:    sbx.files.upload("./project", "/workspace/project")    print(sbx.exec("cd project && python3 -m pytest -q", timeout_ms=600_000).stdout)

Ubuntu's own python3-pytest package on noble is pytest 7.4.4. Installing from PyPI gets the current 9.1.1.

What is in the sandbox already

Item Detail
Python 3.12, with pip, venv and uv; pip install works without a venv
Preinstalled NumPy, pandas and matplotlib in the default image
Disk 4 GiB by default, about 2.5 GiB free; raise it with diskMiB
Root sudo works, for apt-get install of system libraries a test needs

See the sandbox environment for the full list.

Sources

Checked 25 October 2026.

Facts on this page were checked on 25 October 2026.

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