> ## Documentation Index
> Fetch the complete documentation index at: https://obversa.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# API

> @obversa/api: the engine and memory contracts, the graph plan, and the validators for every stored record.

`@obversa/api` holds the contracts the runtime and the plugins share: what
an engine is, what a memory adapter is, how a graph plan is resolved, and
the shape of every stored event, artifact, callback and proof record. Import
it to write an engine or memory adapter, or to validate records a host
reads. Command execution belongs to [Core](/docs/packages/core), memory helpers
to [Runtime](/docs/packages/runtime).

## Install

<CodeGroup>
  ```bash npm theme={null}
  npm install @obversa/api
  ```

  ```bash pnpm theme={null}
  pnpm add @obversa/api
  ```
</CodeGroup>

Included in `@obversa/obversa`.

## Quickstart

Validate an engine's result before you read its parts:

```ts examples/safe-node-attempt.ts (excerpt) {1} theme={null}
  const grok = validateAgentResult(await new GrokCliEngine({
    executable: grokExecutable,
    version: '1.0.44',
    identity: { provider: 'xai', modelFamily: 'grok-4' },
    permissionMode: 'dontAsk',
  }).run(
    request(directory, 'grok-4-example', RESULT_SCHEMA),
    () => {},
    new AbortController().signal,
  ));
```

`validateAgentResult` checks an `AgentResult` against the contract and
returns it; `finalResultPart` and `finalResultText` read the one final
part. The whole file is on [Safe node attempts](/docs/recording/node-attempts).

## Implement an engine

An `Engine` has a name and a `run` method: one `AgentRequest`, one event
sink, one abort signal, one `AgentResult`. It may also have `admit`, which
the runtime calls before a run when the plan asks for engine checks;
`admit` receives the request without its prompt and returns an
`EngineSelectionRecord`, the identity the engine will run under (adapter,
adapter version, provider, model family, model, executable, capabilities).
An engine that would run as something else refuses. An engine without
`admit` is `unsupported` for the check, and the plan says whether that
blocks the run.

A command-line adapter is admitted by path and version, not by a hash of
the executable, and doesn't control grandchildren it can't see. An API-key
adapter is admitted locally with no executable. A live check is an ordinary
`run` with `purpose: 'preflight'`, no tools, no workspace and a leaf
request; it proves the seat answers and does no work.

`runEngineConformance` checks an engine through its real process or
provider boundary. A feature the engine lacks goes in `unsupported` with
its reason; the report lists it and doesn't count it as a failure. One case
is about [your setup](/docs/packages/engines): the kit runs a read step once
with the engine's `clean` option off and once with it on. Clean is the
default, so the fixture opens the engine with `clean: false` for the
`workspace-read` scenario. The fixture's `observe()` reports `ownSetup`
from the arguments or options the engine really passed. The case checks the
run with `clean: false` passed no clean-mode switches, the clean run passed
them, and both stayed read-only. An engine
with no clean mode declares `clean-mode` in `unsupported`. So does an
engine that loads none of your setup and always runs clean: it has no
`clean` option, so the kit has no second run to compare.

`modelIdentity(model)` reads the provider and model family from a model
string: `provider/model` supplies both, a bare model only its family (the
lowercase part before the first hyphen). Whitespace, a second slash, an
empty provider or model, or an empty or `unknown` family is refused with an
`EngineError` of kind `invalid-config`. Every harness that runs other
providers' models derives its identity through it. `classifyEngineFailure`
turns a failure message into an `EngineFailureKind`, and
`LANE_DEAD_FAILURES` names the kinds a fallback treats as lasting.

## Implement a memory adapter

A `Memory` adapter has one `scope` and one `execute(command)` method.
`MEMORY_ROOT` is `/memories`, and every path starts there. `MemoryCommand`,
`MemoryResult`, `MemoryLimits` and `MemoryErrorCode` describe the requests,
results, limits and errors; the commands and codes are on
[Memory port](/docs/memory). `runMemoryConformance` from `@obversa/api/testing`
checks an adapter without a network service.

## Resolve a plan

`resolveGraphPlan(description, resolution)` binds a graph description to a
host's admission record and freezes what the run may use:

```ts examples/custom-graph.ts (excerpt) {6-8} theme={null}
const identity = {
  source: 'npm:@example/draft-review',
  version: '1.0.0',
  digest: 'sha256:1111111111111111111111111111111111111111111111111111111111111111',
} as const;
const resolution: PlanResolution = {
  package: identity,
  admission: { package: identity, permissions: [] },
  executionLanes: [],
};
```

`compileGraphDefinition` validates a definition's data, and
`validateGraphDescription` a description that didn't come from
`compileGraph`. [Plan admission](/docs/graphs/plan-admission) is the guide.

## Validate stored records

Every stored shape has a validator that returns it frozen or throws:
`validateRunDefinition`, `validateRunStartRecord`, `validateRunStorageRecord`,
`validateRunStoragePolicy`, `validateDomainEventEnvelope`,
`validateDomainEventBatch`, `validateNewDomainEvent`, `validateDomainEventId`,
`validateEventStreamRef`, `validateStreamRevision`, `validateStorageId`,
`validateArtifactReference`, `validateNewArtifact`, `validateArtifactScope`,
`validateCallbackRequest`, `validateCallbackResponse`, `validateCallbackEvent`,
`validateAcceptedResultRecord`, `validateApprovalRecord`,
`validateApprovalSubject`, `validateActionDecision`, `validateResolvedPlan`,
`validateIncompleteResultEvidence`. The example reads an artifact
reference back out of an event before trusting it:

```ts examples/durable-storage.ts (excerpt) theme={null}
    const reference = validateArtifactReference(event.payload.artifact);
```

`canonicalJson`, `digestJson` and `cloneFrozenJson` are the JSON helpers the
contract uses; `findKnownSecretInEvents` finds a configured secret in an
event batch before it's written.

## Bind an approval

`createCallbackGate(definition)` turns a gate definition into a request
with a content identity, and `createApprovalCallbackGate(definition,
subject)` puts the subject digest in first, so the question is about exact
bytes:

```ts examples/proof-bound-approval.ts (excerpt) {1} theme={null}
  const request = createApprovalCallbackGate(approvalDefinition, approvalSubject);
  const callbacks = await createStoredCallbackClient(storage, runId);
  await callbacks.post(request, approvalSubject);
```

`approvalSubjectDigest`, `snapshotApprovalSubject`,
`assertApprovalPermissionsAdmitted` and `acceptedResultMatches` are the
pieces under [Proof-bound acceptance and approval](/docs/reviewing/proof-acceptance).
`callbackRequestDigest` gives a definition's digest without creating a
request.

## Options

The contract's option types are on the pages that use them: `AgentRequest`
on [Safe node attempts](/docs/recording/node-attempts), `PlanResolution` on
[Plan admission](/docs/graphs/plan-admission), `RunStoragePolicy` on
[Events and artifacts](/docs/recording/events-and-artifacts). This package adds
no options of its own.

## Errors

* **`EngineError`** carries a `kind` from `EngineFailureKind`: `auth`,
  `billing`, `quota`, `rate-limit`, `model-unavailable`, `missing-cli`,
  `invalid-config`, `transient`, `aborted` and the rest of the union.
  `EngineIncompleteResultError` is a failed turn that still produced
  measured evidence.
* **`GraphValidationError`**: an invalid definition, description or plan.
* **`GraphExecutionError`** with a `GraphExecutionErrorCode`: `ABORTED`,
  `DUPLICATE_POSITION`, `EMPTY_DECISION`, `ENGINE_IDENTITY_UNRESOLVED`,
  `INVALID_EVENT`, `INVALID_PREFLIGHT_CONFIG`, `MISSING_ENGINE_BINDING`,
  `MISSING_MEMORY`, `MISSING_NODE_BINDING`, `PROTOCOL`,
  `RESUME_EVENT_MISMATCH`, `STORED_GRAPH_MISMATCH`.
* **`StorageError`** with a `StorageErrorCode`: `INVALID_STORED_VALUE`,
  `UNSUPPORTED_ENVELOPE_VERSION`, `REVISION_CONFLICT`, `DUPLICATE_EVENT_ID`,
  `CORRUPT_EVENT_STREAM`, `ARTIFACT_NOT_FOUND`, `ARTIFACT_NOT_ADMITTED`,
  `ARTIFACT_INTEGRITY`, `STORAGE_LIMIT_EXCEEDED`, `SENSITIVE_CONTENT`,
  `KNOWN_SECRET`, `UNSAFE_STORAGE_PATH`.
* **`ApprovalSubjectError`**: a permission outside the stored plan
  (`SUBJECT_MISMATCH`).
* **`JsonValueError`**: a value that isn't JSON, with `path`.
* **`MemoryErrorCode`** on a memory result: the fifteen codes on
  [Memory port](/docs/memory#failure).

## API

**Engines.** `Engine`, `AgentRequest`, `AgentResult`, `AgentResultPart`,
`EngineSelectionRecord`, `EngineFailureKind`, `isEngine`, `engineSelection`,
`assistantResult`, `reportedUsage`, `finalResultPart`, `finalResultText`,
`requireFinalResultText`, `validateAgentResult`, `modelIdentity`,
`classifyEngineFailure`, `LANE_DEAD_FAILURES`, `assertReadAccess`,
`TeamSeat`, `SUBAGENT_TOOLS`, `CLAUDE_SUBAGENT_TOOLS`.

**Memory.** `Memory`, `MemoryCommand`, `MemoryResult`, `MemoryLimits`,
`MemoryError`, `MemoryErrorCode`, `MEMORY_ROOT`.

**Graphs and plans.** `compileGraphDefinition`, `resolveGraphPlan`,
`validateGraphDescription`, `validateResolvedPlan`, `GraphDefinition`,
`GraphType`, `GraphDescription`, `PlanResolution`.

**Callbacks and proof.** `createCallbackGate`, `createApprovalCallbackGate`,
`callbackRequestDigest`, `approvalSubjectDigest`, `snapshotApprovalSubject`,
`assertApprovalPermissionsAdmitted`, `acceptedResultMatches`.

**Stored records.** The `validate*` functions above, `canonicalJson`,
`digestJson`, `cloneFrozenJson`, `findKnownSecretInEvents`.

**Subpaths.** `@obversa/api/testing`: `runEngineConformance`,
`runEngineAdmissionConformance`, `runMemoryConformance`,
`runEventStoreConformance`, `runArtifactStoreConformance`,
`runWorkspaceProviderConformance` and their `assert*` forms.
`@obversa/api/run-definition-support`: `runDefinitionSupport`.
`@obversa/api/accepted-result-support`: `acceptedResultSupport`.
`@obversa/api/approval-support`: `bindingFromSubject`, `hasExactFields`,
`isObject`.

## Next steps

* [Safe node attempts](/docs/recording/node-attempts): the engine contract in
  a running file.
* [Plugins and tools](/docs/packages): the adapters that implement these
  contracts.
* [Events and artifacts](/docs/recording/events-and-artifacts): the storage
  ports and their conformance kits.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.