Persistent Memory
Persistent Memory gives the agent a scoped memory store for facts, decisions, preferences, and reusable project context.
projectmemories are shared across sessions in the current working tree.usermemories are shared across projects for the current user.localmemories are isolated to the current session. With the SQLite backend they survive app restarts for that session and are removed when the session is deleted.
[options.persistent_memory]enabled = truebackend = "sqlite"
[options.persistent_memory.embeddings]enabled = trueread_projection = "default"write_projections = ["default"]
[[options.persistent_memory.embeddings.projections]]name = "default"provider = "local"model = "bmo-local"indexed_scopes = ["project", "user"]top_k = 10Backends
Section titled “Backends”| Backend | Storage | Use case |
|---|---|---|
sqlite | Local database (default) | Durable, private, configurable semantic search via embedding projections |
memory | In-process only | Tests, demos; cleared on exit |
supermemory | Supermemory cloud API | Cloud-backed memory; requires API key |
Privacy (Supermemory): With backend = "supermemory", memory content and metadata are sent to Supermemory’s cloud service. Use this only if you accept their terms and privacy policy. For local-only data, use sqlite or memory.
Embedding projections
Section titled “Embedding projections”With the SQLite backend, semantic search runs through named embedding
projections. Canonical memories remain in persistent_memories; each
projection stores its own derived embeddings, build state, queue, and run
history.
- Reads use one active
read_projection. - Writes can fan out to multiple
write_projectionsfor dual-write migration. - New projections backfill from canonical memory content, then drain queued
writes before they become
ready. - Read cutover is explicit, so rollback is just a routing change.
If a config still contains options.persistent_memory.vector, BMO imports
those fields into a named legacy-default compatibility projection on startup.
Prefer embeddings.projections[] for new configs.
Memory tools
Section titled “Memory tools”When enabled, the agent can call:
| Tool | Description |
|---|---|
memory_store(scope, content, type) | Save a fact, decision, or convention in project, user, or local scope |
memory_update(scope, id, content) | Replace an existing memory when a fact is corrected or superseded |
memory_search(scope, query) | Search stored memories; uses the active embedding projection when available, otherwise keyword search |
memory_list(scope) | List recent memories for a scope |
memory_forget(scope, id) | Delete a specific memory within the current project, user identity, or session |
Proactive memory writes
Section titled “Proactive memory writes”BMO can write memories during a conversation without waiting for an explicit “remember this” instruction. The agent is prompted to store durable information when it detects:
- Corrections - the user corrects the agent’s behavior, output, or assumption.
- Preferences - the user states a coding, communication, tooling, or workflow preference.
- Project decisions - the conversation settles an architecture, dependency, naming, or process decision that should apply later.
These writes use the same memory_store tool and scope routing as explicit
memory requests. For the first few proactive writes in a session, BMO may
include a short inline note so the behavior is visible. After that, proactive
writes continue more quietly and remain inspectable through the activity drawer
and /memory viewer.
Auto-retain runs after completed turns as a safety net for corrections, preferences, and decisions the agent did not store during the turn. It is capped and selective; it is not a transcript recorder.
Memory entry layout
Section titled “Memory entry layout”Good memory entries are short, typed, and easy to reuse:
- Keep each entry to one durable fact or decision, usually one or two sentences.
- Phrase entries as actionable positives, such as “prefer snake_case for config keys.”
- Use the most specific type:
preference,decision,convention,fact, orcontext. - Search before storing. If an older memory covers the same topic, update or replace it instead of adding a duplicate.
- Choose the narrowest useful scope:
projectfor the current codebase,userfor cross-project preferences, andlocalfor session-only context.
TUI viewer
Section titled “TUI viewer”The /memory slash command opens an in-TUI memory manager. With SQLite-backed
memory enabled it includes:
Memoriesfor per-scope inspection and deletionEmbeddingsfor listing projections and managing create/rebuild/cutoverMigrationfor queue lag, recent runs, and projection status
When persistent memory is disabled it still shows status, but management controls are unavailable.
Options
Section titled “Options”| Option | Default | Description |
|---|---|---|
enabled | false | Enable persistent memory |
backend | sqlite | Storage backend: sqlite, memory, or supermemory (cloud; requires API key) |
supermemory.api_key | (env) | Supermemory API key; can be set here or via SUPERMEMORY_API_KEY (prefer env for secrets) |
embeddings.enabled | false | Enable named embedding projections for the SQLite backend |
embeddings.read_projection | first enabled projection | Active semantic read projection |
embeddings.write_projections | [read_projection] | Projections that receive new writes |
embeddings.auto_backfill | true | Resume/build projections automatically on startup |
embeddings.fallback_to_lexical | true | Fall back to keyword search when semantic search is unavailable |
embeddings.projections[].name | none | Projection name used for routing and migration |
embeddings.projections[].provider | none | Embedding provider; supported values in v1: openai, cohere, local |
embeddings.projections[].model | none | Embedding model name |
embeddings.projections[].indexed_scopes | ["project", "user"] | Scopes included in this projection |
embeddings.projections[].top_k | 10 | Maximum semantic matches to score before returning results |
embeddings.projections[].dimension | provider default | Optional embedding dimension override |
Projection config is only supported with the sqlite backend. BMO validates
the provider at startup and rejects projection config on memory and
supermemory.
Legacy compatibility options:
| Option | Default | Description |
|---|---|---|
vector.enabled | false | Imported into the compatibility projection’s enabled flag |
vector.embedding_provider | none | Imported into the compatibility projection’s provider name |
vector.embedding_model | none | Imported into the compatibility projection’s model id |
vector.indexed_scopes | all scopes | Imported into the compatibility projection’s indexed scopes |
vector.top_k | 10 | Imported into the compatibility projection’s semantic result cap |
Scope behavior
Section titled “Scope behavior”projectis keyed from the current working directory.useris keyed from the authenticated principal when available, otherwise the local BMO user namespace.localis keyed from the active session ID.
Use cases
Section titled “Use cases”- Project conventions — store coding standards so they’re available every session
- Decisions log — record architectural choices for the agent to reference
- Cross-session context — anything you’d otherwise have to paste into every new session
Related
Section titled “Related”Memories are one of the sources that Adaptive Context can select and rank when building the user-message context block; enabling both can improve which memories are included in long sessions.