The taxonomy
Every memory carries a type, the same one across CLI, MCP and HTTP. Defaults tofact.
A database constraint rejects anything else, even if it gets past the API. Choosing well pays off
twice: the viewer filters by type, and the MCP tool description teaches agents the same
definitions, so an agent saving “user prefers tabs” tags it
preference unprompted.
Recall results can also carry the sentinel type
context. Those are chunks of ingested files,
not saved memories, and their kind is context. You cannot save one. The sentinel exists so a
single result list can hold both kinds honestly.Beliefs, not rows
A memory is a belief with a lineage. Rows are never mutated in place.rootId and version
rootId is the stable identity of the belief, version counts up from 1.Active is current
The newest active row is the belief. Older ones are stale: kept forever, out of recall, dedup
and the graph.
Edges agree
Each step writes a
replaces edge from child to parent, so history and the graph tell the
same story.Validity is temporal
assertedAt is when a version became the belief. staleSince is when it stopped.What creates a version
Resolving a conflict can step a version too: keep new and merge make the winner continue
the existing lineage, so a settled contradiction lands in that belief’s history instead of
orphaning it.
Walking history
GET /memory/:id/history, in the viewer’s memory
panel, and in the read-only memory_history MCP tool.
Agents can read history but not edit a belief.
update is deliberately a human action in the
CLI or viewer. Recall never returns stale versions, so old ones cannot shadow the current one.