# Memory SDK OpenClaw's memory system lives in a standalone package (`packages/memory-host-sdk`) that exposes composable engines for storage, embeddings, query processing, and foundation utilities. The SDK defines a clear host-engine boundary: the host application consumes the SDK surface, while the SDK encapsulates all storage, indexing, and retrieval logic behind exported contracts. *** ## Package Structure The SDK entry point (`engine.ts`) re-exports four focused engine modules: ```typescript export * from "./engine-foundation.js"; export * from "./engine-storage.js"; export * from "./engine-embeddings.js"; export * from "./engine-qmd.js"; ``` Each engine is a self-contained barrel export covering one concern. New code is directed to the focused subpaths rather than the aggregate surface. *** ## Engine Storage The storage engine (`engine-storage.ts`) provides the persistence and retrieval primitives built on SQLite with the `sqlite-vec` vector extension. ### Key Exports - **`MemoryChunk`** and **`MemoryFileEntry`** — the core data types. A chunk is an indexed segment of content with metadata; a file entry represents a source document on disk. - **`buildFileEntry`** / **`buildMultimodalChunkForIndexing`** — constructors for creating index-ready records. - **`chunkMarkdown`** — splits markdown content into semantically coherent chunks for embedding. - **`cosineSimilarity`** — vector distance computation for retrieval ranking. - **`parseEmbedding`** — deserializes stored embedding vectors. - **`ensureMemoryIndexSchema`** — creates or migrates the SQLite schema (tables, FTS indexes, vector columns). - **`loadSqliteVecExtension`** — loads the `sqlite-vec` native extension into the SQLite connection. - **`requireNodeSqlite`** — resolves the Node.js SQLite driver. - **`readMemoryFile`** — reads a memory file from disk with safety checks. - **`resolveMemoryBackendConfig`** — resolves backend-specific configuration (SQLite paths, vector dimensions, etc.). ### Storage Architecture The storage layer uses SQLite as a single-file database with the `sqlite-vec` extension providing vector column support. Memory chunks are stored alongside their embeddings in the same database, enabling hybrid queries that combine full-text search with cosine vector similarity in a single SQL statement. This mirrors the approach used by ZeroClaw's SQLite backend (see [[ZeroClaw/Memory]]). ```typescript // Types exported for consumers type MemoryChunk = { /* chunk content, metadata, embedding vector */ }; type MemoryFileEntry = { /* source file path, hash, modification time */ }; type MemorySearchResult = { /* ranked results with scores and source info */ }; ``` *** ## Engine Embeddings The embeddings engine (`engine-embeddings.ts`) provides a pluggable embedding provider system with six built-in backends and batch processing utilities. ### Embedding Providers | Provider | Default Model | Module | |----------|--------------|--------| | Local | `DEFAULT_LOCAL_MODEL` | `embeddings.js` | | Gemini | `DEFAULT_GEMINI_EMBEDDING_MODEL` | `embeddings-gemini.js` | | Mistral | `DEFAULT_MISTRAL_EMBEDDING_MODEL` | `embeddings-mistral.js` | | Ollama | `DEFAULT_OLLAMA_EMBEDDING_MODEL` | `embeddings-ollama.js` | | OpenAI | `DEFAULT_OPENAI_EMBEDDING_MODEL` | `embeddings-openai.js` | | Voyage | `DEFAULT_VOYAGE_EMBEDDING_MODEL` | `embeddings-voyage.js` | ### Provider Interface ```typescript // Core provider contract type MemoryEmbeddingProvider = { name: string; // ... embedding computation methods }; type MemoryEmbeddingProviderAdapter = { // Adapts raw provider to the SDK contract }; // Factory and registry function getMemoryEmbeddingProvider(name: string): MemoryEmbeddingProvider; function listMemoryEmbeddingProviders(): string[]; ``` ### Batch Processing Three batch helpers handle high-throughput embedding jobs for initial indexing or re-indexing: - **`runGeminiEmbeddingBatches`** — Gemini-specific batching with rate limit handling. - **`runOpenAiEmbeddingBatches`** — OpenAI batch API integration (`OPENAI_BATCH_ENDPOINT`). - **`runVoyageEmbeddingBatches`** — Voyage AI batch processing. ### Safety Utilities - **`enforceEmbeddingMaxInputTokens`** — truncates input to provider-specific token limits. - **`estimateStructuredEmbeddingInputBytes`** / **`estimateUtf8Bytes`** — byte estimation for payload sizing. - **`hasNonTextEmbeddingParts`** — detects multimodal content that requires special handling. *** ## Engine Foundation The foundation engine (`engine-foundation.ts`) re-exports core utilities from the main OpenClaw application that the memory system depends on. Rather than duplicating logic, the SDK imports these through relative paths to the monorepo `src/` directory. ### Key Capabilities - **Agent Scope Resolution**: `resolveAgentDir`, `resolveAgentWorkspaceDir`, `resolveDefaultAgentId`, `resolveSessionAgentId` — determines which agent's memory space to operate on. - **Memory Search Configuration**: `resolveMemorySearchConfig` with `ResolvedMemorySearchConfig` type — controls search behavior (result limits, relevance thresholds). - **Configuration Loading**: `loadConfig`, `resolveStateDir` — reads OpenClaw configuration and state directories. - **Session Integration**: `resolveSessionTranscriptsDirForAgent`, `onSessionTranscriptUpdate` — watches for new conversation transcripts to index into memory. - **File Safety**: `writeFileWithinRoot` — prevents path traversal when writing memory files. - **Secrets**: `hasConfiguredSecretInput`, `normalizeResolvedSecretInputString` — resolves API keys for embedding providers. *** ## Engine QMD (Query Processing) The QMD engine (`engine-qmd.ts`) handles query decomposition, keyword extraction, and scope filtering before executing memory searches. ### Query Pipeline - **`extractKeywords`** — pulls meaningful terms from a natural language query, filtering stop words via `isQueryStopWordToken`. - **`parseQmdQueryJson`** — parses structured query results (type `QmdQueryResult`) from the QMD binary. - **Scope Filtering**: `deriveQmdScopeChannel`, `deriveQmdScopeChatType`, `isQmdScopeAllowed` — restricts search results to the appropriate channel and conversation type. - **Session Files**: `buildSessionEntry`, `listSessionFilesForAgent`, `sessionPathForFile` — manages the session transcript files that feed into memory indexing. - **CLI Integration**: `checkQmdBinaryAvailability`, `resolveCliSpawnInvocation`, `runCliCommand` — interfaces with an external QMD binary for query processing. *** ## Integration Pattern The SDK is consumed by the host application through the aggregate `engine.ts` export. The boundary is clear: - **Host responsibility**: Decides when to index, when to search, which agent scope to use, and how to present results. - **SDK responsibility**: Handles all storage I/O, embedding computation, vector indexing, query processing, and schema management. The typical flow: 1. **Initialization**: Host calls `resolveMemoryBackendConfig` to set up the storage backend. 2. **Indexing**: Host uses `engine-embeddings` to generate vectors and `engine-storage` to persist chunks. 3. **Retrieval**: Host uses `engine-qmd` to process the query, then performs a similarity search via `engine-storage`. This separation means the memory engine can be tested independently, and the host can swap backends (e.g., different SQLite configurations, different embedding providers) without changing application logic. *** ## Relevance to Luna Luna's [[Memory]] module defines an `IMemoryStore` interface but the current file-based implementation only supports writing — there is no recall or search capability. ### Patterns to Adopt - **Composable Engine Architecture**: Separating storage, embeddings, and query processing into distinct layers is a clean pattern for Luna. Rather than building a monolithic memory service, Luna could define `IMemoryStorage`, `IEmbeddingProvider`, and `IQueryProcessor` interfaces that compose into a full memory system. - **SQLite + Vector Extension**: Both OpenClaw and ZeroClaw use SQLite with vector extensions for hybrid search. Luna already references SQLite packages — finishing `SqliteMemoryStore` with this architecture is the natural path. - **Pluggable Embedding Providers**: Luna should support multiple embedding backends from the start. The factory pattern (`getMemoryEmbeddingProvider(name)`) maps to C# service registration. - **Batch Processing**: For initial indexing or re-indexing of conversation history, batch embedding helpers prevent rate-limiting issues. - **Query Preprocessing**: Keyword extraction and scope filtering before search improves relevance. Luna should implement query expansion as a pipeline step before hitting the vector store. ### Key Difference OpenClaw's SDK is a package boundary within a monorepo — it re-exports from the main `src/` tree through barrel files. Luna, as a single compiled application, would implement this as a set of interfaces within a `Memory` namespace rather than a separate package. The architectural principle (composable engines with clear contracts) translates directly to C# DI registration.