Knowledge Graph API
The routes that read and maintain the knowledge graph — the typed, weighted, bi-temporal edges memories wire up.
Point-in-time graph query
POST /api/v1/projects/{projectId}/lattice/graph/query
Return the edges valid at a moment (or the current ones), filtered by subject and/or predicate — “what did we believe about X on date Y”.
{
"subjectId": "ent_…",
"predicate": "prefers",
"asOf": "2026-01-01T00:00:00Z",
"limit": 100
}Each edge carries a weight and a bi-temporal validity window:
{
"edges": [
{
"id": "edge_…",
"subjectId": "ent_…",
"predicate": "prefers",
"objectId": "ent_…",
"objectLiteral": null,
"weight": 0.9,
"validFrom": "2025-06-01T00:00:00Z",
"validTo": null
}
]
}Exactly one of objectId (an entity) or objectLiteral (a value) is set.
validTo: null means the edge is still current. limit defaults to 100,
clamped to [1, 1000].
Admin graph CRUD
Under /api/v1/projects/{projectId}/admin/memory, for manual annotation and the
admin canvas (all WRITE_MEMORY):
| Method | Path | Purpose |
|---|---|---|
GET | /admin/memory/entities | List entities (filter by type / scope / search). |
POST | /admin/memory/entities | Create an entity. |
GET | /admin/memory/entities/:entityId | Entity + its 1-hop outgoing edges. |
POST | /admin/memory/entities/:entityId/retire | Retire an entity bi-temporally. |
POST | /admin/memory/edges | Create an edge. |
POST | /admin/memory/edges/:edgeId/retire | Retire an edge bi-temporally. |
GET | /admin/memory/graph/edges | Bulk-load all currently-valid edges (the canvas). |
POST | /admin/memory/graph/traverse | Multi-hop traversal (1–3 hops) from a seed entity. |
GET | /admin/memory/graph/stats | Entity/edge counts + extraction state. |
POST | /admin/memory/graph/extraction/toggle | Opt this project into/out of entity extraction. |
POST | /admin/memory/graph/backfill | Extract entities + edges from memories not yet processed. |
The entities/:entityId/onboarding-context route assembles an onboarding
briefing by inheriting memory along a person’s org chain (member_of /
part_of).
Associative prefetch
POST /api/v1/projects/{projectId}/admin/memory/prefetch-related
Anticipatory retrieval by spreading activation. Given the memories a session
is currently working with (seedMemoryIds), return other memories linked to the
same graph entities, ranked by how many distinct shared entities connect them —
the more graph paths, the stronger the association. Deterministic and read-only;
surfaces the context most likely needed next before it’s asked for.
{ "seedMemoryIds": ["mem_a", "mem_b"], "limit": 10 }The same spreading-activation primitive can fold into ordinary
search when the
MEMORY_ASSOCIATIVE_RECALL_ENABLED flag is on — a ranked search seeds activation
from its top hits and blends the graph-linked memories in with a bounded bonus.
Reflection / insight synthesis
POST /api/v1/projects/{projectId}/admin/memory/reflect
Review a subject’s recent confirmed memories and synthesize higher-order
insight memories — cross-cutting generalizations supported by multiple
raw memories that no single one states (e.g. “consistently churns after a price
increase”). Insights are saved as first-class memories with provenance back to
their sources.
{ "userId": "acct-42", "maxSources": 50, "maxInsights": 5, "dryRun": false }Pass dryRun: true to preview without persisting. Reflection is LLM-based and
gated by the MEMORY_REFLECTION_ENABLED flag; it’s intended to run on a schedule.
Consolidation & dedup
Two distinct maintenance passes:
POST /api/v1/projects/{projectId}/admin/memory/dedup — semantic dedup:
collapse near-duplicate memories (cosine ≥ threshold, default 0.92), keep the
strongest of each group and supersede the rest. Deterministic; no deletion.
{ "threshold": 0.92, "scanLimit": 1000 }POST /api/v1/projects/{projectId}/admin/memory/consolidate — the TS dedup +
decay pass over the project’s memory items (the operation the nightly cron
runs; exposed for on-demand triggering).
POST /api/v1/projects/{projectId}/admin/memory/embeddings/backfill — vectorize
memory items that lack an embedding (catch-up). Call repeatedly until
embedded is 0 to drain a large corpus.