HOLONOGRAPH / The Guide · Surface contracts v0.23.0 all chapters

Chapter 02

Surface contracts

Reflects Holonograph v0.23.0 · ~6 min read

A surface contract is the JSON document that tells Holonograph what an evaluation surface should look like — its dimensions, cohort tags, substrate columns, and vendor routings — before any real traffic hits it. Everything downstream (event ingest, snapshot queries, topology gap-finding) reads from the contract you registered here.

What it is

A surface is the operator's unit of evaluation — one addressable thing your agent calls, with a stable id and a shape you expect it to satisfy. A contract is the versioned declaration of that shape.

Contracts declare four things per surface:

  • Dimensions — the scoring axes an evaluation returns (e.g. correctness, tone, schema-conformance).
  • Cohort tags — the discrete labels you use to slice results (e.g. customer-tier=enterprise, fix_tier=tool-input-schema).
  • Substrate columns — the named columns Holonograph captures with every call, so a later reading can be attributed to what changed about your deployment. See Substrate columns.
  • Routings — which vendor(s) this surface calls, including multiplex arrays for head-to-head comparison. See The multiplexer.

Contracts are versioned by replacement, not mutation: you register a new contract, the agent identifier stays, and Holonograph records a versionId so past events remain readable against the shape they were captured under.

Why it matters

Two things become possible once a contract exists:

  • The lens knows what to expect. Ingested events are validated against the contract's declared dimensions and columns; anything that doesn't match is flagged, not silently accepted.
  • Coverage becomes measurable. The topology scanner (Chapter 09) compares what you declared against what the lens observed and surfaces the gaps — declared-but-never-observed dimensions, observed-but-never-declared ones, retirement candidates. That whole comparison exists because there is a contract to compare against.
When to re-version Adding a dimension, removing a cohort tag, splitting one surface into two, changing routings — any of these should ship as a new contract version, not an in-place edit. The prior version's events remain queryable and attributable against the shape they were captured under.

How to use it

Register or replace

Send the contract JSON via the SDK or directly to the endpoint. Registration replaces the previous version for the same agentId; the response returns a ContractSummary reflecting the newly-active shape.

// SDK
const summary = await client.contract.register({
  agentId: "billing-triage",
  surfaces: [
    {
      id: "classify-intent",
      dimensions: [
        { id: "correctness", type: "score" },
        { id: "schema-conformance", type: "boolean" }
      ],
      cohortTags: ["customer-tier", "fix_tier"],
      substrateColumns: [
        { id: "prompt_hash", control: "operator", visibility: "transparent", semantic: "deployment-state" },
        { id: "tool_schema_version", control: "operator", visibility: "transparent", semantic: "deployment-state" }
      ],
      routings: [
        { surfaceId: "classify-intent", lightSourceId: "anthropic/claude-sonnet-5" }
      ]
    }
  ]
});

Or over HTTP:

POST /holonograph/contract
Authorization: Bearer <token>
x-holonograph-run-mode: production
Content-Type: application/json

{ "agentId": "billing-triage", "surfaces": [ ... ] }

Read back the active contract

GET /holonograph/contract returns the same ContractSummary shape as the register response — useful for reconciliation in CI or a startup check.

Reading the output

A ContractSummary is the compact readback of what's actually in effect. It's the shape you'd diff in a code review of a contract change.

FieldShapeWhat it tells you
agentIdstringThe registered agent identifier.
versionIdstring (opt)The version this summary reflects. Absent on first registration.
surfaces[]arrayOne entry per surface in the contract.
surfaces[].idstringThe surface identifier.
surfaces[].statusenumWhether the surface is active, forward-declared, or retired.
surfaces[].dimensionCountnumberCount of declared dimensions.
surfaces[].cohortTagCountnumberCount of declared cohort tags.
surfaces[].substrateColumnCountnumberCount of substrate columns declared for this surface.
surfaces[].gatedDimensionIds[]string[]Dimensions currently under a governance hold.
surfaces[].removedDimensions[]arrayDimensions removed in this or a prior version, each with a supersededBy reference.
surfaces[].removedCohortTags[]arrayCohort tags removed, each with a supersededBy reference.
pricingobject (opt)Per-surface pricing declarations, if configured.
systemSurfacesobject (opt)System-managed surfaces the contract enables (e.g. drafter, judge).

The supersededBy reference on removed dimensions and cohort tags carries the altitude of the change (surface, dimension, tag) and, where applicable, the id of the replacement — so a later readback of history can tell a promotion from a retirement without ambiguity.

Reference

Endpoints

Method & pathPurpose
POST /holonograph/contractRegister or replace the active surface contract for an agent.
GET /holonograph/contractRead back the active ContractSummary.

Headers

  • Authorization: Bearer <token> — when the deployment enables bearer auth.
  • x-holonograph-run-mode: <mode> — the run mode this call belongs to; see Run modes.

Error envelope

Every error response follows the same shape:

{
  "error": "human message",
  "code": "error_code",
  "details": { }
}

4xx covers validation, auth, and not-found. 5xx is internal. 501 means the feature isn't wired on this deployment.