Skip to main content
POST /v1/retrieve is the flagship call. One request returns evidence, contradictions and a reasoning trace, and tells you which engine served it.

Before you start

The shortest call that works

contradictions on a retrieval is an open object in the contract, and the keys above are the ones this route emits today. They are the mining shape, in snake_case, not the canonical Contradiction object. The stable, listable form with id, a, b, status and detectedAt comes from GET /v1/contradictions.

Reading the response

sources

Ranked evidence. Each entry names the graph node it came from, so you can drill in with GET /v1/recall/graph/node/{nodeId} or link a citation. snippet is capped at 280 characters. To get the full stored text of every source, ask for it, which adds a content key alongside the snippet:
expand also works as a body field. sources.content is the only value defined in v1. The default is lean on purpose: full content multiplies the payload for a response most callers only rank and cite.

contradictions

Where this person’s own beliefs conflict. a and b are the two poles: for a reversal, the concept they moved from and to, and for a retraction, the belief before and after. tension is a 0 to 1 salience. Every contradiction comes back with status: "open", because v1 stores no resolution state. To close one, supersede the side that lost. See Surfacing contradictions in review. Set includeContradictions: false to skip the detection pass if you do not use them.

cognition

The brain’s reasoning trace: confidence is how strongly it settled, driftRate is how far the activated region has moved from what the brain trained on, focalNodeIds are the nodes it settled on as the centre of the answer, and useSystem2 is true when it escalated from a fast associative lookup to slow deliberate reasoning.
cognition is null on the hybrid path. It is not an error, and it is not an empty object. The fallback engine has no reasoning state to report, so there is nothing honest to put there. Any code that reads cognition.confidence unconditionally will crash the first time an organization retrieves before its brain is trained.

path, degraded and degradationReason

These three exist so a quality drop is never silent. Read Brain path and hybrid path for the mechanism, and Train and serve an ExoBrain to get off the fallback.

usage

readUnits is the number of sources returned, which is the billable read unit. embedTokens is a documented estimate of the tokens spent embedding your query, at roughly 3.5 characters per token, not a metered figure. brainInference says whether the brain actually ran.

Scoping the call

scope decides whose content is searched. To retrieve as one of your end users, provision them once and then send the header on every call:

Streaming

Set stream: true and the same result arrives as text/event-stream, so a UI can render evidence while the reasoning is still resolving. Events arrive in a fixed order:
Three things about that stream, because they are easy to get wrong:
  • Every frame is a wrapped object, not a bare value. cognition arrives as {"cognition": {...}}, the same nesting as sources and contradictions. Read JSON.parse(data).cognition, not JSON.parse(data).
  • done carries the whole envelope, not a summary. It repeats sources, contradictions and cognition alongside path, degraded, latencyMs, traceId and usage. If you only want the final object, ignore the first three events and parse done.
  • There is no [DONE] sentinel. The done event is the terminator. The result is computed before the first frame is sent, so the events are ordered rather than incremental.
sources always arrives first, so you can paint the evidence list before the model has finished settling. Wait for done before reading path and degraded. POST /v1/search is the same hybrid vector plus keyword retrieval with the cognition layer removed. No brain inference, no contradiction detection, no reasoning trace. topK on search is coerced into 1 to 50 rather than rejected. On retrieve, a topK outside 1 to 50 is a validation error.

When it goes wrong

Not an error. The organization has no trained brain, so the hybrid path served the call and reported that honestly in degradationReason. The sources are real and usable. Train a brain to get the reasoning block. See Train and serve an ExoBrain.
Either the key lacks the read scope, or you sent an X-Exo-Subject value that has never been provisioned. The subject seam refuses an unknown selector before the handler runs, so this fails fast rather than silently reading the wrong partition. Provision it with PUT /v1/subjects/{id} first. See permission_denied and subject_not_found.
query must be 1 to 10,000 characters and topK must be 1 to 50. The errors[] array in the problem body names the offending field and a JSON pointer to it. See validation_error.
A dependency, usually the embedder or the connection pool, is temporarily unavailable. Retrieve degrades to 503 rather than 500 by design, which means it is safe to retry with backoff. See service_degraded.

Next

Cognition

The reasoning block, field by field, and when it is null.

Conditioning your own agent

Turn the same graph into a prompt for a model you host.