Appearance
Memory
system.agents.memory is the per-actor memory store. It lives in the same SQLite database as sessions and embeddings, but on different tables. Its job is to let an agent or its caller persist freeform text records, search them by content, and group them by mount and target.
What's stored
From schema.sql:22-33 (memories):
| Column | Purpose |
|---|---|
id | autoincrement primary key |
mount | the actor mount this memory belongs to |
target_key | optional: the target the memory is about |
profile_key | optional: the agency profile that wrote it |
scope | one of actor (default), subtree, class, instance, session, profile (see MemoryScope in profiles/AgencyProfile.ts:3) |
content | the memory text |
tags | JSON array of strings |
realm | optional realm tag (cross-actor grouping) |
created_at | epoch-ms |
There is also an FTS5 virtual table (memories_fts) and triggers that mirror inserts/deletes from the main table.
What's NOT stored
Memory is not the place for:
- Inference call traces (those go to observability via
actorLogand to session-levelappendActivityFrames). - Tool call records (those live in
session_messagesrows). - Embeddings of the memory content (those go to
memory_embeddingskeyed bymemory_id). - Inference credentials. Ever.
Search tiers
MemoryActor declares an accept op memory.searchTier that returns which tier is active. Three tiers exist (MemoryActor.ts and AgentsStore.ts:231-249):
| Tier | Method | When |
|---|---|---|
like | SQLite LIKE %query% | always available |
fts5 | FTS5 MATCH with BM25 ranking, Porter stemming, unicode61 tokenizer | when sqlite was built with FTS5 (hasFts5 is true) |
hybrid | Vector + FTS5, falls back to FTS5, falls back to LIKE | when EmbeddingService has a working provider |
The "search degrades gracefully" promise is enforced by checking hasFts5 and provider availability at call time.
Scope cascade
memoryBelongsToCascade in skills/MemoryCascade.ts decides whether a stored memory is visible to a given query based on its scope. The intended order (broadest to narrowest) per MemoryScope:
global > class > subtree > actor
> profile > instance
> session > noneA query at scope: 'actor' returns memories saved at actor, subtree, class, and global. A query at scope: 'session' returns only the current session's memories.
Plans
The same actor (MemoryActor) also owns plans (schema.sql:59-82) — structured work plans with steps, status (pending/in-progress/done/skipped), and execution tracking (plan_executions records who started a step, when it completed, and the output). plan.create, plan.update, plan.active, plan.complete, plan.history, plan.execute, plan.execution-complete, plan.executions are all in MemoryActor.accepts.
Audit trail
memory_access_log (schema.sql:129-138) records every cross-actor read/write. memory.audit-trail returns it, scoped to a target mount, with limit pagination. This is application-level audit — system-level observability lives in system.observability.
See also
Source:
projects/matrix-3/packages/agents/src/MemoryActor.ts:79-102(accepts),projects/matrix-3/packages/agents/src/AgentsStore.ts:182-265(memory CRUD),projects/matrix-3/packages/agents/schema.sql:22-140(tables and audit log).