acp-v1 extension schema and golden wire vectors provide machine-readable wire contracts. Use the artifacts matching your release. They describe protocol support; the exact release’s signed conformance report and the deployment’s capability status determine which capabilities you can use.
The server.mjs excerpts explain the protocol scaffold; connect it to your own agent’s tools and execution loop. Use the scaffold supplied by the authorized alpha CLI to start your own implementation; no Checkfu source checkout is required. See CLI access for artifact access and authentication.
Start from a scaffold
Use this path when your company owns the harness implementation. To use an official harness, select its named profile instead; you do not need to author a custom recipe. A catalog entry markedimage_required still needs a
qualified image and is not a ready-to-run default. See capability
status for availability.
checkfu harness init acp writes a minimal ACP starter and image packaging:
loadSession: false and does not declare or connect MCP tools.
The protocol examples below come from that maintained CLI template. Implement
the tool connection in your agent before declaring MCP delivery or the
corresponding capability.
Connect the starter to your domain implementation and declare only the capabilities it supports. Pass oneshot for the one-shot image contract. An existing ACP executable can use a recipe that installs and launches it; it does not need a TypeScript rewrite or Vercel dependency in its own implementation.
The wire: JSON-RPC over stdio
A harness is a process. The Runner launches it inside the sandbox, writes newline-delimited JSON-RPC 2.0 to its stdin, and reads the same framing from its stdout. Stderr is yours for logging. The starter uses the official ACP SDK for framing and request dispatch rather than maintaining a separate JSON-RPC server. Its input drain keeps the SDK connection open until an accepted turn has settled:path=apps/cli/templates/acp/server.mjs
initialize: declare only what you serve
The first request is initialize. The response names your protocol version and capabilities:
path=apps/cli/templates/acp/server.mjs
mcpCapabilities: { http: true } and the matching recipe delivery. Richer harnesses may implement
Checkfu’s namespaced extensions; see the declaration
handshake. Qualify each
implemented capability on the exact release before relying on it.
Declare only what your implementation serves. A declaration is not proof: only server-issued, signed conformance evidence realizes a capability. Inspect the exact report’s checks and admitted capability matrix before configuring a Session. A check marked unsupported, skipped or failed does not realize that capability; some surfaces have no executable qualification case yet. Registration or a passing base protocol check does not make those surfaces available. A Session requesting an unproven capability is refused rather than given a substitute.
Session and turn lifecycle
session/new opens one process-local session. The starter refuses MCP servers
and additional directories rather than pretending to connect them:
path=apps/cli/templates/acp/server.mjs
session/prompt streams the model answer through session/update and returns
its native stop reason:
path=apps/cli/templates/acp/server.mjs
conversation.event_cursor, conversation.history, and the current input.
The starter forwards that text to the model; it does not maintain its own
conversation store. On an ordinary subsequent Run, Checkfu rebuilds the envelope
from retained Session context. Reloading the console reads that retained history;
it does not restore an agent process. A supported native checkpoint is a separate
recovery path and must avoid replaying history already present in restored state.
Qualify the complete agent journey
Before adopting a release, exercise your actual agent implementation through the Session path you intend to support:- Complete useful work with a real native tool or granted MCP tool, and inspect the recorded tool result as well as the final response.
- Start a subsequent Run in the same Session and check the context your agent
actually retains. A successful first turn does not prove continuation. The
scaffold above declares
loadSession: false; connect and qualify your own state handling before advertising restoration. - Cancel while work is in flight. A cooperative ACP implementation handles
session/cancel, stops its pending work, and settles the prompt. Check both the terminal outcome and any tool side effects. A cancellation acknowledgement does not prove that effects were undone or an upstream provider request terminated; a notification alone does not prove that execution stopped. - Exercise a known provider refusal, then submit a valid fresh prompt through your release’s supported retry path. Check the failed Run’s recorded outcome, the next Run’s useful result, and the absence of credentials in errors or diagnostics. Pinned BYOK refusal must not switch to paid managed tokens. A successful retry does not establish native checkpoint restoration or reverse effects from the failed attempt. If a request, tool effect, cancellation, or custody callback has an uncertain outcome, retain its original operation and use only the release’s supported reconciliation path. Do not create a new operation or reopen the native owner to repeat an effect whose outcome is unknown; a joined or closed local process does not establish rollback.
- Exercise recovery only for the mechanisms your release supports. An externally
custodied native checkpoint must be exported and imported through the declared
Checkfu extensions. Native restore requires nonempty, bounded native state.
The wire value
same_run_resumealso covers completed conversation state carried into a later Run of the same frozen Session; its name does not require the same Checkfu Run ID. Pending approvals require their exact admitted continuation, rather than an unrelated new input. Keep that state outside agent-readable files, and do not put provider credentials in it.
portable_native_checkpoint: false on a recipe whose state cannot cross this
boundary. BYOH recipes omit external checkpoint custody by default. Set
portable_native_checkpoint: true only after qualifying native state across
fresh processes, replacement sandbox filesystems, and MCP credentials. If the
upstream state refers to private files, retain those files through a supported
filesystem recovery path or carry and restore their required contents in the
checkpoint. A restart against the old filesystem does not prove recovery after
sandbox replacement. Same-Run restoration with its original admitted
configuration is a separate qualification.
Select recovery support from the exact admitted release and its qualified
capabilities. A protocol integration or an upstream conversation identifier does
not establish checkpoint support. Checkfu’s current Pi coding and generic ACP
guest adapters refuse restored transport state; Cursor’s protocol helper does
not establish native restoration. Their source integration is not a portable
recovery offering. For a custom harness that keeps history in sandbox-local
files, qualify a supported file-restoration path before advertising recovery in
a replacement sandbox. A retained filename alone does not restore its contents.
The shared adapter refuses checkpoint export, checkpoint import, and native
approval or question parking when initialize does not declare
checkfu.capabilities.native_checkpoint: "external_custody". It returns ACP
invalid params (-32602) with data.reason: "native_checkpoint_unsupported".
That refusal does not establish a checkpoint or a restored Session. Explicit
recipe opt-in supplies the declaration; conformance must still qualify the
release before Checkfu admits the capability.
Use the capability matrix to record unsupported
continuation, interruption or checkpoint behavior explicitly. Source support,
passing local protocol cases, a qualified packaged image and hosted availability
are separate results. Keep the tested release digest and profile version with
your receipts; rebuilding or changing the profile requires qualifying the
changed inputs.
The governed model plane arrives in the environment
This scaffold uses Checkfu’s governed model plane. On this path, the harness receives a scoped gateway token; Checkfu keeps the provider credential outside the workload. Routing, budget enforcement, and platform-observed model usage apply to calls through that gateway. The sandbox environment carriesCHECKFU_MODEL_BASE_URL and CHECKFU_MODEL_TOKEN — the platform-neutral names, and the ones to prefer in new code — pointing at the governed model gateway. The same values are also exported under the vendor-shaped aliases OPENAI_BASE_URL/OPENAI_API_KEY and ANTHROPIC_BASE_URL/ANTHROPIC_API_KEY for the formats your image declares (both pairs when it declares none), so a harness built against an existing SDK works unmodified; note that ANTHROPIC_BASE_URL is the origin without the /v1 suffix its OpenAI-shaped sibling carries. When every route the Session admitted serves one format your image declared, the environment also carries CHECKFU_MODEL_API — openai-completions, openai-responses, or anthropic-messages — and only that format’s alias pair, so an image that speaks several formats picks the one the gateway will forward. Official and customer harnesses selecting this model plane receive the same projection. The model name you send is rewritten to the admitted route. The protocol scaffold reads the OpenAI alias:
path=apps/cli/templates/acp/server.mjs
harness_owned model plane uses the harness’s own credentials and routing. Checkfu has no model wire or token-usage authority on that path, so Session text alone cannot establish platform-observed model usage. An opaque declaration records unknown model control. Declare only the model control and usage authority your integration can demonstrate; admission rejects requested guarantees that the selected path cannot provide.
The platform tool plane: MCP handoff
For an ACP release that implementssession_http delivery, granted platform
tools arrive as HTTP MCP servers in session/new. Connect those original
servers using a maintained MCP client and preserve their current exact-call
approval and credential boundaries. The generated starter does not implement
this connection and refuses a nonempty server list. Use --mcp-delivery none
until your implementation and exact release have qualified the handoff.
Emit native tool_call and tool_call_update observations for actual tool
work. Narrative output is not a tool-delivery receipt; Checkfu’s served-call
record remains authoritative. Declaring MCP support creates no tool grant.
The image contract
Your harness runs under a container posture the sandbox imposes, not one your image chooses: the process runs as user65532:65532, the root filesystem is read-only, and exactly /workspace, /tmp, and /home/checkfu are writable. Build for it — a harness that expects to write elsewhere, or to be root, fails at runtime rather than at registration.
Be precise about what enforces this. The sandbox provider applies the posture at materialization; the values above are the same ones the catalog’s image contract records for first-party entries, and a custom image registered through harness add oci has no catalog entry at all. Conformance does not check container posture — its case set covers the ACP handshake, tool correlation, and the declared control axes, and contains no uid, read-only-root, or writable-path case. The maintained starter does not test or attest that posture. Verify the
selected Environment and immutable image through the actual owner-supported
checks before claiming isolation. Measurements your harness reports from inside
its workload remain self-reports, not platform attestation.
Non-secret configuration reaches the harness as visible JSON in CHECKFU_HARNESS_CONFIGURATION, validated against the configuration schema registered with the release. Credentials never belong there — provider access rides the model plane above, and tool authority rides the MCP handoff.
A generated Vercel recipe image forwards this variable only when its
forward_env explicitly includes CHECKFU_HARNESS_CONFIGURATION. Use that
opt-in for an image whose native process understands the JSON, and register the
closed configuration schema with the release so profile validation happens
before the image starts. An arbitrary customer Dockerfile already receives its
declared environment; this recipe forward_env switch is not a requirement
for that path. The configuration is not a provider route or credential
authority. Official DeepSeek managed rows are not BYOH recipe
examples; a BYOH image must document its own accepted schema and native
selection.
Register, verify, run
Registration is the same advanced lane arc for every custom harness: build and push an immutable image, register the digest, request server-signed conformance, then create or update an Agent so Checkfu records the next immutable AgentVersion. Low-level registration records do not replace the AgentVersion or Environment admitted by a Session.--model-wire openai_responses
records its supported dialect on the release. Declare the dialects your own
implementation actually uses; the model route must serve one of them.
These registration commands use --mcp-delivery none for the unmodified
checkfu harness init acp starter shown above. The starter refuses MCP servers.
Use --mcp-delivery session_http only after your implementation connects the
HTTP MCP servers supplied in session/new. That flag records the delivery
contract on the release; the initialize capability alone does not set it.
Only the digest-pinned name@sha256:... form registers; a mutable tag fails before anything persists, and a new image is always a new release. The Custom ACP harness example describes how the resulting profile fits the Agent, Environment, and Session model.
Upgrade and roll back one logical harness
Keep the logical harness lane name stable after initial adoption. Test and publish a new immutable digest, then create the release, advance the profile with optimistic concurrency, and verify the exact resulting version in one CLI workflow:--expected-version is checked before the CLI creates a release, then the API
guards the patch with the same current version. The command prints a recovery
command as soon as an OCI release exists, so a failed or interrupted profile
patch never strands an undiscoverable artifact. After a successful patch it
prints the exact rollback command. Rollback is an ordinary forward version:
--verify targets the
returned profile version directly instead of resolving the logical name a
second time. Non-secret configuration is retained unless --configuration
is supplied, and the CLI validates the resulting configuration against the
target release before patching.
For an OCI-to-OCI update, omitted process, platform, configuration-schema,
model-wire, and MCP options inherit from the current immutable release. This
keeps an image-only rebuild exact without silently dropping a declared
capability; pass an option only when the new binary intentionally changes that
part of the release contract.
Or hand us the repository instead
If you would rather not run a container build at all,POST /v1/organizations/{organization_id}/harness-builds takes a GitHub repository URL, an optional ref, and an explicit platform build pool or Workspace/RunnerPool target. Checkfu builds the image and mints the Organization-owned, digest-pinned release for you. Ownership never implies execution authority. The ref is resolved to an exact commit at submission and only that commit is stored, so the immutability rule above is unchanged rather than relaxed: no branch or tag is ever stored on the result, and re-registering a repository is always a new build. Submission is accepted with 202; poll GET /v1/organizations/{organization_id}/harness-builds/{id} for settlement.
Two repository shapes are recognized:
harness-recipe.jsonat the repository root — the recipe-in-repo path. Commit the recipe plus the context its install command needs. Checkfu prepares a Vercel-shaped adapter image from that recipe. You do not need a Dockerfile for this path. The selected Runner must have a recipe base configured by its operator. Adopt the result asacp-v1with entrypoint/opt/checkfu/bin/checkfu-vercel-harnessandmodel_wire_dialectsfrom the recipe’s route. The privateandyrewlee/checkfu-customer-harness-fixturerepository is an additional example for developers who already have access. The recipe below works with your own published ACP package.- A Dockerfile and no recipe file — Checkfu builds that Dockerfile
as a stranger image. Direct-OCI registration (
checkfu harness add oci) remains the path for images you already built yourself.
harness-recipe.json.
Replace the package name, exact version and executable with your agent’s values;
the package must be accessible to the build Runner. This example assumes the
agent reads OPENAI_BASE_URL and OPENAI_API_KEY and uses OpenAI Chat Completions.
Choose the route and environment mapping that your agent actually supports.
builtin_tools list declares no native tools; add only tools your agent exposes.
Declare session_http MCP delivery only when the agent implements that transport.
For a native ACP server that enforces an allow-list supplied in session/new
metadata, the recipe can declare that mapping:
native_name values (or tool_name when absent),
then Vercel delivers the array under that exact _meta key. The native server
must enforce it before executing any built-in. An empty array disables every
built-in; an absent selection preserves native defaults. read, glob, and
grep are separate grants. Merely hiding a tool from the model is insufficient.
Unknown names and ambiguous native aliases are refused. Vercel continues to own
bootstrap, transport, Session restoration, turns, and cancellation; the mapping
does not introduce another agent loop.
Recipes do not inherit Vercel’s generic approval capability by default. Declare
"builtin_tool_approvals": "acp-permission-request" only if the native server
actually requests ACP permission before the governed operation and obeys the
decision. Without that declaration, approval-requiring modes fail before native
startup. The declaration alone grants no approval authority: signed conformance
must exercise the request and continuation on the exact release and profile.
A Session using this capability must enable native continuation capsules in its
capture policy; Workspaces with zero-data-retention (ZDR) mode cannot use native
approvals. The noncatalog Docker proof runs both decisions through the
public API (owned/harness-sandbox/public-customer-native-action-approval).
The separate launch-file-arg / dsh-overlay mapping is not a generic file
writer. It selects the reviewed DeepSeek plugin adapter and requires pinned
@deepseek-ai/dsh@0.1.5-rc.1, dsh --profile acp, and the complete matching
native tool inventory and built-in aliases. A recipe cannot relabel DeepSeek’s
shell as a read tool. Other harnesses use their own enforceable mapping;
declaring DeepSeek’s mapping cannot grant filtering support to another engine.
This DeepSeek integration also accepts the maintained adapter’s model configuration.
Declare these fields in the release’s configuration schema and set them on the
HarnessProfile so the native selector and context/output limits match the model
you route through Checkfu:
DSH_HOME in retained
Harness state, such as /home/checkfu/.checkfu-harness/deepseek, so the native
journal is available to later Runs. This does not establish portable native
checkpoint restoration.
The following example uses an ACP recipe that consumes HTTP MCP servers and
OpenAI-compatible chat completions. Run it from your own checkout of the harness
repository, not from a Checkfu source checkout. Commit harness-recipe.json at
the repository root and push that commit to GitHub first. With --recipe, the
CLI reads the recipe from the local commit that --ref names and derives the
entrypoint and wire dialect from it. --ref may be a full commit SHA, a tag, or
a branch (tags/v1.0.0, heads/main, or a bare name that is not both). Checkfu
resolves the ref once to an exact commit and the build records only that commit,
so a tag rebuilds a historical release after the branch has moved on. If your
checkout and Checkfu resolve the ref to different commits, the CLI refuses the
result, and the Runner refuses a build whose entrypoint or wire dialects differ
from the recipe at the frozen commit. A bare SHA is accepted only while it is
the tip of a branch in that repository, so name the tag for an older commit, and
a commit that exists only in a fork is refused. The command can stop at the ordinary
release-profile handoff, or compose adoption and signed verification without
introducing a privileged build-only profile path. Set
CHECKFU_RUNNER_POOL_ID to the rpool_... ID of a build-capable RunnerPool
in your Workspace first:
--dry-run to print the exact build request without submitting it. If the
waiting process exits, resume without resubmitting the build:
--recipe and supplies its own entrypoint
and model wire dialect.
Without --adopt, success prints checkfu harness add release --name ... --release hrel_... --driver checkfu:acp-v1@1. With --adopt, the CLI submits
that same public profile-creation payload; --verify additionally waits for
signed conformance and prints status. Building an image grants no conformance
or admission privilege.
Prepare an Environment from the release
Create your Agent and its dependencies through the ordinary resource operations. No installer prepares them for you. Put the harness reference, model, and instructions in an Agent project and runcheckfu agent apply, or
call Agent create directly. Then create the Environment that uses the built
release’s exact image repository and digest, and grant the Agent
use_environment through a PermissionAssignment. The
quickstart shows that Environment grant.
The Agent also needs a use_harness PermissionAssignment for the adopted
Workspace HarnessProfile. Set the subject to kind: "agent_definition" with
agent set to the Agent ID, and the resource to kind: "harness" with id
set to the HarnessProfile ID. Adopting the profile or creating the Agent does
not grant this permission automatically. Use
Create a PermissionAssignment.
An inline BYOK model configuration pins model_credential_id and does not need
an additional use_model grant. If you use a reusable ModelRoutingProfile,
select it with an Agent use_model PermissionAssignment whose resource kind is
model-binding and whose resource ID is the profile ID. See
Create a PermissionAssignment.
Keep the harness reference consistent with the adopted profile and the Agent
manifest. These are nonsecret configuration files; no Checkfu checkout or manual
trust evidence is needed.
For this preparation sequence, build with --adopt first, then create the
Agent and Environment and verify against that Environment. The combined build
command above assumes its named sandbox is already prepared.
agent apply prints and pass it as --agent-id on later
applies. The derived sandbox digest can differ from its harness base-image
digest. Creating these resources does not establish exact-image execution
readiness. That remains the separate check below.
Official catalog identity is recorded when a release is adopted. A later catalog
refresh does not invalidate an already-admitted Run’s pinned release. Native
checkpoint and approval authority come from its verified capability admission,
with the same provider, custody, and policy checks for official and customer
harnesses. A catalog label alone grants neither capability.
For an existing profile, leave --adopt off and pass the resulting release to
checkfu harness update <profile> release --release <hrel_...> instead. OCI
releases select the canonical protocol driver automatically; a non-OCI release
requires the explicit --driver value. The update path then follows the same
fresh-verification rule above.
Check execution readiness
A completed build creates an immutable release. Adoption selects a profile, and verification exercises its declared capabilities. Before an ordinary Session, the execution deployment must also serve that exact image on a qualified runtime and provide placement capacity. A passing conformance report or ready Runner alone does not supply that execution authority. After attaching the profile to an Agent, inspect public support diagnostics:harness_artifact_mismatch, ask the operator to publish and qualify an execution
offering and matching placement for the exact release image. Supply your release
ID, profile ID/version, and image digest. These prerequisites apply to new and
upgraded releases; do not change the digest to an unrelated image to bypass
the refusal.
A successful preflight still leaves exact admission to Session creation. Keep
your existing profile until the new release is verified and its execution
path is available. Existing Sessions and in-flight Runs retain their frozen
choices; later Session admissions can select the updated profile.
Where to go next
- To understand the boundary, use the maintained CLI ACP template — the protocol floor is intentionally minimal, and its omitted capabilities are explicit.
- To adapt an SDK-authored agent, use the OpenAI Agents SDK over ACP example — it pins the official SDK, routes its fixed model through Checkfu’s gateway, disables the SDK’s separate trace exporter, and declares no MCP handoff.
- For the contract itself, Harness wire extensions and the schema and vector artifacts remain the normative source.