Default configuration is fully local — JSON files on disk, no network calls, no embeddings, no external services.
Data only leaves the host if you explicitly configure one of these:
Feature
What leaves
Where it goes
How to avoid
Embeddings (OpenAI/NVIDIA/Azure)
Memory text
Embedding API endpoint
Use noop embeddings or Ollama (local)
LLM (OpenAI/OpenClaw/Ollama)
Memory text for extraction/compression
LLM API endpoint
Don't configure llm option, or use Ollama
Supabase storage
All memory data
Your Supabase project
Use json or memory storage (default)
Webhook writethrough
Store/decay event payloads
Your webhook URL
Don't configure webhookWritethrough
Key security properties:
Only 2 env vars are read directly by code: OPENAI_API_KEY and OPENCLAW_GATEWAY_TOKEN. All others (Supabase, NVIDIA, Azure) are passed via explicit config objects.
All provider URLs are validated against SSRF (private IPs blocked, cloud metadata blocked).
Supabase: prefer anon key + RLS over service key. Service key bypasses row-level security.
All user content sent to LLMs is XML-fenced with injection guards.
Test safely with storage: { type: 'memory' } — nothing touches disk or network.
See docs/guide.md § Security for the full security model.
Quick Start (Zero Config)
javascript
import { createMemory } from '@jeremiaheth/neolata-mem';
const mem = createMemory();
await mem.store('agent-1', 'User prefers dark mode');
const results = await mem.search('agent-1', 'UI preferences');
Works immediately with local JSON storage and keyword search. No API keys needed.
With Semantic Search
javascript
const mem = createMemory({
embeddings: {
type: 'openai',
apiKey: process.env.OPENAI_API_KEY,
model: 'text-embedding-3-small',
},
});
// Agent IDs like 'kuro' and 'maki' are just examples — use any string.
await mem.store('kuro', 'Found XSS in login form', { category: 'finding', importance: 0.9 });
const results = await mem.search('kuro', 'security vulnerabilities');
Supports 5+ embedding providers: OpenAI, NVIDIA NIM, Ollama, Azure, Together, or any OpenAI-compatible endpoint.
Key Features
Hybrid Search (Vector + Keyword Fallback)
Uses semantic similarity when embeddings are configured; falls back to tokenized keyword matching when they're not:
javascript
// With embeddings → vector cosine similarity search
// Without embeddings → normalized keyword matching (stop word removal, lowercase, dedup)
const results = await mem.search('agent', 'security vulnerabilities');
Keyword search uses an inverted token index for O(1) lookups. When >500 memories exist, vector search pre-filters candidates using token overlap before cosine similarity (candidate narrowing).
Biological Decay
Memories fade over time unless reinforced. Old, unaccessed memories naturally lose relevance:
javascript
await mem.decay(); // Run maintenance — archive/delete stale memories
await mem.reinforce(id); // Boost a memory to resist decay
Memory Graph (Zettelkasten Linking)
Every memory is automatically linked to related memories by semantic similarity:
await mem.store('kuro', 'Vuln found in API gateway');
await mem.store('maki', 'API gateway deployed to prod');
const all = await mem.searchAll('API gateway'); // Cross-agent search
Supabase key guidance: Prefer the anon key with Row Level Security (RLS) policies over the service role key. The service key bypasses RLS and grants full access to all stored memories. Only use it for admin/migration tasks.
Local-only mode (default): Memories are stored as JSON at ./neolata-mem-data/graph.json (relative to CWD). No data leaves your machine. Keyword search works without any API keys.
With embeddings/extraction/LLM: When you configure an external provider (OpenAI, NIM, Ollama, etc.), your memory text is sent to that provider's API for embedding or extraction. This is opt-in — you must explicitly provide an API key and base URL.
Mode
Data sent externally?
Storage location
Default (no config)
❌ No
./neolata-mem-data/graph.json
Ollama embeddings
❌ No (local)
./neolata-mem-data/graph.json
OpenAI/NIM embeddings
⚠️ Memory text → provider
./neolata-mem-data/graph.json
Supabase storage
⚠️ All data → Supabase
Supabase PostgreSQL
LLM conflict resolution
⚠️ Memory text → provider
Storage unchanged
To keep all data local: Use Ollama for embeddings and JSON storage. No API keys needed for keyword-only search.