Expand description
§VelesDB-memory
Local-first memory layer for AI agents, exposed through a single MCP
server. This crate is the domain core: it maps nine memory operations onto
VelesDB’s in-core Agent Memory SDK.
| Operation | Meaning |
|---|---|
remember | store a fact (+ optional links to other memories) |
recall | semantic retrieval of similar facts |
recall_where | semantic retrieval filtered by metadata |
recall_fused | vector + graph fused retrieval |
relate | create a typed edge between two memories |
forget | delete a memory |
why | recall + multi-hop graph traversal |
feedback | reinforce or penalize a memory after use |
remember_extracted | extract facts from raw text and auto-wire the graph |
§License boundary (non-negotiable)
This crate exposes memory semantics only (results), never raw database
capabilities (query(velesql), create_collection, upsert(vectors),
traverse(graph)). Exposing the raw engine would constitute a “Substantial
Set” of the Software’s features and breach the VelesDB Core License 1.0
(§1, No Hosted or Managed Service). See VISION.md §5 and PLAN.md Phase 4A.
§Generics at the core, dyn at the edges (doctrine)
Two dispatch styles coexist in this crate, and the split is a rule, not an accident of history:
- Compile-time seams are generic parameters.
service::MemoryService<E: Embedder, S: FactStore>is monomorphized over its embedder and its storage backend: each consumer (native daemon, WASM binding) compiles exactly the backend it uses, recall paths carry no vtable, and a backend that cannot support an operation fails at compile time instead of at a customer. Since #1959 the storage surface is four facets (FactStore,RecallStore,GraphStore,ColumnStore;MemoryStoreis their sum, kept as an alias), and each service method carries the bound of the facet it consumes — so “cannot support” is now judged per capability, not per backend. - Runtime choices are type-erased once, at the edge. A backend picked
by configuration —
VELESDB_MEMORY_EMBEDDER, anextractorargument, a bring-your-own reranker — crosses into the crate asDynEmbedder,DynExtractororDynReranker, built once at startup. The erasure happens at construction, never inside an operation.
A new abstraction follows the same test: chosen at compile time → generic
parameter; chosen by configuration → a Dyn* alias resolved at startup.
And an adapter over one of these traits forwards the whole trait —
partial forwarding is how a binding silently loses a capability the server
already publishes (the #1690–#1692 gap family), and is rejected in review.
The storage facets refine the unit that rule applies to: an adapter picks
which facets it serves, but each facet it implements is forwarded whole.
Re-exports§
pub use context::ContextCompiler;pub use dated_context::format_dated_context;pub use dated_context::DatedContext;pub use embedder::select_embedder;pub use embedder::DynEmbedder;pub use embedder::EmbedError;pub use embedder::Embedder;pub use embedder::EmbedderSelection;pub use embedder::HashEmbedder;pub use embedder::HASH_EMBEDDER_NOTICE;pub use embedder::OllamaEmbedder;pub use embedder::OpenAiEmbedder;pub use embedder::DEFAULT_OLLAMA_MODEL;pub use embedder::DEFAULT_OLLAMA_URL;pub use error::ErrorCategory;pub use error::MemoryError;pub use extract::select_extractor;pub use extract::DynExtractor;pub use extract::ExtractError;pub use extract::ExtractedAttribute;pub use extract::ExtractedFact;pub use extract::ExtractedRelation;pub use extract::Extraction;pub use extract::Extractor;pub use extract::ExtractorSelection;pub use extract::OutlineExtractor;pub use extract::OllamaExtractor;pub use extract::OpenAiExtractor;pub use http_client::Auth;pub use http_client::HttpJsonClient;pub use mcp::McpServer;pub use model::column_value_matches;pub use model::BoundedMemoryEdges;pub use model::ColumnFilter;pub use model::ColumnOp;pub use model::EntityProfile;pub use model::EntityRelation;pub use model::Explanation;pub use model::FusionOptions;pub use model::Link;pub use model::MemoryEdge;pub use model::MemoryNode;pub use model::Recollection;pub use model::RememberedExtraction;pub use model::UnrelateOutcome;pub use remote_endpoint::embedder_env_endpoint;pub use remote_endpoint::role_auth;pub use remote_endpoint::RemoteEndpoint;pub use rerank::DynReranker;pub use rerank::RerankError;pub use rerank::Reranker;pub use service::AutographWorkerHandle;pub use service::MemoryService;pub use service::Metadata;pub use storage::NativeStore;pub use storage::ColumnStore;pub use storage::FactStore;pub use storage::GraphStore;pub use storage::MemoryStore;pub use storage::RecallStore;pub use storage::AUTO_DATE_FIELD;
Modules§
- column_
filter_ conformance - The ONE
ColumnFilterconformance table bothMemoryStorebackends run, so the native (VelesQL-translating) and WASM (payload-testing) paths cannot drift apart again (#1759). Deliberately NOT target-gated: the WASM backend is one of the two that must run it. The ONE table everyMemoryStorebackend must satisfy forColumnFilter, and the fixture it runs against. - config
- The optional TOML configuration file: one place to set every knob, with
command line > environment > file > defaultprecedence. Native-only — it reads the filesystem. The optional TOML configuration file: one place to set every knob. - context
- The deterministic context compiler (EPIC-P-070): classify, dedup, and pack
caller-supplied context fragments under a token budget — no LLM, no cloud,
every decision auditable. Gated behind the default
contextfeature. The deterministic context compiler (EPIC-P-070). - dated_
context - Format recalled facts as a chronological, date-prefixed timeline with a
“now” anchor — the dated-context representation measured to lift temporal
question answering, shipped as product behavior rather than a harness prompt.
Dated context: turn recalled facts into a chronological, date-prefixed
timeline with a “now” anchor — the representation measured to lift temporal
question answering (the
examples/locomotemporal ablation: +33.6pp, McNemar p=1.8e-28). This ships that representation as product behavior so a caller reproduces it through the installed API instead of re-implementing the formatting in a prompt. - embedder
- Pluggable text → vector embedding.
- embedding_
provenance - Which embedding model filled a store, and whether the configured one can
still read it. Gated on
persistencebecause an unrecorded store is a directory on disk — see the module docs for why the backend is deliberately not part of the record. What embedder filled this store, and whether the configured one can still read it (#1751, arbitration A1). - error
- Error type for the memory layer.
- export
- Export a store’s facts as JSONL — one JSON object per line — WITHOUT an embedder.
- extract
- Optional text → facts + entities extraction, the layer that makes the graph self-build.
- http_
client - Authenticated JSON over HTTP: the transport under every remote inference backend, with no knowledge of role or vendor. Authenticated JSON over HTTP — the transport layer under every remote inference backend.
- limits
- Resource caps (DoS limits) shared by every adapter — the single source of
truth for fact size, recall limit, and
whyhop depth. Resource caps shared by every adapter (the MCP server and the language bindings). - logging
- Per-request observability, gated by
VELESDB_MEMORY_LOG(#1780): silent by default, stderr only, never a payload. Rides themcpfeature with the server it observes. Per-request observability, gated byVELESDB_MEMORY_LOG(#1780). - mcp
- The MCP server transport. Gated behind the default
mcpfeature so library consumers (e.g. the language bindings) can depend on the memory core without pulling thermcp/tokioserver stack. MCP transport: exposes the memory service as MCP tools over stdio. - migration
- Read-only diagnosis of a store an embedding-model change made unopenable, and the feasibility proof the rebuild depends on (#1762). Never writes to the store it inspects. Read-only diagnosis of a store that a changed embedding model has made unopenable, and the feasibility proof the rebuild depends on (#1762, PR A).
- model
- The domain data model — the value types the memory layer exchanges
(
Link,Recollection,ColumnFilter,Explanation, …), separate from the service that computes them. Domain data model: the request/response value types of the memory layer. - reachability
- Is a configured remote inference backend actually reachable? (#1751 D2)
- remote_
endpoint - Where a remote embedding/extraction backend’s URL, model and credential come from, resolved from the environment once so the daemon and the language bindings read the same variables the same way (#1886). Where a remote embedding/extraction backend’s URL, model and credential come from — one shape for both roles, on purpose. The two were configured differently for historical reasons only — extraction by role, embedding by product — and an operator who has configured one should not have to learn the other (#1751, arbitration C1).
- rerank
- Optional second-stage re-scoring of a fused recall pool (bring your own
cross-encoder/LLM). Never wired in by default — see
rerank::Reranker. Optional second-stage re-scoring of aMemoryService::recall_fusedcandidate pool, the layer that lifts a ranking miss (a relevant fact deep in the pool, below the fusion cutoff) into the finalk— the lever validated on the LoCoMo ceiling diagnostic (multi-hop recall@8 = 50%, recall@64 = 89%: the gold fact is IN the pool, just outranked). - service
- The memory service: five operations over the in-core Agent Memory SDK.
- storage
- The storage backend abstraction —
storage::MemoryStoreand the default, file-backedstorage::NativeStore. ImplementMemoryStoreto run the wedge over a different backend (e.g. an in-memory one for WASM). Storage backend abstraction forcrate::service::MemoryService.
Constants§
- DEFAULT_
DIMENSION - Default embedding dimension — the single source of truth, taken from the
SDK’s own default so the server, library, and tests never restate the
value.
velesdb_core::agent(where the canonical constant lives) is itselfpersistence-gated, so apersistence-free build (e.g.velesdb-wasm) falls back toFALLBACK_DIMENSION.