skip to content
The endpoint contract

The contract

The endpoint contract

One host, one wire. Every surface — chat, workflows, code, the CLI, an external agent — is a client of the same governed planes; this page is the public record of that wire.


Conifer is a host you stand up and call. The desktop studio, the CLI, and a third-party agent all speak to the same HTTP surface, with the same shapes, the same headers, and the same receipts — there is no private wire. The contract is published so a client written against it keeps working: the surface only grows, it never breaks.

Served planes

PlaneWireSpecified by
/v1OpenAI-compatible chat completions and model listingOpenAI's API, served verbatim
/v1/messagesAnthropic-compatible messages and count_tokensAnthropic's Messages API, served verbatim
/api, /infillOllama-compatible chat, generate, and infillOllama's API, served verbatim
/agent/v1Agent tasks, approvals, workflows, sessions — 25 routesThe frozen OpenAPI document
/lab/v1The kernel lab as an API — 12 routesThe frozen OpenAPI document
/host/v1Host identity, health, telemetry — 8 routesThe frozen OpenAPI document
/observe/v1The queryable observability surface, read-only by construction — 4 routesThe frozen OpenAPI document
/canopy/v1The metaharness read slice — instances, tasks, task events, placement dry-run — 5 routesThe frozen OpenAPI document
/recorder/v1Flight Recorder write/control — per-rack grants, write-token ingest, purge — 4 routesThe frozen OpenAPI document

Contract version 1.4.0. The governed planes are specified by the machine-readable document below; the compatible facades are specified upstream and served verbatim. Conifer semantics ride only in the x-conifer-* header family, never in bespoke body fields.

Additive-only evolution

That rule, quoted verbatim from the canonical contract, governs every plane above. Fields that were present stay present, with the same type and the same name; new endpoints, new fields, and new enum values are the only non-breaking change. Fixtures are normative: when code and contract disagree, the code is wrong. A client may therefore ignore anything it does not recognize — an unknown field, header, or code is never an error.

The routing slot

Routing is part of the wire, not a private feature of any surface. A client submits an ask; the host executes within it; a receipt discloses what actually ran.

The ask

Model fieldMeaning
<concrete-id>Serve exactly this model, or refuse with a typed error. A named model is never silently substituted.
autoDelegate the choice to this door's decider; the receipt discloses the pick.

Ids beginning conifer or auto are reserved, including the auto/<pool> grammar and the constraint-header family — reserved names grow additively like everything else. The advisory x-conifer-request-type request header steers auto, never auth or billing. Credit-spending calls carry a client-minted idempotency-key header, stable per turn, so a retry never bills twice.

The receipt

Response headers on a settled completion disclose the execution:

HeaderMeaning
x-conifer-requested-modelThe ask, verbatim.
x-conifer-effective-modelThe model that executed.
x-conifer-route-reasonWhy, as a code from the vocabulary below.
x-conifer-endpointThe venue that served it, e.g. credits or byok:<provider>.
x-conifer-cost-nanousdSettled cost in nano-USD when the call was metered. Absent when unmetered — absent is never zero.

A hop that decides emits its own receipt; a hop that relays forwards the upstream receipt unchanged. The header family versions add-only: a v2 may add headers, never remove or rename them.

Reason codes

The x-conifer-route-reason vocabulary is owned by a versioned artifact (route-reasons.json, version 7) and grows additively. The codes:

Code
privacy_local_only
offline
capability_unavailable
context_overflow
needs_vision
needs_audio
needs_tools
local_confident
low_confidence
predicted_low_local_quality
not_entitled
as_requested
type_routed
tier_substitution
budget_downgrade
budget_floor
sticky_promotion
content_unsupported
cloud_not_permitted
airgap
out_of_budget
endpoint_down
capability_unmet
tainted
no_cloud_lane
resident
pinned
unknown_local_model
local_unavailable
cloud_masked
cloud_unavailable
tool_capability_unmet
tool_stream_unsupported
cache_unsupported
thinking_unsupported
vision_unsupported
native_fallback
strategy_routed
health_routed
provider_failover

Codes are opaque to clients: a newer host may emit a code an older client has never seen, and the client treats it as an unknown string, never as an error.

Changelog

VersionDateChange
1.4.02026-07-09Flight Recorder Phase 1: the /recorder/v1 write/control family mounts — arm/disarm a rack's recording grant (PUT /recorder/v1/racks/{rack_id}), review grants (GET /recorder/v1/racks), write-token-gated capture ingest (POST /recorder/v1/ingest), and purge with crypto-shred (DELETE /recorder/v1/racks/{rack_id}/history) — every response the one RecorderEnvelope, bearer required even on loopback. Recorder reads mount no new noun; they ride /observe/v1 as surface transcript. The same window mounted the /canopy/v1 read slice (instances, tasks, task events, placement dry-run) additively, consuming no version slot of its own.
1.3.02026-07-09Team Pulse: the /observe/v1 plane lands — the queryable observability surface. Four read-only routes (GET /observe/v1/surfaces, GET /observe/v1/surfaces/{surface}/schema, POST /observe/v1/query, POST /observe/v1/questions/{name}) over the ObserveEnvelope schema; bearer required even on loopback; the async query door stays reserved, not mounted.
1.2.02026-07-06Session state adds cancelled and waiting; suspend_kind and wrapper_cycle; run inputs and verified retry provenance (retried_from); external session registration (POST /agent/v1/sessions, heartbeat, end) and the session work receipt (GET /agent/v1/sessions/{id}/receipt); pause, resume, and run-now on runs; task journaling (GET /agent/v1/tasks/{id}); SubstrateInfo adds contract_version, the capability probe.
1.1.02026-07-05One host: the OpenAI and Ollama facades and the observation plane ride the managed endpoint. Session adds waiting_on, cwd, tokens, and route; GET /agent/v1/runs/{id}; the bearer security scheme for non-loopback binds.
1.0.02026-06-13The native-plane document freezes (x-status: final), reconciled with the host's route table in both directions: every documented path is mounted, every mounted native path is documented.

Every entry is additive. No version has removed, renamed, or retyped a member.

Machine-readable

The normative artifact is the OpenAPI 3.1 document the native planes are generated from: openapi-native-planes.yaml. The copy served here is byte-identical to the contract this site is built against; a drift test fails the test suite when they diverge. Its canonical home is the platform’s contracts directory, alongside the golden fixtures (turn events, run events, host identity, session states) that pin the wire byte-for-byte across repos.

A live host discloses its own contract version at GET /host/v1/info (contract_version), so a client can probe capability before relying on it.