The loop
Every arrow into the graph is asynchronous, and every arrow out is a normal request. That asymmetry is the single most important thing to internalise: writes return a job id, reads return data.Step one: content in
You push anything a person thinks in. Raw text throughPOST /v1/ingest, files and transcripts through POST /v1/import, coding-agent sessions through the session family, and repositories through the GitHub connector.
Each call returns immediately with a job id:
202 application/json
GET /v1/ingest/{job_id}/status for progress, or GET /v1/jobs/{job_id} for the canonical cross-family view, where a finished import reports what your content actually became:
200 application/json
result block is the multi-phase import pipeline reporting itself. A single POST /v1/ingest writes one node through a leaner path and reports no result block at all, so result is null on those jobs. Read the absence as “this job type does not report”, not as “nothing happened”.
Send an Idempotency-Key and a retry returns the original job id rather than a second copy. See Ingesting content.
Step two: the graph
What comes out is not an index of passages. It is a graph.- Nodes are units of content with a title, text and an authority level. Authority is why an imported document outranks a line an agent narrated about itself.
- Edges are typed relations between nodes, some derived from structure, some from similarity, some asserted by you. An edge you assert has capped authority, so organic evidence always outranks a hand-written link.
- Domains are communities the graph discovers in itself rather than a taxonomy you supply.
Step three: reads
Four surfaces read the graph, and choosing between them is most of the integration design.retrieve is the flagship because it is the one that answers with provenance. condition is the one that matters if you are wiring Exo into an agent you already own: it hands back a prompt artifact rather than more text for you to rank.
The one asymmetry to plan around
Retrieval runs on the org’s trained ExoBrain when there is one, and falls back to hybrid vector plus keyword search when there is not. The response always says which:cognition is populated only on the brain path. On the hybrid path it is null, because there is no reasoning state to report. Build for null from day one: every new org starts there. See Brain path and hybrid path.
The objects you will meet
Seven named objects carry the capability that a vector store cannot express. Each has its own page with a real payload.Cognition
Confidence, reasoning tier, whether it escalated to slow deliberate reasoning, and the nodes it settled on. From
POST /v1/retrieve.Contradiction
Two poles of a belief conflict and how tense it is. From
GET /v1/contradictions.Belief and supersession
How a belief was replaced and where authority went. From
GET /v1/graph/nodes/{id}/history.ManifoldState
Discovered thinking dimensions, basins and trajectory. From
GET /v1/recall/identity.Phase
Eras of thought clustered from content dates. From
GET /v1/recall/temporal.ConditioningPack
A ready-to-inject prompt with a voice profile and an expiry. From
POST /v1/condition/session.AgentFailurePattern
The recurring ways a team’s coding agents go wrong, anonymised. Defined in the contract, surface not in v1.
One layer per end user
If you are building a product with your own users, provision a subject for each of them. A subject is an isolated memory partition, backed by physical per-organization schema isolation rather than a filter on a shared table.cURL
X-Exo-Subject header, and acts as the key owner when you do not. DELETE /v1/subjects/{id} erases everything that end user ever stored, which is the documented erasure path. See One memory per end user and Subjects and isolation.
Where to go next
Quickstart
Five calls, from a key to a retrieve response you can read.
Concepts
What Exo stores, and why it is a graph rather than an index.
API reference
All 80 operations, with the traps the generated schema cannot carry.