> ## Documentation Index
> Fetch the complete documentation index at: https://checkfu.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Sandbox defaults

> What sandbox you get when you do not pick one, per lane, and exactly what each default costs you in capability.

Nothing in the public API names a sandbox provider. A Session names a
[SandboxProfile](/concepts/security) — a tier, a network policy, a retention mode,
resource limits — and the control plane lands the Run on a Runner that advertises a
provider satisfying every one of those requirements. So "which provider ran my agent?"
always has an answer, and it is always chosen for you.

This page is that answer, per lane, with the capability consequences. It is the only
place these defaults are stated together; everything else is the code that implements
them.

## The selection rule, once

A Runner advertises an **ordered** list of providers. When a Run names only
requirements, the control plane intersects that advertisement with the server-owned
pool enrollment and takes the **first entry that satisfies the Run**. Order is
therefore the tie-break, and it is fixed:

```
checkfu-mock  →  docker  →  e2b  →  daytona  →  host-process
```

A Runner advertising both Docker and host-process serves an unpinned Run on **Docker**,
and falls through to host-process only when Docker cannot satisfy the requirements —
which is also the honest reading of "host-process is a fallback, not a peer". The mock
sits first but is only ever advertised when a Runner is started with
`CHECKFU_ENABLE_MOCK_HARNESS=true` — which `checkfu dev` does for you, and says so — so
it cannot appear ahead of a real provider on a Runner nobody put in that mode.

`daytona` is a supported hosted placement that ranks **below** `e2b` on purpose.
Admitting a placement is not the same as defaulting to it, so a Runner that enables
both still serves an unpinned Run on E2B; enabling Daytona alone is you choosing it,
not the platform migrating you. Nothing in this rank is a claim about either
provider's reliability or about concentration risk.

One place deliberately does **not** choose for you: once a Run is placed, the sandbox
runtime resolves the adapter by exact provider and revision, and a request matching more
than one adapter fails as ambiguous rather than picking a winner. Ordering decides which
provider a Run lands on; nothing downstream of that guesses.

Every Runner announces this on start, before it attaches.
`checkfu.runner.sandbox_provider.advertised` names each provider, its rank in that
order, and its realized posture; a provider that claims no network isolation is
announced as a **warning**, not an info line. A Runner that assembled no provider at
all emits `checkfu.runner.sandbox_providers.none` — and then fails to attach rather
than idling, because a capability advertisement must carry at least one provider. The
warning is what tells you which of those two things happened.

## Defaults per lane

| Lane                                                      | Default when you name nothing                                                                                                                                     | What that costs you                                                                                                                                                                                                                                                                                                                        |
| --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Hosted** (Checkfu-operated platform pool)               | `e2b`                                                                                                                                                             | `ephemeral_zdr` retention **only** — no durable snapshots and no [Checkpoint](/concepts/checkpoints) to resume from; zero mounts; no package materialization; `amd64` microVM only. Network isolation and compute accounting are enforced.                                                                                                 |
| **BYOC** (your own Runner, `checkfu-runner`)              | `docker` when a pinned model relay **and** its egress network are configured; otherwise **no provider at all**, unless you separately enabled E2B or host-process | Without the relay the Docker provider is not advertised — the Runner warns that it assembled no provider (`checkfu.runner.sandbox_providers.none`) and then fails to attach, rather than sitting idle looking healthy. With it: `durable` and `ephemeral_zdr`, snapshot clone, up to 61 mounts, network isolation enforced.                |
| **Local CLI, packaged artifact** (`checkfu runner start`) | `host-process`                                                                                                                                                    | **No container isolation and no egress enforcement** — harnesses run as ordinary OS processes on your machine's own network. `unrestricted` network mode only, so a `none` or `allowlist` SandboxProfile can never be admitted here. No snapshots, no mounts, no package materialization, `durable` retention only, no compute accounting. |
| **Local CLI, source checkout** (`checkfu runner start`)   | none forced — whatever `CHECKFU_*` configures, which is Docker-with-relay or nothing                                                                              | Same as BYOC, including the failure to attach when nothing is configured. The CLI states this before the Runner starts.                                                                                                                                                                                                                    |
| **Local development** (`checkfu dev`)                     | `checkfu-mock`                                                                                                                                                    | **No harness code executes and no container is created.** The mock settles the control path deterministically; it proves your wiring, never your agent.                                                                                                                                                                                    |

`--sandbox host-process|docker|none` overrides the local CLI lanes, except that inherited
`CHECKFU_ENABLE_HOST_PROCESS_SANDBOX=true` wins over every flag — weak isolation is chosen,
never silently inherited. The only other valid value is exact `false`; malformed values fail
before launch. `checkfu dev --harness` picks the development lane's
sandbox: any catalog harness or `oci` moves it off the mock and onto Docker.

## The hosted baseline, exactly

"Hosted lands on E2B" is a provider, not a baseline. This is the baseline — what a
hosted sandbox actually gives you, in the numbers the adapter advertises. Every figure
below is pinned to the adapter constants by
`apps/runner/test/e2b-hosted-baseline.test.ts`, so this table cannot drift from the code
without a test failing.

### There is no default image, and that is the design

The first thing to know is the thing most likely to surprise you if you arrive from a
platform that ships one: **Checkfu has no hosted default base image and no default OS.**
There is no "Ubuntu 22.04 unless you say otherwise". Every SandboxProfile names its own
`base_image` as a reference plus an exact `sha256:` digest, and the hosted template is
built from that image and nothing else — Checkfu adds no layer of its own on top.

So the preinstalled inventory of a hosted sandbox is exactly:

1. whatever your digest-pinned base image contains, plus
2. the `packages` your profile declares, installed into a derived image before the
   sandbox starts.

Nothing else is present, and nothing is present that you did not name. The cost is that
a first profile is more typing than a platform with a default image. The benefit is the
one this whole surface is organized around: the image your agent ran on is a digest you
chose, so "what was installed?" is answerable exactly, months later, from the profile
version alone.

### Ceilings and floors

Resource limits are yours to set on the profile; the hosted provider bounds what it will
accept. Note where that bound bites: creating the profile does **not** check it — a
profile asking for 16 GiB is stored happily. The refusal comes when a Run tries to
provision onto this provider, and it is a refusal, never a silent clamp. So a profile
outside these bounds is not an error you see at authoring time; it is a Run that cannot
land on the hosted lane.

| Axis         | Hosted floor          | Hosted ceiling            |
| ------------ | --------------------- | ------------------------- |
| CPU          | 1,000 millis (1 core) | 8,000 millis (8 cores)    |
| Memory       | 512 MiB               | 8,192 MiB (8 GiB)         |
| Disk         | 20,480 MiB (20 GiB)   | 1,048,576 MiB (1 TiB)     |
| Max duration | 1 second              | 86,400 seconds (24 hours) |

Two realization details are worth knowing because they are visible in what you get:
CPU is realized as whole cores (`cpu_millis` divided by 1,000, rounded **down** — so
1,500 millis is one core), and memory is rounded **down** to an even MiB. Both round
down, never up: the sandbox never exceeds the limit the profile named.

### What the hosted lane does not do

| Capability | Hosted               | Why it matters                                                                |
| ---------- | -------------------- | ----------------------------------------------------------------------------- |
| Retention  | `ephemeral_zdr` only | No durable snapshot and no [Checkpoint](/concepts/checkpoints) to resume from |
| Snapshots  | Not supported        | A Session cannot be cloned from a hosted sandbox                              |
| Mounts     | 0                    | Memory, files, and project mounts do not materialize on this lane             |

### Isolation, per axis, with its authority

A hosted sandbox does not claim uniform hardening. Each axis names who enforces it, and
`not_enforced` is stated rather than omitted — an absent control is a fact, not a gap in
telemetry.

| Axis                 | Authority           |
| -------------------- | ------------------- |
| Sandbox isolation    | `provider_attested` |
| Disk limit           | `provider_attested` |
| Network policy       | `provider_attested` |
| Resource limits      | `provider_attested` |
| Mounts sealed        | `runner_enforced`   |
| Non-root             | `guest_observed`    |
| Root read-only       | `not_enforced`      |
| No new privileges    | `not_enforced`      |
| Capabilities dropped | `not_enforced`      |

`guest_observed` is evidence, not enforcement: the guest reported it and the platform
cannot prove the guest was prevented from changing what it reports. Read the four
`provider_attested` rows as the hosted lane's real isolation story, and see
[provider grading](/concepts/sandbox-provider-grading) for what an egress claim is worth
at each grade.

### Which local lane you landed in

`checkfu runner start` prints one of these before the Runner attaches. There is no
silent outcome — every lane below announces, including the ones that force nothing.

| Lane                     | How you get it                                                                                    | What the Runner ends up with                                                                                                    |
| ------------------------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `host-process`           | packaged artifact with no `--sandbox`, or `--sandbox host-process`                                | Host-process tier enabled, with its isolation floor stated                                                                      |
| `host-process-inherited` | `CHECKFU_ENABLE_HOST_PROCESS_SANDBOX=true` already in your environment, with any artifact or flag | Same tier, same floor; the CLI pins the inherited answer and says the environment decided                                       |
| `host-process-declined`  | An effective host-process lane with `CHECKFU_ENABLE_HOST_PROCESS_SANDBOX=false`                   | No tier forced — the environment's answer was "no", which is a different outcome from enabling it                               |
| `docker`                 | `--sandbox docker` and inherited host-process authority is not `true`                             | Nothing forced; the container path appears only once a daemon and pinned relay are configured                                   |
| `none`                   | `--sandbox none` and inherited host-process authority is not `true`                               | Host-process disabled by the CLI; other explicit `CHECKFU_*` provider configuration still applies                               |
| `unset`                  | source checkout with no `--sandbox` and inherited host-process authority is not `true`            | Nothing forced; whatever other `CHECKFU_*` variables configure, which may be nothing — in which case the Runner fails to attach |

## Why host-process announces so loudly

The host-process tier exists because laptops without a container runtime are real, and
a Runner on a bare machine previously had nothing to offer. It is deliberately the
weakest tier Checkfu ships, and the design rule is that its weakness is **declared,
never implied**: the capability envelope advertises `network_isolation: false`, no
snapshots, `durable` retention only, and the `unrestricted` network mode alone, so
admission intersects the realized behavior rather than a label. The CLI states that
floor before the Runner attaches, and the Runner restates it on every boot.

Managed Runs still admit this provider only against exact conformance evidence for its
provider and materialization revisions, so an unconformed host-process Runner cannot
serve managed work regardless of what it advertises.

## The other default: your Runner key's enrollment ceiling

What a Runner advertises is only half the answer. Every Runner credential carries a
server-owned **enrollment** — the ceiling of what that key is allowed to run — and the
control plane admits the *intersection* of the two. A provider the Runner advertises but
the ceiling does not enroll is not available, no matter what the Runner claims.

A Runner API key minted **without an explicit enrollment gets the compatibility default,
which enrolls `checkfu-mock` and nothing else.** A Runner on such a key can advertise
Docker, E2B, and host-process and still run no real harness, because the intersection
admits only the mock. If the intersection is empty — the Runner advertises only real
providers and the ceiling enrolls only the mock — the Runner's presence announcement is
refused outright rather than accepted as a Runner that can never claim work.

This is why the two surfaces below are worth comparing rather than trusting one.

## Reading it for yourself

`checkfu doctor` lists the Workspace's live Runner presences, and
`GET /v1/runner-pools/presences` returns the same over HTTP: the providers, their
revisions, their network modes, and their runtime assurances, in advertisement order.

Read them as a pair:

* The Runner's own boot log (`checkfu.runner.sandbox_provider.advertised`) is what it
  **advertised** — what this machine can actually do.
* A presence record is what the control plane **admitted** — the advertisement already
  intersected with the credential's enrollment ceiling.

A provider in the boot log but missing from the presence record is a ceiling mismatch,
not a Runner problem: the key's enrollment does not cover it. Mint the credential with
the enrollment you intend rather than relying on the compatibility default.
