Build web apps, agents, and AI applications with the Memvid Node.js SDK. Native bindings deliver blazing-fast performance with a TypeScript-first API.
Installation
npm install @memvid/sdk
# or
pnpm add @memvid/sdk
# or
yarn add @memvid/sdk
Requirements: Node.js 18+, macOS/Linux/Windows. Native bindings included - no extra dependencies needed.
create() will OVERWRITE existing files without warning!| Function | Purpose | If File Exists | Parameter Order |
|---|
create(path, kind) | Create new .mv2 file | DELETES all data | path first, then kind |
use(kind, path) | Open existing .mv2 file | Preserves data | kind first, then path |
Always check if the file exists before choosing — see example below.
Quick Start
import { create, use } from '@memvid/sdk';
import { existsSync } from 'fs';
const path = 'knowledge.mv2';
// CRITICAL: Check if file exists to avoid data loss!
const mem = existsSync(path)
? await use('basic', path) // Open existing file (kind first!)
: await create(path, 'basic'); // Create new file (path first!)
// Add documents
await mem.put({
title: 'Meeting Notes',
label: 'notes',
text: 'Alice mentioned she works at Anthropic...'
});
// Search works immediately
const results = await mem.find('who works at AI companies?', { k: 5, mode: 'lex' });
console.log(results.hits);
// Ask questions
const answer = await mem.ask('What does Alice do?', { k: 5, mode: 'lex' });
console.log(answer.answer);
// Seal when done (commits changes)
await mem.seal();
API Reference
| Category | Methods | Description |
|---|
| File Operations | create, open, close, use | Create, open, close memory files |
| Data Ingestion | put, putMany, putFile, putFiles | Add documents with embeddings |
| Search | find, ask, vecSearch, timeline | Query your memory |
| Corrections | correct, correctMany | Store ground truth with retrieval boost |
| Memory Cards | memories, state, enrich, addMemoryCards | Structured fact extraction |
| Tables | putPdfTables, listTables, getTable | PDF table extraction |
| Sessions | sessionStart, sessionEnd, sessionReplay | Time-travel debugging |
| Tickets | syncTickets, currentTicket, getCapacity | Capacity management |
| Security | lock, unlock, lockWho, lockNudge | Encryption and access control |
| Utilities | verify, doctor, maskPii | Maintenance and utilities |
Core Functions
File Operations
import { create, open, verifyMemvid, doctorMemvid, info } from '@memvid/sdk';
// Create new memory file
const mem = await create('project.mv2');
// Open existing memory
const existing = await open('project.mv2');
// With options
const mem = await create('project.mv2', 'basic', {
enableLex: true, // Enable lexical index
enableVec: true, // Enable vector index
memoryId: 'mem_abc' // Bind to dashboard
});
// Verify file integrity
await verifyMemvid('project.mv2', { deep: true });
// Repair and optimize
await doctorMemvid('project.mv2', {
rebuildTimeIndex: true,
rebuildVecIndex: true,
vacuum: true
});
// Get SDK info
const sdkInfo = info();
Framework Adapters
Choose an adapter for your framework:
import { use } from '@memvid/sdk';
// Available adapters
const mem = await use('basic', 'file.mv2');
const langchain = await use('langchain', 'file.mv2');
const llamaindex = await use('llamaindex', 'file.mv2');
const vercelai = await use('vercel-ai', 'file.mv2');
const openai = await use('openai', 'file.mv2');
const crewai = await use('crewai', 'file.mv2');
const autogen = await use('autogen', 'file.mv2');
const haystack = await use('haystack', 'file.mv2');
const langgraph = await use('langgraph', 'file.mv2');
const semantickernel = await use('semantic-kernel', 'file.mv2');
const googleadk = await use('google-adk', 'file.mv2');
Auto-Embedding
The SDK automatically enables vector embeddings when OPENAI_API_KEY is set in your environment:
// Embeddings are automatically enabled using text-embedding-3-small
await mem.put({ title: 'Doc', text: 'Content here' });
How it works:
- If
OPENAI_API_KEY is set and enableEmbedding is not specified, embeddings are auto-enabled
- Uses OpenAI’s
text-embedding-3-small model (1536 dimensions)
- If no API key is present and no model specified, falls back to local
bge-small (384 dimensions)
| Environment | Default Behavior |
|---|
OPENAI_API_KEY set | Auto-enable with text-embedding-3-small |
| No API key | Local bge-small if enableEmbedding: true |
Explicit enableEmbedding: false | No embeddings |
Set OPENAI_API_KEY once in your environment and the SDK handles the rest. No need to pass enableEmbedding: true or specify models.
Data Ingestion
put() - Add Single Document
await mem.put({
// Required
title: 'Document Title',
// Content (one of these)
text: 'Document content...',
file: '/path/to/document.pdf',
// Optional
uri: 'mv2://docs/intro',
tags: ['api', 'v2'],
labels: ['public', 'reviewed'],
kind: 'markdown',
track: 'documentation',
metadata: { author: 'Alice', version: '2.0' },
// Embeddings
enableEmbedding: true,
embeddingModel: 'bge-small', // or 'openai', 'nomic', etc.
vectorCompression: true, // 16x compression with PQ
// Behavior
autoTag: true, // Auto-generate tags
extractDates: true // Extract date mentions
});
putMany() - Batch Ingestion
const docs = [
{ title: 'Doc 1', text: 'First document content' },
{ title: 'Doc 2', text: 'Second document content' },
{ title: 'Doc 3', text: 'Third document content' }
];
const frameIds = await mem.putMany(docs, {
enableEmbedding: true,
compressionLevel: 3,
embedder: openaiEmbeddings // Custom embedder
});
putFile() - Document Parsing
Ingest documents directly from files. Supports PDF, DOCX, XLSX, PPTX, and more. The SDK automatically extracts text content and creates searchable frames.
// Single file ingestion
const frames = await mem.putFile('/path/to/report.pdf');
console.log(`Ingested ${frames.length} frames from PDF`);
// With options
const frames = await mem.putFile('/path/to/presentation.pptx', {
chunkSize: 1000, // Characters per chunk
chunkOverlap: 200, // Overlap between chunks
enableEmbedding: true, // Generate embeddings
embeddingModel: 'bge-small'
});
// Excel/XLSX files
const frames = await mem.putFile('/path/to/data.xlsx');
// Each sheet becomes searchable content
// Word documents
const frames = await mem.putFile('/path/to/document.docx');
putFiles() - Batch Document Ingestion
Ingest multiple documents at once:
const files = [
'/path/to/report.pdf',
'/path/to/slides.pptx',
'/path/to/data.xlsx',
'/path/to/notes.docx'
];
const allFrames = await mem.putFiles(files, {
chunkSize: 1000,
enableEmbedding: true
});
console.log(`Total frames: ${allFrames.length}`);
Supported Formats:
- PDF - Text extraction with page-aware chunking
- DOCX - Microsoft Word documents
- XLSX - Excel spreadsheets (all sheets, formulas evaluated)
- PPTX - PowerPoint presentations (slide text and notes)
No extra dependencies required - document parsing is built into the native bindings.
For XLSX files with formulas, the SDK extracts the calculated values, not the formula text. This ensures searchable, meaningful content.
Search & Retrieval
find() - Hybrid Search
// Simple search
const results = await mem.find('budget projections');
// With options
const results = await mem.find('financial outlook', {
mode: 'auto', // 'lex', 'sem', 'auto', 'clip'
k: 10, // Number of results
snippetChars: 480, // Snippet length
scope: 'track:meetings', // Scope filter
// Access control (ACL)
// In "enforce" mode, tenantId is required.
aclContext: { tenantId: 'tenant-123', roles: ['finance'] },
aclEnforcementMode: 'enforce',
// Adaptive retrieval
adaptive: true,
minRelevancy: 0.5,
maxK: 100,
adaptiveStrategy: 'combined', // 'relative', 'absolute', 'cliff', 'elbow'
// Time-travel
asOfFrame: 100,
asOfTs: 1704067200,
// Custom embeddings
embedder: customEmbedder,
queryEmbeddingModel: 'openai'
});
console.log(results.hits);
Query Syntax: Multi-word queries use OR logic by default for better recall. Use AND for intersection: "machine AND learning". Use quotes for exact phrases: '"machine learning"'.
Permission-Aware Retrieval (ACL)
See Permission-Aware Retrieval (ACL) for the full model.
At a high level:
- Write per-frame ACL metadata during ingestion (
metadata.acl_*)
- Pass
aclContext + aclEnforcementMode: 'enforce' to find() / ask()
import { getAclScopeFromApiKey, aclContextFromScope } from '@memvid/sdk';
const scope = await getAclScopeFromApiKey();
const aclContext = aclContextFromScope(scope);
const hits = await mem.find('budget', {
mode: 'lex',
k: 5,
aclContext,
aclEnforcementMode: 'enforce',
});
ask() - LLM Q&A
const answer = await mem.ask('What was decided about the budget?', {
k: 8,
mode: 'auto',
// LLM settings
model: 'gpt-4o-mini',
modelApiKey: process.env.OPENAI_API_KEY,
llmContextChars: 120000,
// Privacy
maskPii: true,
// Time filters
since: 1704067200,
until: 1706745600,
// Options
contextOnly: false, // Set true to skip synthesis
returnSources: true, // Include source documents
// Adaptive retrieval
adaptive: true,
minRelevancy: 0.5,
// Access control (ACL)
aclContext: { tenantId: 'tenant-123', roles: ['finance'] },
aclEnforcementMode: 'enforce',
});
console.log(answer.answer);
console.log(answer.sources);
vecSearch() - Pure Vector Search
const results = await mem.vecSearch('query', queryEmbedding, {
k: 10,
adaptive: true,
minRelevancy: 0.7
});
Grounding & Hallucination Detection
The ask() response includes a grounding object that measures how well the answer is supported by context:
const answer = await mem.ask('What is the API endpoint?', {
model: 'gpt-4o-mini',
modelApiKey: process.env.OPENAI_API_KEY
});
// Check grounding quality
console.log(answer.grounding);
// {
// score: 0.85,
// label: 'HIGH', // 'LOW', 'MEDIUM', or 'HIGH'
// sentence_count: 3,
// grounded_sentences: 3,
// has_warning: false,
// warning_reason: undefined
// }
// Check if follow-up is needed
if (answer.follow_up?.needed) {
console.log('Low confidence:', answer.follow_up.reason);
console.log('Try these instead:', answer.follow_up.suggestions);
}
Grounding Fields:
| Field | Type | Description |
|---|
score | number | Grounding score from 0.0 to 1.0 |
label | string | Quality label: LOW, MEDIUM, or HIGH |
sentence_count | number | Sentences in the answer |
grounded_sentences | number | Sentences supported by context |
has_warning | boolean | True if answer may be hallucinated |
warning_reason | string? | Explanation if warning is present |
Follow-up Fields:
| Field | Type | Description |
|---|
needed | boolean | True if answer confidence is low |
reason | string | Why confidence is low |
hint | string | Helpful hint for the user |
available_topics | string[] | Topics in this memory |
suggestions | string[] | Suggested follow-up questions |
correct() - Ground Truth Corrections
Store authoritative corrections that take priority in future retrievals:
// Store a correction
const frameId = await mem.correct('Ben Koenig reported to Chloe Nguyen before 2025');
// With options
const frameId = await mem.correct('The API rate limit is 1000 req/min', {
source: 'Engineering Team - Jan 2025',
topics: ['API', 'rate limiting'],
boost: 2.5 // Higher retrieval priority (default: 2.0)
});
// Batch corrections
const frameIds = await mem.correctMany([
{ statement: 'OAuth tokens expire after 24 hours', topics: ['auth', 'OAuth'] },
{ statement: 'Production DB is db.prod.example.com', source: 'Ops Team' }
]);
// Verify correction is retrievable
const results = await mem.find('Ben Koenig reported to');
console.log(results.hits[0].snippet); // Should show the correction
Use correct() to fix hallucinations or add verified facts. Corrections receive boosted retrieval scores and are labeled [Correction] in results.
Automatic Enrichment
// Extract facts using rules engine (fast, offline)
const result = await mem.enrich('rules');
// View extracted cards
const { cards, count } = await mem.memories();
// Filter by entity
const aliceCards = await mem.memories('Alice');
// Get entity state (O(1) lookup)
const alice = await mem.state('Alice');
console.log(alice.slots);
// { employer: 'Anthropic', role: 'Engineer', location: 'SF' }
// Get stats
const stats = await mem.memoriesStats();
console.log(stats.entityCount, stats.cardCount);
// List all entities
const entities = await mem.memoryEntities();
Manual Memory Cards
// Add SPO triplets directly
const result = await mem.addMemoryCards([
{ entity: 'Alice', slot: 'employer', value: 'Anthropic' },
{ entity: 'Alice', slot: 'role', value: 'Senior Engineer' },
{ entity: 'Bob', slot: 'team', value: 'Infrastructure' }
]);
console.log(result.added, result.ids);
Export Facts
// Export to JSON
const json = await mem.exportFacts('json');
// Export to CSV
const csv = await mem.exportFacts('csv', 'Alice');
// Export to N-Triples (RDF)
const ntriples = await mem.exportFacts('ntriples');
// Extract tables from PDF
const result = await mem.putPdfTables('financial-report.pdf', true);
console.log(`Extracted ${result.tables_count} tables`);
// List all tables
const tables = await mem.listTables();
for (const table of tables) {
console.log(table.table_id, table.n_rows, table.n_cols);
}
// Get table data
const data = await mem.getTable('tbl_001', 'dict');
const csv = await mem.getTable('tbl_001', 'csv');
Time-Travel & Sessions
Timeline Queries
const timeline = await mem.timeline({
limit: 50,
since: 1704067200,
until: 1706745600,
reverse: true,
asOfFrame: 100
});
Session Recording
// Start recording
const sessionId = await mem.sessionStart('qa-test');
// Perform operations
await mem.find('test query');
await mem.ask('What happened?');
// Add checkpoint
await mem.sessionCheckpoint();
// End session
const summary = await mem.sessionEnd();
// List sessions
const sessions = await mem.sessionList();
// Replay session with different params
const replay = await mem.sessionReplay(sessionId, 10, true);
console.log(replay.match_rate);
// Delete session
await mem.sessionDelete(sessionId);
Encryption & Security
import { lock, unlock, lockWho, lockNudge } from '@memvid/sdk';
// Encrypt to .mv2e capsule
const encryptedPath = await lock('project.mv2', {
password: 'secret',
force: true
});
// Decrypt back to .mv2
const decryptedPath = await unlock('project.mv2e', {
password: 'secret'
});
// Check who has the lock
const lockInfo = await lockWho('project.mv2');
// Nudge stale lock
const released = await lockNudge('project.mv2');
Tickets & Capacity
// Get current capacity
const capacity = await mem.getCapacity();
// Get current ticket info
const ticket = await mem.currentTicket();
// Sync tickets from dashboard
const result = await mem.syncTickets('mem_abc123', apiKey);
// Apply ticket manually
await mem.applyTicket(ticketString);
// Get memory binding
const binding = await mem.getMemoryBinding();
// Unbind from dashboard
await mem.unbindMemory();
Cloud Project & Memory Management
Programmatically create projects and memories on the Memvid dashboard, then bind local .mv2 files to them.
import { configure } from '@memvid/sdk';
configure({
apiKey: 'mv2_your_api_key_here',
dashboardUrl: 'https://memvid.com'
});
Create and List Projects
import { createProject, listProjects } from '@memvid/sdk';
// Create a new project
const project = await createProject({
name: 'My AI Project',
description: 'Knowledge base for my AI agent'
});
console.log(`Project ID: ${project.id}`);
console.log(`Slug: ${project.slug}`);
// List all projects
const projects = await listProjects();
for (const proj of projects) {
console.log(`${proj.name} (${proj.id})`);
}
Project Response Fields:
| Field | Type | Description |
|---|
id | string | Unique project ID |
organisationId | string | Organisation ID |
slug | string | URL-friendly slug |
name | string | Project name |
description | string? | Optional description |
createdAt | string | ISO 8601 timestamp |
updatedAt | string | ISO 8601 timestamp |
Create and List Memories
import { createMemory, listMemories } from '@memvid/sdk';
// Create a memory in a project
const memory = await createMemory({
name: 'Agent Memory',
description: 'Long-term memory for chatbot',
projectId: project.id
});
console.log(`Memory ID: ${memory.id}`);
console.log(`Display Name: ${memory.displayName}`);
// List all memories
const allMemories = await listMemories();
// List memories in a specific project
const projectMemories = await listMemories({ projectId: project.id });
Bind Local File to Cloud Memory
import { create } from '@memvid/sdk';
// Create local .mv2 file bound to cloud memory
const mv = await create('./agent.mv2', 'basic', { memoryId: memory.id });
await mv.enableLex(); // Enable lexical search
// Add content
await mv.put({ title: 'Meeting Notes', label: 'notes', text: 'Today we discussed...' });
// Search
const results = await mv.find('discussed', { k: 5 });
// Close
await mv.seal();
Complete Example
import { configure, createProject, createMemory, create } from '@memvid/sdk';
// 1. Configure SDK
configure({ apiKey: process.env.MEMVID_API_KEY });
// 2. Create project
const project = await createProject({
name: 'Knowledge Base',
description: 'Company docs'
});
// 3. Create cloud memory in project
const memory = await createMemory({
name: 'Docs Memory',
projectId: project.id
});
// 4. Create local file bound to cloud memory
const mv = await create('./docs.mv2', 'basic', { memoryId: memory.id });
await mv.enableLex();
// 5. Add content
await mv.put({ title: 'API Guide', label: 'docs', text: 'API documentation...' });
await mv.put({ title: 'FAQ', label: 'docs', text: 'Frequently asked questions...' });
// 6. Search
const results = await mv.find('API', { k: 5 });
console.log(`Found ${results.hits?.length || 0} results`);
// 7. Clean up
await mv.seal();
Embedding Providers
External Providers
import {
OpenAIEmbeddings,
GeminiEmbeddings,
MistralEmbeddings,
CohereEmbeddings,
VoyageEmbeddings,
NvidiaEmbeddings,
getEmbedder
} from '@memvid/sdk';
// OpenAI
const openai = new OpenAIEmbeddings({
apiKey: process.env.OPENAI_API_KEY,
model: 'text-embedding-3-small' // or 'text-embedding-3-large'
});
// Gemini
const gemini = new GeminiEmbeddings({
apiKey: process.env.GEMINI_API_KEY,
model: 'text-embedding-004'
});
// Mistral
const mistral = new MistralEmbeddings({
apiKey: process.env.MISTRAL_API_KEY
});
// Cohere
const cohere = new CohereEmbeddings({
apiKey: process.env.COHERE_API_KEY,
model: 'embed-english-v3.0'
});
// Voyage
const voyage = new VoyageEmbeddings({
apiKey: process.env.VOYAGE_API_KEY,
model: 'voyage-3'
});
// NVIDIA
const nvidia = new NvidiaEmbeddings({
apiKey: process.env.NVIDIA_API_KEY
});
// Factory function
const embedder = getEmbedder('openai', { apiKey: '...' });
// Use with putMany
await mem.putMany(docs, { embedder: openai });
// Use with find
await mem.find('query', { embedder: gemini });
Local Embeddings (No API Required)
import { LOCAL_EMBEDDING_MODELS } from '@memvid/sdk';
await mem.put({
text: 'content',
enableEmbedding: true,
embeddingModel: LOCAL_EMBEDDING_MODELS.BGE_SMALL // 384d, fast
});
// Available local models
LOCAL_EMBEDDING_MODELS.BGE_SMALL // 384d - fastest
LOCAL_EMBEDDING_MODELS.BGE_BASE // 768d - balanced
LOCAL_EMBEDDING_MODELS.NOMIC // 768d - general purpose
LOCAL_EMBEDDING_MODELS.GTE_LARGE // 1024d - highest quality
Error Handling
import {
MemvidError,
CapacityExceededError, // MV001
TicketInvalidError, // MV002
TicketReplayError, // MV003
LexIndexDisabledError, // MV004
TimeIndexMissingError, // MV005
VerifyFailedError, // MV006
LockedError, // MV007
ApiKeyRequiredError, // MV008
MemoryAlreadyBoundError, // MV009
FrameNotFoundError, // MV010
VecIndexDisabledError, // MV011
CorruptFileError, // MV012
VecDimensionMismatchError // MV014
} from '@memvid/sdk';
try {
await mem.put({ title: 'Large file', file: 'huge.bin' });
} catch (err) {
if (err instanceof CapacityExceededError) {
console.log('Storage capacity exceeded (MV001)');
} else if (err instanceof LockedError) {
console.log('File locked by another process (MV007)');
} else if (err instanceof VecIndexDisabledError) {
console.log('Enable vector index first (MV011)');
}
}
// Get frame content
const content = await mem.view(frameId);
const contentByUri = await mem.viewByUri('mv2://docs/intro');
// Extract binary assets (PDF, images)
const asset = await mem.extractAsset(frameId);
console.log(asset.mimeType, asset.filename, asset.data);
// Get frame metadata
const info = await mem.getFrameInfo(frameId);
console.log(info.uri, info.title, info.timestamp);
Environment Variables
| Variable | Description |
|---|
MEMVID_API_KEY | Dashboard API key for sync |
OPENAI_API_KEY | OpenAI embeddings and LLM |
GEMINI_API_KEY | Gemini embeddings |
MISTRAL_API_KEY | Mistral embeddings |
COHERE_API_KEY | Cohere embeddings |
VOYAGE_API_KEY | Voyage embeddings |
NVIDIA_API_KEY | NVIDIA embeddings |
ANTHROPIC_API_KEY | Claude for entities |
MEMVID_MODELS_DIR | Model cache directory |
MEMVID_OFFLINE | Use cached models only |
Deploying to Vercel
The Memvid Node.js SDK uses native bindings (N-API) for optimal performance. When deploying to Vercel’s serverless environment, you need to configure Next.js to bundle the native binary correctly.
next.config.ts Configuration
Add outputFileTracingIncludes to ensure the native .node files are bundled with your serverless functions:
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
experimental: {
outputFileTracingIncludes: {
'/api/*': [
'./node_modules/@memvid/sdk-linux-x64-gnu/**/*',
'./node_modules/@memvid/sdk/**/*',
],
},
},
};
export default nextConfig;
For more reliable deployments, explicitly add the Linux platform package to your dependencies:
{
"dependencies": {
"@memvid/sdk": "^2.0.146",
"@memvid/sdk-linux-x64-gnu": "^2.0.146"
}
}
Vercel’s serverless runtime uses Amazon Linux 2 (x64). The SDK automatically selects the correct platform binary, but explicit inclusion ensures bundling works correctly.
Serverless /tmp Storage
Vercel’s serverless functions have ephemeral /tmp storage that doesn’t persist between invocations. For production apps:
- Use cloud storage (S3, R2, etc.) to persist
.mv2 files
- Download on-demand when the function cold starts
- Pass files as buffers between API routes instead of file paths
// Example: Download from S3 if not in /tmp
import { existsSync } from 'fs';
import { writeFile } from 'fs/promises';
const localPath = `/tmp/${memoryId}.mv2`;
if (!existsSync(localPath)) {
const buffer = await downloadFromS3(userId, memoryId);
await writeFile(localPath, buffer);
}
const mem = await open(localPath);
Troubleshooting
| Error | Solution |
|---|
Native binary not found for platform: linux-x64 | Add outputFileTracingIncludes config |
GLIBC_2.35 not found | Ensure you’re using SDK v2.0.146+ (built for glibc 2.26) |
ENOENT: no such file or directory | Files in /tmp don’t persist; use cloud storage |
TypeScript Types
import type {
PutInput,
PutManyInput,
FindInput,
AskInput,
MemoryCard,
MemoryCardInput,
EntityState,
FrameInfo,
TableInfo,
SessionSummary,
MemvidErrorCode
} from '@memvid/sdk';
Next Steps