Memory API Service
Relevant source files
The following files were used as context for generating this wiki page:
The Memory API Service provides RAG (Retrieval-Augmented Generation) capabilities for the Nyansa project by transforming an Obsidian vault into a searchable vector index. It scans Markdown notes, parses their structure, generates embeddings using Ollama, and stores the resulting vectors in Qdrant for semantic search.
Sources: services/memory-api/README.md:3-8, README.md:20-24
System Architecture
The service operates as a TypeScript/Node.js application within the Nyansa Docker network. It interacts with three main external components: a local Obsidian vault for source data, Ollama for embedding generation, and Qdrant for vector storage and retrieval.
Data Flow Overview
The diagram shows the transition from raw Markdown notes to searchable vector points and the subsequent search flow.
Sources: services/memory-api/README.md:79-90, README.md:46-77
Core Modules
Note Parsing
The parser extracts structured information from Markdown files, including YAML frontmatter, titles, tags, and wikilinks. It resolves titles by checking the frontmatter title field, then the first H1 heading, and finally the filename.
- Tags: Collected from frontmatter and inline
#tags, then normalized to lowercase. - Links: Identifies
[[wikilinks]]and![[embeds]]. - Frontmatter: Handles YAML blocks delimited by
---or....
Sources: services/memory-api/src/markdown/parse.ts:10-27, services/memory-api/src/markdown/frontmatter.ts:15-21
Heading-Aware Chunking
The chunker splits notes into sections based on ATX headings. It packs paragraphs into chunks up to a configurable maxChars limit (default 1500) while attempting to keep code blocks whole.
The chunking process ensures that each chunk retains its context via a "heading path" (e.g., Setup > Docker).
Sources: services/memory-api/src/markdown/chunk.ts:25-45, services/memory-api/src/domain.ts:32-38
Ingestion Pipeline
The Ingestor manages the lifecycle of vault indexing. It supports incremental (default) and full modes. In incremental mode, it uses SHA-256 hashes of note content and an index_version to determine which files require re-indexing.
Sources: services/memory-api/src/ingest/ingest.ts:55-75, services/memory-api/README.md:26-34
API Endpoints
The service requires a Bearer token for all endpoints except /health.
| Endpoint | Method | Description |
|---|---|---|
/health | GET | Returns 200 if Ollama and Qdrant are reachable. |
/ingest | POST | Triggers vault indexing. Supports full or incremental. |
/search | POST | Performs semantic search. Accepts query, limit, and tags. |
Sources: services/memory-api/src/app.ts:74-118, services/memory-api/README.md:14-65
Configuration
The service is configured via environment variables, validated by Zod at startup.
| Variable | Default | Description |
|---|---|---|
MEMORY_API_TOKEN | (Required) | Security token (minimum 32 characters). |
QDRANT_API_KEY | (Required) | API key for the Qdrant vector store. |
VAULT_PATH | /vault | Path to the Obsidian vault mount. |
EMBEDDING_MODEL | nomic-embed-text | Ollama model used for embeddings. |
CHUNK_MAX_CHARS | 1500 | Maximum character length for a single chunk. |
Sources: services/memory-api/src/config.ts:3-15, services/memory-api/README.md:105-117
Data Model
Each chunk is stored in Qdrant as a point with the following payload structure:
| Field | Type | Description |
|---|---|---|
path | string | Vault-relative path to the note. |
title | string | Resolved title of the note. |
tags | string[] | Deduplicated tags from the note. |
section | string | Full heading path for the chunk. |
text | string | The actual text content of the chunk. |
note_hash | string | SHA-256 hash used for change detection. |
Sources: services/memory-api/src/domain.ts:41-57, services/memory-api/README.md:95-103
The Memory API Service enables efficient semantic retrieval of Obsidian notes by maintaining a synchronized vector representation of the vault, allowing other Nyansa components (like n8n workflows) to perform source-backed queries.