Skip to main content
Nothing in the public API names a sandbox provider. A Session names a SandboxProfile — 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:
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

--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. 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

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. 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 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.

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.