Top-level module for the Nous Memory System.
Provides persistent memory for agents with hybrid text + vector search, temporal decay, importance weighting, and flexible scoping.
Quick Start
# Minimal setup (ETS store, keyword-only search)
agent = Agent.new("openai:gpt-4",
plugins: [Nous.Plugins.Memory],
deps: %{memory_config: %{store: Nous.Memory.Store.ETS}}
)Architecture
Three layers, all plain modules and structs (no GenServer):
- Data Layer —
Entry(struct),Store(behaviour + backends) - Search Layer —
Search(orchestrator),Scoring(RRF, decay) - Integration —
Plugins.Memory(plugin),Memory.Tools(agent tools)
Store Backends
| Backend | Text search | Vector search | Deps |
|---|---|---|---|
Store.ETS | Jaro distance | None | None |
Store.SQLite | FTS5 (BM25) | Cosine similarity, computed in Elixir over every stored embedding | exqlite |
Store.DuckDB | ILIKE (the fts extension is loaded best-effort) | list_cosine_similarity in SQL | duckdbex |
No shipped backend does indexed (ANN) vector search — both vector paths above are full scans over the entries that have an embedding. That is usually the right trade at the corpus sizes agent memory reaches, but it is a scan, and it is worth knowing before you point one at a million rows.
Need something else — Tantivy, HNSW, a vector database, your own search cluster?
Nous.Memory.Store is a documented extension point: implement the behaviour in
your own application, pass the module as :store, and every consumer treats it
like a built-in. See that module for the contract, Nous.Memory.Store.Results
for the shared retrieval tail, and Nous.Memory.Store.Conformance for the
contract suite Nous runs against its own backends.
Embedding Providers
| Provider | Description | Deps |
|---|---|---|
Embedding.Bumblebee | Local on-device (Qwen 0.6B) | bumblebee, exla |
Embedding.OpenAI | OpenAI text-embedding-3-small | None (uses Req) |
Embedding.Local | Ollama / vLLM / LMStudio | None (uses Req) |
No embedding configured = keyword-only search. The system never fails if no embedding provider is set.
Summary
Functions
Search memories directly (bypassing agent tools).
Store a memory entry directly (bypassing agent tools).
Validate a memory configuration map.
Functions
@spec search(module(), term(), String.t(), module() | nil, keyword()) :: {:ok, [{Nous.Memory.Entry.t(), float()}]}
Search memories directly (bypassing agent tools).
Examples
{:ok, results} = Nous.Memory.search(Nous.Memory.Store.ETS, store_state, "dark mode")
@spec store(module(), term(), Nous.Memory.Entry.t()) :: {:ok, term()} | {:error, term()}
Store a memory entry directly (bypassing agent tools).
Examples
{:ok, store_state} = Nous.Memory.Store.ETS.init([])
entry = Nous.Memory.Entry.new(%{content: "User likes dark mode"})
{:ok, store_state} = Nous.Memory.store(Nous.Memory.Store.ETS, store_state, entry)
Validate a memory configuration map.
Returns {:ok, config} with defaults applied, or {:error, reason}.