Skip to content

Sandboxes and limits ​

A sandbox is the virtual machine a cloud run happens on. This page covers its sizes and architectures, what it has installed, what it can reach, the limits it runs under and what is kept afterwards.

Every run, every pre-run and every "Check once" of a GitHub repository or your own image project gets a fresh virtual machine. It runs in London (see run location). It is never reused or shared, and it is deleted when the run ends. How it is isolated is in the security overview.

Choose a class ​

The class sets the size of the virtual machine. Standard is the default.

ClassvCPUsMemoryDiskx86 machineARM machineSuits
Small2 shared (x86) / 1 (ARM)4 GB30 GBe2-mediumn4a-standard-1Light agents that only call external model APIs
Standard28 GB30 GBe2-standard-2n4a-standard-2Most agents
Large416 GB50 GBe2-standard-4n4a-standard-4Agents with a database and several tool backends
Extra large832 GB100 GBe2-standard-8n4a-standard-8Small local models or heavy dependencies
2X large1664 GB200 GBe2-standard-16n4a-standard-16Large builds, several heavy services, or local models that need more memory
GPU (coming soon)8, and one GPU with 24 GB of GPU memory32 GB100 GBg2-standard-8NoneLocal models that need a GPU

On ARM a vCPU is a full core; on x86 it is a hyperthread. A class costs the same on x86 and ARM; see pricing. Every class is available on every plan, Free included. The GPU class runs on x86 in London only. It is shown greyed out ("coming soon") until the platform's GPU image is ready and has passed its security checks; then the platform switches it on.

To choose, open the project's "Settings" → "Sandbox", pick the "Class" and click "Save". You can also pick it in the "Class" step of the connection wizard.

The platform recommends a class from the test connection (how many containers start beside the agent), the repository's dependency files (very large packages such as torch, TensorFlow or CUDA) and the latest 3 sandbox runs (memory ran out, the disk filled up, preparing reached the time limit, preparing took 10 minutes or more). When it installs very large packages, or the last preparation was slow, it says so beforehand whatever it recommends, such as "This repository installs very large packages such as torch: preparing the environment may take 20 minutes or more". Both places say the recommended class and why beside the class set now, which the class box keeps showing; "Switch to …" applies it. Once the test connection says what it installs (its review.yaml's setup, or the default setup of the repository's root files), only that counts. It never recommends a smaller class.

The platform doesn't change the class by itself unless your organization's owner switched "Ask me before the AI changes things" off under "Organization" → "Policy" → "What the AI does by itself" (on by default). With that on, the AI switches the project to the recommended class within the AI's spending caps and the project says so; "Settings → Sandbox" switches it back.

Every run of the project uses its class, and the run records which class it ran on. A class the platform has disabled can't be chosen for new runs; runs already going are not affected.

Custom spec ​

"Custom…", the last option under "Class", sets the size yourself, on every plan, Free included. It is mostly for a size no class has, such as 200 GB of memory.

FieldValues
CoresAn even number from 2 to 80
Memory (GB)2 to 640
Disk (GB)30 to 2,000
GPUNone, 1, 2 or 4 (24 GB of GPU memory each)

The platform gives you the cheapest machine at least that big:

  • Without a GPU, the cores are the larger of the cores you asked for and the memory ÷ 8, rounded up to an even number (a core comes with at most 8 GB), and the memory is the larger of what you asked for and 2 GB per core. ARM follows the same rule up to 64 cores and 512 GB; for more, choose x86.
  • With GPUs (x86 only), you get the smallest machine with that many GPUs that covers the cores and memory you asked for: with 1 GPU, 4 cores and 16 GB, 8 and 32, 12 and 48, 16 and 64, or 32 and 128; with 2 GPUs, 24 cores and 96 GB; with 4 GPUs, 48 cores and 192 GB. Anything bigger is refused.

When that is more than you asked for, a line under the fields says what you get, for example "Actually allocated: 26 cores · 200 GB memory · 30 GB disk", beside the price per hour ("Price: about $3.64/hour"). A custom spec runs in London, and you don't choose where. GPUs in a custom spec open together with the GPU class; until then a spec with a GPU is refused with the same "coming soon" note.

A custom spec is billed like a class, per second, at its own price, and the estimate before a run uses that price. Prices and examples are under pricing.

Choose the architecture ​

Sandboxes run on x86 (amd64) or ARM (arm64). Set it under "Settings" → "Sandbox" → "Architecture":

SettingRepository projectImage project
Auto (default)x86x86 when the image has it, else ARM
x86x86x86, if the image has it
ARMARMARM, if the image has it

An image project can only choose architectures its image is built for. When the setting names another, a run is refused, and the message names the architectures the image has. A repository defaults to x86 because some Python packages, downloaded binaries and x86-only tools don't install on ARM.

An exec format error, or a package that can't be found for aarch64, means the architecture is wrong. The platform spots these in the log of the pre-run (or of "Check once") and pre-runs again on the other architecture by itself, leaving the project's setting alone. If that passes, it switches the project's architecture, says why under "Settings" → "Sandbox" and offers "Switch back". When both fail, both results are in the pre-run's result. A test waiting on that pre-run moves with it.

When the image has no build for the architecture the setting names, "Check once" runs on the one it has.

Choose the run location ​

Set it under "Settings" → "Sandbox" → "Run location":

SettingWhere the sandbox runs
Auto (default)London
LondonLondon

Both run in London today. They differ only if the platform opens another location: Auto may then start a run there when London is full, while London waits in the queue. Where your data is kept is under data processing.

Since 24 October 2026 sandboxes run in London only. Sweden (EU) is no longer offered, and the settings don't show it; projects that had chosen it were moved to Auto. A project still set to it is refused when a run starts and told to set the run location to "Auto"; its runs are never moved to London without asking.

What the machine image has ​

Sandboxes boot from the platform's machine image, one per architecture:

  • Ubuntu 24.04 LTS, with the week's updates.
  • Docker Engine with the Compose plugin, and the devcontainer CLI.
  • Node.js 20 and 22 (node is 22; node20 and node22 are on the PATH), with corepack for pnpm and yarn.
  • Python 3.12 and 3.11, each with venv, and uv.
  • Go 1.23 and Java 21 (OpenJDK).
  • Pre-pulled images: postgres:16-alpine, mysql:8, redis:7-alpine, node:22-alpine, python:3.12-slim.
  • Two users: runner runs the test runner, and agent (uid 1500) runs your agent, with no sudo and no Docker access.

A virtual machine with a GPU (the GPU class, or a custom spec with GPUs) boots from the same x86 image with the GPU driver and the container toolkit added. An agent that runs on the virtual machine sees the GPU directly; an agent that runs in a container gets it too (its container is started with --gpus all).

The image is rebuilt every week. Each run records the image version it used, as part of its version.

What a sandbox can reach ​

  • Inbound: nothing. Sandboxes have no external IP address.
  • Outbound: TCP ports 443 and 80 only, through one fixed IP address in London. Port 80 is there for image builds; your agent itself is held to 443.
  • Your agent can reach your services on 127.0.0.1 through their published ports, and the internet on port 443. It can't reach the cloud metadata server, the platform's control plane or the container network directly.

Allow-list the sandbox address ​

If your test backend or model gateway admits only known addresses, ask us for the sandboxes' outbound address at admin@nice2.io and add it to your allow-list. The address in Sweden (EU) is no longer used since 24 October 2026. A chat AI is called from the control plane's own fixed address instead.

Limits ​

Your organization's policy limits cloud runs. Owners set it under "Organization" → "Policy", within what the plan allows (see organization policy).

LimitDefaultWhat happens
Sandboxes running at once2Further runs wait in a queue and start in order as earlier ones end.
Longest run120 minutes5 minutes before it, the test runner stops after the attempt in progress and the partial results are reported. A run still going at the limit is stopped and its virtual machine deleted. The virtual machine also has a hard limit of its own: it is deleted 10 minutes after the limit.
Sandbox hours per monthNoneAn owner can set a limit. Once used up, new runs are refused with the reason, and sandboxes still running stop after the attempt in progress. The hours come back on the 1st of the month (UTC).

The plan caps what the policy can be set to:

PlanSandboxes at onceLongest runSandbox hours per month
Free160 minutesNo cap
Pro3240 minutesNo cap
Ultra10480 minutesNo cap
Prepaid3240 minutesNo cap
EnterpriseNo capNo capNo cap

A pre-run or a "Check once" uses a sandbox and sandbox hours like a run. Sandbox time is billed at its class's price, or its custom spec's (unit prices). On Free, Pro and Ultra it comes out of the period's credit first, then the credit balance.

If the virtual machine never reaches the platform ​

A new virtual machine must reach the platform within 12 minutes of being created. If it doesn't, the platform deletes it and starts another by itself. It is the same run, started by the same person, and it waits for one of the organization's slots; the page shows the reason and the first machine's console output (with keys and tokens masked, as in the job's log). That time is not charged and doesn't count against the month's sandbox hours.

The run ends only when the second machine doesn't reach the platform either. The platform then sends our engineers (admin@nice2.io) the job id, the cloud and region each machine was in, and their boot logs (secrets masked). The page says "The platform's engineers have been told", and there's nothing for you to do.

The same goes when the cloud can't create the virtual machine. That isn't charged either; the platform tries once more a minute later and tells us if that fails too. A run is started again once only, and not after a cancel.

If the virtual machine disappears or loses contact mid-run ​

The run is marked unfinished and is not retried: your agent may already have changed data in the test backend. Reset the test backend, then start again. The start form asks you to confirm you've checked. Until someone has, automatic runs and runs started with a project API token are refused. What ran is reported as usual, and the attempts that didn't run can be filled in.

When the virtual machine disappears mid-run, its time after the last partial result it handed in isn't charged and doesn't count against the month's sandbox hours, and the platform's fill-in run after it isn't charged either. A run that loses contact with its sandbox (its lease ran out) is billed as usual. See the platform's problem isn't charged.

When a run loses contact with its sandbox mid-way (its lease runs out), the platform first reads the review.yaml the run used. That is the overlay's copy if it hasn't changed since the run started, and otherwise the repository's at that commit.

When all of the conditions below hold, whatever the agent could change was on that virtual machine and went with it, so the platform checks it itself. The job page says "The platform checked", and the audit log records it as the platform's (job.auto_acknowledge, with the backends it found):

  • the agent runs on the virtual machine (driver: command or harness); with driver: http, its endpoint and reset URL are on 127.0.0.1 or localhost;
  • the tools go through the tool proxy to an upstream on 127.0.0.1 (attach: http_proxy), or are the platform's fixture;
  • the data reset is an HTTP address on 127.0.0.1, or SQL whose database address on 127.0.0.1 is set in runner_env; the data reads are a SQLite file on the machine, or an address on 127.0.0.1 set in runner_env;
  • the only project secrets the agent is handed are model keys (OPENAI_API_KEY and the like), and the addresses agent.env and runner_env hand it are on 127.0.0.1.

If any one of them doesn't hold, a person still checks. Each of these counts as not holding:

  • an outside address;
  • an address from a project secret (the platform can't read its value);
  • a data reset that is a command;
  • MCP tool servers (mcp_wrap, whose connections aren't in review.yaml), or a connection that only sees replies;
  • a review.yaml that can't be read, or that changed after the run started.

What is kept after a run ​

WhatHow long
Your source code or image, and the project secretsDeleted with the virtual machine
The run bundle's evidence files and the sandbox logsThe organization's retention period, 90 days by default
The report and its verdictAs long as the project exists
The dependency cache (repository projects)30 days
A container image built from your Dockerfile or devcontainer.json, per commit30 days

A run bundle may unpack to at most 512 MB, 10,000 files and 64 MB per file.

Next steps ​

The legal texts on this site are drafts pending legal review and are not yet in force.