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

# Harnesses and models

> Choose the agent loop, model route, and sandbox an Agent uses.

Checkfu keeps three execution choices independent:

| Resource                | Chooses                                                                       |
| ----------------------- | ----------------------------------------------------------------------------- |
| **HarnessProfile**      | The agent loop: Claude Agent, Codex, pi, or another implementation            |
| **ModelCredential**     | One stable, rotatable provider credential identity                            |
| **ModelRoutingProfile** | A stable head whose immutable revisions publish routing policy and candidates |
| **SandboxProfile**      | The execution environment and resource limits                                 |

An Agent stores their logical names. Session admission resolves them to exact,
immutable versions, so changing a Workspace alias affects new Sessions without
changing existing ones.

If your Workspace already has all three names, you can stop here and use them in
an [Agent definition](/concepts/agents). The rest of this page is for people
configuring an execution stack or bringing a harness.

## Choose an adoption path

There are four HarnessProfile sources — `catalog`, `recipe`, `oci`, and
`release` — plus **ConnectedRuntime**, which enrolls an ACP process you already
run and creates no profile. The table below applies those paths to concrete harnesses.
`openclaw` is the only catalog entry carrying a published default image today, but the image is
not the same thing as readiness: the entry remains `blocked` until its signed readiness receipt
exists. Every other packaged entry is `image_required` and adopts through `recipe` with an image
you build.

`GET /v1/harness-catalog` lists every known entry with a `launch_role` (`primary`, `alternative`,
or `local_fixture`), a `mode` (`managed`, `packaged`, `custom`, or `connected`), and an
`availability` (`ready`, `image_required`, or `blocked`). Launch role states product intent;
availability states whether that entry can run. Checkfu's own `checkfu` entry is the sole product
primary, every other deployed entry is an explicitly selected alternative, and `checkfu-mock` is
a local/test fixture that is absent from the deployed catalog. Catalog order is never a default.
What each adapter may claim for nested children, teams, workflows, and native
transcripts is the [Session execution graph](/concepts/session-execution-graph#adapter-fidelity)
ceiling; a catalog seat does not invent collaboration.

The product may select a Harness without asking only when the unique primary is ready. Because
`checkfu` is currently `image_required`, the deployed product has no automatic Harness selection
today: choose a ready alternative or adopt an image explicitly. Local development may select its
unique ready fixture while the primary is unavailable; that behavior does not make the fixture a
production default or make the primary ready.

The Add harness profile form highlights the unique product primary as an
authoring convenience even while it is `image_required`, so you can provide the
missing digest. That is not a launch or catalog adoption: creating the profile
is still an explicit mutation, and malformed role data falls back to the generic
custom-image form instead of selecting another catalog row.

Catalog and HarnessRuntime reads accept `root`, `admin`, `developer`, and `viewer` keys. Creating
a HarnessRelease or HarnessProfile, publishing a new HarnessProfile version, and requesting
conformance require `root`, `admin`, or `developer`. Runner keys are data-plane credentials and
cannot browse these control-plane resources. Releases, profiles, versions, and conformance reports
are private to the selected Workspace; the catalog itself is the same platform-owned directory in
every Workspace.

The paths below are grouped by what you supply. The middle column is the `source.kind` you send
when creating a HarnessProfile, which is a separate vocabulary from the catalog's `mode`: a
`ready` packaged entry is adopted through `catalog`, while an `image_required` or `blocked` one
is adopted through `recipe`, which takes the entry name plus an image you supply by digest.

| Path                                                           | Profile source   | What you supply                                                                                                              |
| -------------------------------------------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| OpenClaw with a published image, awaiting signed readiness     | `recipe`         | A digest-pinned image; its catalog default remains blocked until the readiness receipt exists                                |
| OpenCode, stock Pi, Hermes, Claude Agent, or Codex             | `recipe`         | A digest-pinned image built from the exact generic Vercel cohort recipe (`pnpm vercel-harness-image:build --harness <name>`) |
| First-party Checkfu harness awaiting a published default image | `recipe`         | A digest-pinned image built from the checked-in `apps/harness` source (`pnpm harness-images:build checkfu`)                  |
| Cursor, organization-build-only                                | `recipe`         | The same generic Vercel workload built with the exact Cursor recipe; Checkfu does not publish its proprietary runtime        |
| Completely custom CLI or ACP harness                           | `oci`            | The image plus a one-shot or ACP command; Checkfu creates the release and profile together                                   |
| Shared immutable release                                       | `release`        | An existing HarnessRelease ID and its exact driver                                                                           |
| Existing OpenClaw, Hermes, or proprietary ACP process          | ConnectedRuntime | An Agent plus the local ACP command; no image or inbound endpoint                                                            |

On every managed path above, the harness loop runs inside the Run's sandbox for the whole turn.
The [brain plane](/concepts/brain-plane) is a separate split topology that runs the loop on the
worker plane and summons a sandbox only when a command needs one. It is not admissible in
production today.

<Warning>
  The Checkfu CLI has no self-service public installation channel during private
  alpha. CLI examples on this page assume access through an explicitly authorized
  alpha arrangement. See [CLI access in private alpha](/getting-started/cli-access)
  for the source-checkout and HTTP alternatives.
</Warning>

`checkfu:oneshot-v1@1` is the universal floor every harness can reach: prompt through stdin or
an argv-named file, one process per turn, process exit is completion, and disk state restored
from the turn-boundary Checkpoint. ACP is the enrichment lane above it, and the namespaced
[checkfu ACP extensions](/concepts/harness-extensions) enrich ACP in turn.
`checkfu:acp-v1@1` buys richer events and lifecycle behavior, but nothing above the floor is
required for governance, wire evidence, or usage authority. Customer code and protocol shims stay
inside the sandbox; the trusted Runner never imports a customer package.

The private-alpha CLI command surface includes both the developer scaffold installer and the
outbound connector supervisor. Contributors run it from a source checkout as
`pnpm exec checkfu`; no packaged customer distribution is implied.

### What the one-shot floor cannot do

The floor's limits are structural, not gaps waiting to be filled. One-shot invocations run with
the CLI's own permission prompts bypassed, so mid-run [ActionApprovals](/concepts/action-approvals) are
impossible there. The control that replaces them is the admitted sandbox posture, read-only
versus writable. Interrupting means killing the process. There are no streaming deltas unless the
CLI itself emits stream-JSON, so a one-shot Run reports `event_fidelity: "minimal"` in its
capability set. Choose an enrichment lane when you need any of those; choose the floor when you
have a CLI and want it governed today.

A `oneshot-v1` release declares how its command is assembled:

| Field                     | Meaning                                                                                                                                |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `argv`                    | The command arguments, in place of the ACP variant's `arguments`. Only `{prompt_path}` and `{resume_flag}` may appear as placeholders  |
| `prompt_transport`        | `stdin` or `argv_path`: how the turn's prompt reaches the process                                                                      |
| `output_mode`             | `stream_json` or `text`                                                                                                                |
| `resume_flag`             | Optional flag that continues the previous turn, substituted at `{resume_flag}`                                                         |
| `output_schema_flag`      | Optional flag that requests typed output                                                                                               |
| `output_schema_transport` | `argv_json` or `argv_path`: whether that flag takes inline JSON or a schema file path. Checkfu never guesses this from the flag's name |

### Stock Pi through Vercel's maintained adapter

The `pi` catalog entry uses Vercel's maintained HarnessAgent adapter inside
Checkfu's one generic named-vendor workload. The image lock pins the stock Pi
package and the complete adapter/runtime closure; Checkfu carries no Pi fork or
second protocol implementation. The entry stays `image_required` until a
published image earns a signed readiness receipt. Build it with
`pnpm vercel-harness-image:build --harness pi`.

### Cursor owns its own model plane

The `cursor` entry uses Vercel's maintained Cursor adapter and drives Cursor's
local agent inside the sandbox against `/workspace`. Cursor authenticates to
its own backend and exposes no Checkfu model-gateway route, so the catalog
declares `model_control: harness_owned` and `usage_authority: unknown`.
Checkfu cannot meter or budget model traffic it never observes.

The customer-owned Runner supplies the Cursor login and exact model selection.
Admission requires the server-authored Cursor release marker plus a live Runner
advertisement matching profile revision, release digest, provider, and model;
the generic entrypoint alone grants nothing. Cursor remains
organization-build-only because its runtime is proprietary. Build it with
`pnpm vercel-harness-image:build --harness cursor`.

### The first-party checkfu harness

The `checkfu` entry is Checkfu's own harness: pi's agent libraries wrapped in
a Checkfu-authored ACP server with externally escrowed same-Run recovery,
native steering, cooperative interrupt, governed subagents, structural tool
completion evidence, and per-turn execution telemetry. It remains a normal
catalog citizen behind the same ACP driver and conformance vocabulary.

Its independent build context is `apps/harness`, not the Vercel workload.
Build and contract-verify it with `pnpm harness-images:build checkfu`. The
entry remains `image_required` until an exact published image earns the
ordinary signed readiness receipt.

### Claude Agent via the Claude Agent SDK shim

The stable catalog id `claude-code` now uses Vercel's maintained Claude Agent
HarnessAgent adapter in the generic workload. Checkfu owns the sandbox, ACP
trust boundary, policy compilation, and durable event-log lifecycle; Vercel
owns the vendor SDK mapping. The entry keeps its evidence-bounded capability
ceiling and remains `image_required`. Build it with
`pnpm vercel-harness-image:build --harness claude-code`.

### Codex through its app-server

The `codex` entry uses Vercel's maintained Codex HarnessAgent adapter, which
drives the pinned Codex app-server surface inside the same generic workload.
There is no Checkfu-authored Codex protocol server or fallback implementation.
The entry remains `image_required` until publication and exact signed
readiness. Build it with `pnpm vercel-harness-image:build --harness codex`.

### OpenCode through Vercel's maintained adapter

The `opencode` entry uses Vercel's maintained OpenCode adapter and the same
generic image boundary. Exact adapter and runtime pins come from the coherent
Vercel cohort; availability and support still come only from publication and
signed tuple evidence. Build it with
`pnpm vercel-harness-image:build --harness opencode`.

### Hermes uses its reviewed ACP adapter

The `hermes` entry uses Vercel's ACP-backed HarnessAgent adapter over the
exact frozen Hermes source/runtime closure. Checkfu no longer maintains a
separate Hermes protocol bridge. Build the organization image with
`pnpm vercel-harness-image:build --harness hermes`; the entry remains
`image_required` until an exact published digest is qualified.

Readiness and the published image are inseparable in the schema. A `ready`
entry always names the exact image it resolves to; an `image_required` entry
has no `default_image`, and recipe adoption supplies a digest-pinned image.

### Managed OpenClaw and an existing Gateway are different modes

The `openclaw` image contract starts an ephemeral, loopback-only OpenClaw Gateway and its ACP
bridge together inside the Checkfu sandbox. The Gateway's internal token is minted inside that
sandbox, and model requests go only through the short-lived Checkfu model plane. A compatible
digest-pinned image therefore uses ordinary Runner, sandbox, conformance, and cleanup evidence.
The catalog entry carries a Checkfu-published `default_image`, but it is still `blocked` with
`missing_evidence: "signed_readiness_receipt"`; a published digest alone does not make a harness
qualified. Adopt an explicitly supplied digest through `recipe`, or run
`checkfu harness init openclaw` when you need a customized build. Catalog adoption becomes
available only after the signed receipt promotes the entry to `ready`.

OpenClaw's `openclaw acp` command can also bridge to an existing operator-owned Gateway. That
command can be exercised through the connected-ACP alpha path, but the curated
`openclaw-connected` entry stays `blocked`, reporting `missing_plane: "upstream_acp_conformance"`,
until a pinned OpenClaw revision passes the black-box connector journey. `checkfu harness connect --agent <agent-id> --principal <principal-id> -- openclaw acp` enrolls the runtime and supervises the
ACP child through outbound HTTPS only, then prints the exact `session chat` command to use.

The Gateway's own configuration and credential stay with the operator-owned OpenClaw process.
Checkfu never turns them into HarnessProfile configuration or injects them into a managed
sandbox. Connected execution shares the Session event stream but makes no Runner, sandbox,
conformance, model-control, or platform-usage claim. The same supervisor accepts an
always-on Hermes process or proprietary ACP harness through the same ACP boundary.

Interrupt is cooperative in this operator-owned mode. Checkfu sends ACP cancel, replaces the
supervised ACP process after a bounded grace, and rejects every later gateway write. It cannot
claim process-kill authority over a separate customer daemon that ignores ACP.

The connected-ACP **Private alpha** carries instructions, retained conversation, and catalog
tools. Tool calls do not cross ACP: each Connection in the frozen admission roster is delivered
as a platform MCP server authenticated by the claim's short-lived gateway bearer, so the same
policy, approval, custody, budget, and audit path governs connected and managed calls. A
tool-bearing version fails closed when no executable Connection is released or the ACP client does
not advertise HTTP MCP support. Injected skills, output schemas, and attachments remain
unsupported; the connector rejects those richer turns before starting the harness. Use packaged
or custom OCI execution when those semantics are required. ACP permission requests are still
cancelled because they concern operator-owned local harness actions, outside Checkfu's governed
platform-tool boundary.

An interactive turn or Automation selects a ConnectedRuntime explicitly; Checkfu never silently
reroutes managed work based on presence. Under standard retention, an Automation submitted while
that process is offline stays queued and is delivered after reconnect. Under ZDR it fails closed
instead of retaining execution content. Leaving the target unset starts a fresh managed Sandbox
for each firing.

<Warning>
  A ConnectedRuntime is not a customer-VPC Runner. It supervises one operator-owned ACP process and carries none of the managed Runner's Sandbox, isolation, model-control, usage-authority, or cleanup claims. Customer-operated Runner deployment has a distinct `customer_runner` topology and must be read through [capability status](/getting-started/status); Checkfu does not yet publish a supported AWS, GCP, or Kubernetes deployment package.
</Warning>

### What a connected runtime realizes

Connecting your own process is not the managed lane at a different address. Checkfu
publishes one capability ceiling for the connected topology and returns it to your
connector on every claim, so what the lane can do is a value you can read rather than a
tier you have to infer. Of the 34 runtime capabilities a Run can require, a connected
runtime realizes six:

| Capability                  | What you get                                                |
| --------------------------- | ----------------------------------------------------------- |
| `input.text`                | The turn's user message reaches your harness                |
| `observation.user_message`  | Agent messages land in the Session log                      |
| `observation.progress`      | Thinking and context-compaction observations are normalized |
| `observation.tool_activity` | Tool use and tool results are normalized                    |
| `control.interrupt`         | Cooperative cancel, as described above                      |
| `lifecycle.cancel`          | Checkfu ends the Run and fences every later gateway write   |

Releasing an executable Connection adds exactly three more — `gateways.platform_tools`,
`gateways.credential_proxy`, and `accounting.tool_usage` — because those are the surfaces
platform MCP actually carries. Nothing else promotes: a control-MCP grant is a delivery
surface, not evidence, so the published ceiling is identical with and without it.

The remaining capabilities are unsupported, and each absence follows from who owns the
process rather than from work not yet done:

* **Nothing about the model is enforceable.** Your process holds its own model
  credential and calls the provider directly, so `gateways.platform_model` and
  `accounting.model_usage` have no server-observed fact behind them. Model routing,
  fallback, budgets denominated in model spend, and platform model billing are managed-lane
  features. A signed observation batch attests what your connector *reported*; it cannot
  attest what your process *did*.
* **Nothing about the machine is attestable.** `isolation.network`,
  `accounting.compute_usage`, `lifecycle.bounded_start`, and `lifecycle.orphan_recovery`
  are properties of a sandbox Checkfu provisions. There is no sandbox here, so there is no
  network policy, no compute metering, no start deadline, and no way to recover a runtime
  that vanished mid-turn.
* **Zero data retention is unavailable.** ZDR requires a live Runner slot Checkfu can
  fence and destroy. A connected Run under a `zdr` Workspace fails closed rather than
  admitting a lane whose retention Checkfu cannot bound. See
  [the retention model](/concepts/tenancy-and-governance#retention-model).
* **The platform cannot park a connected turn.** ActionApproval continuation, Questions,
  and custom-tool declarations work by parking a running Run and resuming
  it with the answer. Stock ACP has no verb for that and no way to attribute a completion
  to a specific prompt (D159), so `control.action_approval_continuation`,
  `control.question_yield`, `control.custom_tool_declaration`,
  `control.custom_tool_continuation`, and `control.steer` are all unsupported.
  Persistent thread spawn/message controls are also unsupported because the connected
  agent has no Session-scoped control-MCP delivery surface. Governance
  itself still runs: a platform tool call that needs review returns an `approval_required`
  result carrying the ActionApproval id, and the harness repeats the identical call once a human
  decides. Steering an in-flight connected turn is promoted into the next Run rather than
  delivered mid-turn.
* **Checkpoints are not the mechanism.** The connected topology's continuation grade is
  `live`: your process holds its own state and resumes it by owning it. That is a
  different guarantee from a Checkfu Checkpoint, so `continuity.checkpoint_export` and
  `continuity.checkpoint_import` stay unsupported and Checkpoints are a managed-lane
  feature.
* **Files and richer inputs do not cross.** `input.structured`, `input.files`,
  `input.attachments`, `resources.filesystem`, `resources.project_memory_mounts`, and
  `resources.artifacts` all need a filesystem Checkfu staged. Injected skills and output
  schemas are rejected before the harness starts.
* **Two observation grades stay unproven.** Your connector may report subagent lifecycle
  batches and they land in the log, but `observation.subagents` derives from a declared
  capability axis a connected runtime cannot claim, and `observation.diagnostics` has no
  executable case on this lane. Neither is an admitted capability, so a Run that requires
  one cannot use this lane. Ordinary messages, thinking, and tool activity are unaffected.

What is genuinely the same on both lanes: the Session event log, PermissionAssignments and ActionPolicies,
the ActionApproval decision on a platform tool call, Connection custody and egress rules, audit
records, and the API surface you drive it all through.

### Attesting what a connected runtime reported

Because the process is yours, Checkfu cannot vouch for what it sends by watching it. A connector
can instead sign what it reports. Register an Ed25519 public key when you create or enroll the
ConnectedRuntime, and the owning Session verifies each signed observation batch: the new event
envelopes then carry `attested: true`. Unsigned batches still land, just without that grade.

The detached signature binds the runtime, Session, Run, current key version, producer sequence,
and the RFC 8785-canonicalized observations, so one signature is valid only for the exact Run and
position it was produced for. Rotate the public key together with the connector token by supplying
`attestation_key` to `POST /v1/connected-runtimes/{id}/token`. The new generation applies to
later batches, and the private key never enters Checkfu.

## Diagnose managed Runner capacity

The **Harnesses → Runner capacity** inventory shows every unexpired RunnerGeneration visible to
the Workspace. Its summary totals the slots advertised by unexpired `ready` generations. Here,
`ready` means the live Runner process generation is announcing presence; it does not establish
that any particular Harness target is ready. Inspect a generation to see its RunnerPool and
placement, exact driver versions, provider and materialization revisions, sandbox capability
envelope, model/tool plane protocols, and heartbeat expiry.

This is operational evidence, not an admission promise. Presence cannot prove conformance, claim
work, or satisfy ZDR live custody. Under D168 a host Harness target can remain unready while its
Runner generation announces ready presence; a claim against that target fails fast with its
structured readiness reason. A concrete managed Run still intersects its immutable RunSpec, the
Runner enrollment ceiling, current ConformanceReport, provider capacity, and governance before the
control plane fixes one ExecutionTarget and mints a Session-owned lease. An expired presence is
displayed as offline if it remains in a browser's retained projection; refresh removes it from the
server inventory.

## Bring an arbitrary harness in one request

The image must be pinned by digest; tags are rejected. At the declared entrypoint it speaks
either ACP v1 over stdin/stdout or the one-shot protocol, whichever the release declares. The
hosted sandbox target accepts Debian-derived `linux/amd64` OCI images; local development against
your own container runtime is the broader Linux OCI proof.
Use `checkfu harness add oci --name <name> --image <name@sha256:...> --entrypoint <path>`;
`--arg`, `--platform`, `--working-directory`, `--configuration`, and
`--configuration-schema` expose the complete arbitrary-image contract. Configuration is
deliberately non-secret; never place model keys, gateway tokens, or other credentials in it.
The equivalent typed HTTP request is:

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --request POST https://api.checkfu.com/v1/harness-profiles \
    --header "Authorization: Bearer $CHECKFU_API_KEY" \
    --header "Checkfu-Version: 2026-08-29" \
    --header "Idempotency-Key: $(uuidgen)" \
    --header "Content-Type: application/json" \
    --data '{
      "name": "claims-specialist",
      "source": {
        "kind": "oci",
        "release": {
          "image": "ghcr.io/acme/claims-agent@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
          "entrypoint": "/opt/agent/acp",
          "arguments": ["--stdio"],
          "working_directory": "/workspace",
          "platform": { "os": "linux", "architecture": "amd64" },
          "configuration_schema": {
            "type": "object",
            "properties": { "industry": { "type": "string" } },
            "required": ["industry"],
            "additionalProperties": false
          }
        }
      },
      "configuration": { "industry": "insurance" }
    }'
  ```

  ```ts TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const profile = await checkfu.harnessRuntime.profiles.create(
    {
      name: "claims-specialist",
      source: {
        kind: "oci",
        release: {
          image:
            "ghcr.io/acme/claims-agent@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
          entrypoint: "/opt/agent/acp",
          arguments: ["--stdio"],
          working_directory: "/workspace",
          platform: { os: "linux", architecture: "amd64" },
          configuration_schema: {
            type: "object",
            properties: { industry: { type: "string" } },
            required: ["industry"],
            additionalProperties: false,
          },
        },
      },
      configuration: { industry: "insurance" },
    },
    { idempotencyKey: crypto.randomUUID() },
  )
  ```
</CodeGroup>

Configuration is public, validated against the release schema, and never a secret field.
Model provider keys remain in Checkfu's credential vault. A short-lived Run token lets the
harness call the model plane; the plane chooses the pinned provider/model and attaches the raw
provider credential at the outbound edge.

## Capability evidence and conformance

Catalog capability data is a ceiling: the strongest semantics an integration could realize.
An OCI profile begins unverified. Requesting verification resolves the selected profile,
sandbox, and model names server-side and queues a conformance Run. Normal Runs stay blocked
until a passing **ConformanceReport** exists for that exact release, driver, sandbox image,
model routing profile revision, policy, and suite revision. Passing evidence expires 30 days after the
server observes completion; after that ceiling the exact tuple must be verified again before
normal Runs can use it.

The report records actual event fidelity, continuation, checkpoint, approval, interrupt,
mid-run input, model-control, and usage-authority semantics. Changing any tuple member or reaching
the report's expiry invalidates the evidence instead of silently carrying an old compatibility
claim forward. Newly completed reports expose an `evidence_manifest_revision` and
`evidence_manifest_hash` over the exact server-interpreted evidence, audit actors, and validity
window. Checkfu uses the stored revision to recompute this digest before serving terminal evidence;
predecessor reports remain visibly unhashed until they expire.

### Compatibility is the set of current exact reports

Checkfu does not infer a support matrix from catalog membership, harness name, or model provider.
Each unexpired passing ConformanceReport is one compatibility cell: the exact HarnessProfile
version, release digest, driver, sandbox image, ModelRoutingProfile revision, policy hash, suite revision,
target, and qualification it records. The compiler admits that cell and refuses a normal Run when
no matching report exists. A new model route, image, driver, sandbox, or policy therefore requires
fresh evidence; compatibility never spreads to a neighboring cross-product by implication.

The repository contains two narrower engineering proofs that do not promote hosted support:
the same normalized Runner scenario executes local source-built Claude Agent and Codex images, and
the same model-plane request contract routes through exact OpenAI and Google AI Studio profiles
while provider credentials remain at the outbound host edge. Neither proof is a paid-provider
receipt or a hosted qualification. Product support remains exactly the cells represented by
current deployment ConformanceReports.

There is one thing Checkfu now publishes *below* support: which harnesses and model providers
can physically speak to each other at all. That is the wire dialect a harness knows — a harness
that only speaks Anthropic's `/v1/messages` cannot drive an OpenAI-compatible route regardless of
its model routing profile — and it is declared data with a
[generated reachability matrix](/concepts/harness-extensions#which-harnesses-can-reach-which-model-providers).
Read it as a necessary condition and nothing more: a reachable cell says the wire fits, never
that the tuple is supported.

### Proving tool delivery at the execution locus

A verification request may opt in to one additional server-computed check by sending
`prove_platform_mcp: true` on `POST /v1/harness-profiles/{id}/verifications` (CLI:
`checkfu harness verify <profile> --prove-platform-mcp`). The flag defaults to off, so existing
tuples and harnesses that never call platform tools are untouched.

An opted-in conformance Run carries one platform-owned MCP server (provider `checkfu`) alongside
the model-plane grant. That surface serves `initialize`, `ping`, `tools/list`, and a single
platform-authored `checkfu_conformance_probe` tool under a bounded per-claim budget. When the
harness reaches it from inside the sandbox and the probe is served at least once, the completed
report carries a passing `capability_execution_locus` check computed from Checkfu's own
served-call record — never from harness- or runner-asserted evidence. A harness that reports tool
activity while the platform served nothing fails this check: that is exactly the shape of a
harness whose tools execute outside the sandbox network (for example through a vendor-hosted
gateway daemon), which grammar checks alone cannot detect.

Requesting the opt-in requires a Runner enrolled with the `platform-mcp-v1` plane protocol; when
enrolled Runners exist and none declares that plane, the verification is refused immediately with
the remedy instead of waiting unclaimed. What the check proves is reachability of the platform
MCP surface from the tool execution locus; the full CapabilityGateway path (connections, policy,
ToolInvocation fencing) is exercised only by a real Session-backed Run.

<Note>
  A passing locus check does not by itself mean tools flow on the Session lane in a deployment.
  Session-backed Runs receive their platform-MCP grant only when the deployment declares its public
  hostname (the `CHECKFU_PUBLIC_HOSTNAME` deployment variable, which also pins the model-plane
  origin); until an operator sets it, deployed managed Runs receive no MCP servers even though
  conformance can prove locus reachability.
</Note>

## Model routing profiles

An Agent refers to a logical **ModelRoutingProfile**, not a hardcoded provider credential. The
profile head is stable identity and lifecycle; each explicit publish creates an immutable revision
containing the candidate ladder, routing policy, and credential-source choices. Most profiles are
`platform_routed`: omit `access` (or send `platform_routed`) when creating the head. When platform
supply is enabled, Checkfu provisions one credential-free starter profile instead.

```json POST /v1/organizations/workspaces/{workspace_id}/model-credentials theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "key": "anthropic-primary",
  "provider_key": "anthropic",
  "api_key": "sk-ant-…"
}
```

The secret is write-only. Create the profile head separately, then publish revision 1 using the
returned credential ID and the head's `resource_version`.

```json POST /v1/organizations/workspaces/{workspace_id}/model-routing-profiles theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "key": "primary" }
```

```json POST /v1/model-routing-profiles/{id}/revisions theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "expected_resource_version": 1,
  "routing_policy": "fallback",
  "candidates": [
    {
      "tier": "default",
      "provider": "anthropic",
      "model": "claude-sonnet-4-5",
      "credential_source": {
        "type": "workspace_credential",
        "model_credential_id": "mcred_…"
      }
    }
  ]
}
```

Rotate with `POST /v1/model-credentials/{model_credential_id}/generations`, sending the current
`expected_resource_version` and a new `api_key`. Revoke with
`DELETE /v1/model-credentials/{model_credential_id}` and the same optimistic fence. Neither action
rewrites a ModelRoutingProfileRevision; dispatch resolves and records the exact live generation.

A harness that already owns an end user's model subscription can instead use the explicit
`harness_owned` lane. Its head creation request sets `"access": "harness_owned"`; every candidate
in its published revision uses `{ "type": "harness_owned" }` as `credential_source`. Checkfu stores
no ModelCredential or platform-provider selector. Admission
then requires a live customer-owned Runner whose immutable enrollment and current advertisement
both declare one exact, non-secret capability: pinned HarnessProfile version, HarnessRelease
digest, provider, and model. The exact Vercel Cursor recipe is the sole current implementation. Generic
ACP harnesses cannot opt in merely by setting the access field.

Session creation validates one closed model-access lane together with the selected Agent Version,
Environment, and harness evidence:

| Access lane       | Model selection | Credential custody  | Routing  | Wire provenance     | Usage evidence      |
| ----------------- | --------------- | ------------------- | -------- | ------------------- | ------------------- |
| `platform_routed` | platform        | platform            | platform | `platform_observed` | `platform_observed` |
| `harness_owned`   | harness         | harness environment | harness  | `absent`            | `absent`            |

The fields are one structural union, so a hybrid such as `harness_owned` plus platform routing is
invalid. An unschedulable exact pair is rejected by Session creation with the corresponding
admission error. Automation admission, SessionThread admission, and final release freezing enforce
the same gate.

The `portable_core` experience profile is neutral to these two lanes. It describes text input,
user-message observation, compute accounting, and bounded lifecycle. A platform-routed Run adds
the platform-model and observed-model-usage requirements from its actual configuration; a
harness-owned Run does not pretend Checkfu has evidence it explicitly lacks.

For Cursor, the credential is process-local Runner configuration. It is injected only into the
exact matched Cursor container on a BYOC Docker placement; it cannot appear in the ModelRoutingProfile,
Runner enrollment or presence, RunSpec, plane grant, claim receipt, API response, or hosted
execution plane. The claim's structural `access: harness_owned` grant variant cannot represent a
platform model URL or bearer. A wrong pool, hosted placement, stale profile or release pin,
different model, missing local login, or restricted network therefore refuses before execution.
See [Enroll an exact Cursor login](/getting-started/local-agents#enroll-an-exact-cursor-login)
for the exact enrollment and local configuration.

On an admitted harness-owned Session, `session.admitted` records `usage_evidence: absent`.
The Runner cannot begin or record a platform model call, and Checkfu emits no model UsageLedger
entry—no zero-filled estimate, model token total, model spend, or model-Budget consumption.
Sandbox compute and retention measurements remain independent and continue to be recorded.

Each candidate carries a `tier` (`default`, `planning`, or `tool_loop`), a `provider`, a `model`, a strict `credential_source`, and an optional `effort` over one closed scale (`minimal`, `low`, `medium`, `high`, `max`). The source is exactly one Workspace ModelCredential, an eligible platform provider, or `harness_owned`; nullable hybrids are rejected. Candidates that share a provider must share that exact source, so several tiers or fallback choices cannot silently select different credentials for one provider. When declared, the model gateway translates the effort into the exact provider parameter before dispatch — `reasoning_effort` on OpenAI-compatible surfaces, a `thinking` budget on Anthropic messages — so one knob applies identically under every harness, and the translated request is exactly what the retained model wire records. A provider with no mapping is a visible no-op, never a silent guess; absent means the provider default. Because the knob is per candidate, one profile can run its `planning` tier at `high` and its `tool_loop` tier at `low`. `routing_policy` is one of `cheapest_sufficient`, `pinned`, or `fallback`, and the three genuinely differ. `pinned` runs the first candidate you listed for the requested tier. `cheapest_sufficient` runs the cheapest of them by Checkfu's reviewed price catalog — every candidate you list under a tier is one you have declared sufficient for it, so Checkfu picks the least expensive of your own choices and never promotes a model you did not list. A candidate Checkfu has no reviewed price for is ordered after the priced ones rather than assumed cheap, and if none of them is priced the policy falls back to your order unchanged. The comparison is made once, when admission freezes the release, so a price change cannot reroute a Session that is already running. `fallback` is the only policy that may try a later candidate, and only after a typed provider failure. ModelCredential and generation reads are secret-free; `api_key` never appears after its write request.

### Which models can you list as candidates?

`GET /v1/models` returns the reviewed models the model gateway can route, so a model picker never
hardcodes provider strings. Each entry carries its `provider`, `model`, admitted
`context_window` in tokens, whether it is `priced`, and a `supply_class` — `platform_supply`
only where an admissible platform adapter sits behind the route, and `byok` for every other
priced route, which needs a Workspace credential for that provider. It is a single bounded
`data` array with no pagination, derived from the reviewed price catalog and the wired
context-window table.

It is a projection, not a second authority, and the boundary is worth knowing in both
directions. A model absent from the list is exactly the one admission refuses as
`unpriced_model` when a model-spend budget must admit it — but it is still schedulable with
your own key: it is simply unpriced, and its context window falls back to the industry floor.

ModelRoutingProfile and ModelCredential reads accept `root`, `admin`, `developer`, and `viewer`;
creation and updates require `root`, `admin`, or `developer`. Runner keys are data-plane credentials
and cannot browse either registry. Both resources are private to the selected Workspace, and a
foreign ID is indistinguishable from a missing ID. A ModelCredential read exposes its stable identity,
logical key, provider, public base URL, custody policy, status, health, and active generation number.
It never returns the submitted API key or an internal vault locator. A ModelRoutingProfile head contains
only identity and lifecycle state; its immutable revisions contain explicit, secret-free credential-source
policy.

There is no implicit matching-key override. To change credential authority, publish a new profile revision:
use `workspace_credential` with a ModelCredential ID for Workspace-owned BYOK,
`platform_provider` with its provider key and `eligible_at_admission` policy for platform supply, or
`harness_owned` only for a harness-owned profile. A rejected or revoked Workspace credential fails
closed; routing never silently falls back to Checkfu's provider account. At Run admission, the execution
release freezes the exact Workspace credential generation ID while remaining secret-free.

Workspace policy always wins. If every candidate violates a provider constraint, routing fails closed with `model.no_eligible_model`.

## The version a Session runs is fixed at admission

A [Session](/concepts/sessions-and-runs)'s AgentDeploymentRevision — and with it the Agent
release, harness, ModelRoutingProfile, and sandbox — is resolved once at admission and frozen for the
Session's whole life:
[Two freeze horizons](/concepts/sessions-and-runs#two-freeze-horizons). Workloads that need a
specific revision regardless of later publishes can pin one with
`agent_deployment_revision_number: N` on Session create, or with a reusable
`agent_deployment_revision_selection: { "type": "pinned", "revision_number": N }` on a Session
template, Automation target, or AgentPlacement.

## Next steps

<CardGroup cols={2}>
  <Card title="Tenancy and governance" icon="shield" href="/concepts/tenancy-and-governance">
    How Workspace policy, PermissionAssignments, and Principals bound what a ModelRoutingProfile is allowed to route to.
  </Card>

  <Card title="Sessions and runs" icon="play" href="/concepts/sessions-and-runs">
    How a Session pins or tracks Agent deployment revisions and records each Run as events.
  </Card>
</CardGroup>
