SurrealDB Agent Memory splits the experiential side of memory into six typed areas. Each has its own lifecycle, decay posture, and retrieval weighting. A parallel trace layer records how memory was used.
The eight pillars are summarised in Eight pillars and six categories.
An example: four sentences about cats
The six categories are easier to remember if you map them to how you already classify speech:
| Sentence | Category in play |
|---|---|
| “I have a cat.” | Identity / knowledge about the speaker (present) |
| “I saw a cat last night.” | Episodic (the story) plus extracted knowledge with a past valid time |
| “House cats weigh about 4 kg.” | Knowledge at general scope - like a textbook fact, not “about Alice” |
| “I used to have a cat.” | Knowledge superseded in time - still stored, no longer current |
Instructions and uncertainty sit beside these: “always use cute nicknames for pets” is not a zoology fact; “Alice says 5 kg but the manual says 4 kg” becomes uncertainty, not a silent average. Together with Tri-temporal model, this is how SurrealDB Agent Memory keeps personal, general, and time-bound memories from blurring together.
1. Episodic - the raw conversational record
The ordered session / turn stream: what was said, in order, including anaphora (pronouns and references like “he” or “that project” that point back to something said earlier).
Written once; not reconciled like extracted facts.
May age out faster than derived beliefs.
Browsed with Sessions and turns tooling.
2. Identity - who the principal is
Stable facts about the person or agent: “Alice is Head of Platform at Acme”, “King Charles III is head of state of the United Kingdom”. Long retention, high weight in profile summaries.
3. Knowledge - what the principal knows
Facts shared in conversation, distinct from uploaded manuals: “Alice is learning Rust”, “The Atlas launch is in Q3”. Medium retention - fades without reinforcement unless consolidated.
4. Context - what is happening now
The working set for this conversation: “Alice is debugging checkout today”, “We are reviewing the EU pricing page”. Short retention, replaced quickly.
5. Instructions - how to behave
Behavioural directives, not world facts: “always British English”, “never use my first name”, “keep answers under three bullet points”. Applied at prompt assembly, not generic retrieval.
6. Uncertainty - explicit gaps
Records when SurrealDB Agent Memory is not confident enough to commit: conflicting sources, weak extraction, or open questions. Surfaces “I’m not sure” instead of invented fill-ins.
Reading them back
Every extracted attribute carries its memory_category, so anything that assembles a profile should filter on it rather than treating all attributes alike:
identityandknowledgefor anything that should stay true - a user profile, a character sheet, a summary someone will read next week.contextfor what is happening now - valuable for the current turn, misleading in a durable summary.
The split can be stark. Ingesting a novel chapter by chapter will tend to produce far more context attributes for protagonists than identity and knowledge attributes: things like state_of_mind, physical_state and feeling against occupation, eye_color and personality_trait. When read as one undifferentiated set, that describes a mood; filtered to identity and knowledge, it describes a person.
Note that a context key can hold several live values at once. Transient states are written as they are observed, and a later value does not necessarily supersede an earlier one. As such, the "the current state" is not a single row. You can take the most recent by created_at (which is known time - the chapter, not the upload), or read the whole chain from GET /entities/{type}/{name}/history/{key} and pick from it.
Setting the category
With infer: "full", the default, extraction chooses the category of each fact from the text. A request cannot change that choice.
With infer: "triples", you choose it. A memory_category on a triple sets the category of that fact, and a memory_category at the top level of the request sets it for every triple that has none of its own. A triple with neither is stored as knowledge.
POST /api/v1/{context_id}/facts
Authorization: Bearer <key>
Content-Type: application/json
{
"infer": "triples",
"scopes": [["org/acme/team/platform"]],
"memory_category": "knowledge",
"triples": [
{ "entity": { "type": "project", "name": "Atlas" },
"key": "launch_quarter", "value": "Q3" },
{ "entity": { "type": "project", "name": "Atlas" },
"key": "current_blocker", "value": "EU pricing review",
"memory_category": "context" }
]
}Here launch_quarter is stored as knowledge from the request default, and current_blocker as context from its own field. The accepted values are identity, knowledge and context.
Use triples for a fact that must not expire with the working set, such as a decision someone states in a meeting. A stored fact keeps its category: there is no endpoint that moves a fact to another category. Writing the same fact again as a triple does not change its category either. While a context fact is live, a triple with the same entity, key, value and scope counts as the same assertion, so Agent Memory writes nothing new and the context fact still expires on its own schedule. Write a fact as knowledge or identity when your application first learns it. See Expiry of context facts.
At a glance
| Category | Holds | Typical lifetime |
|---|---|---|
| Episodic | Raw turns / transcripts | Short-to-medium |
| Identity | Stable facts about the principal | Long |
| Knowledge | Learned / shared factual context | Medium |
| Context | Current working state | Short: expires 7 days after it was learned |
| Instructions | Behaviour preferences | Until forgotten (a change of mind is stored as a new instruction) |
| Uncertainty | Deliberate “we do not know” | Until resolved or superseded |