Persistent, self-organizing memory for AI agents β atomic fact extraction, knowledge graph, LLM deduplication, and semantic recall across your LAN
- Docker Desktop β runs PostgreSQL, Qdrant, Server, Dashboard
- Ollama β runs locally on host for embedding generation (needs GPU)
- MiniMax API Key β cloud LLM for fact extraction & deduplication
# 1. Clone
git clone https://github.com/thdeptrai/memolo.git
cd memolo
# 2. Pull embedding model
ollama pull qwen3-embedding:8b
# 3. Configure
cp .env.example .env
# Edit .env β set these 2 required values:
# MEMOLO_MASTER_KEY=<random string for API security>
# MINIMAX_API_KEY=<your MiniMax API key>
# 4. Start everything
docker compose up -d
# β
Done!
# API: http://localhost:7437
# Dashboard: http://localhost:3001bash update.sh
# Or: git pull && docker compose up -d --build memoloMemolo is a local-first AI memory system that turns raw agent conversations into structured, searchable, and self-maintaining knowledge. Here's what happens when an agent sends a message:
USER MESSAGE + AGENT RESPONSE
β
βΌ
βββββββββββββββββββββ
β 1. Save Raw Data β Exchange saved to PostgreSQL with sequence number
βββββββββ¬ββββββββββββ
β
βΌ
βββββββββββββββββββββ
β 2. Batch Queue β Exchange enqueued into in-memory buffer
β (if batch enabled)β (reduces LLM API calls for cloud providers)
βββββββββ¬ββββββββββββ
β
βββββ (flush every 10s or when batch full) βββββ
β β
βΌ βΌ
βββββββββββββββββββββ ββββββββββββββββββββ
β 3. Extract Facts β β 5. Update Graph β
β + Dedup (combined)β 1 LLM call per batch: β β
β β β’ Extract atomic facts β Entities β DB β
β β β’ ADD/UPDATE/DELETE/NONE β Co-occurring β β
β β β’ User + Agent facts β relationships β
βββββββββ¬ββββββββββββ ββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββ
β 4. Embed & Store β Generate 4096-dim embedding via Ollama,
β β store in Qdrant for semantic search
βββββββββββββββββββββ
QUERY: "What tools does the user prefer?"
β
βΌ
βββββββββββββββββββββ
β 1. Query Enrich β Enrich query using conversation profile
βββββββββ¬ββββββββββββ (active topic, preferences, context)
β
ββββββββββββββββββββββ¬βββββββββββββββββββ
βΌ βΌ βΌ
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β 2. Semantic β β 3. Cross- β β 4. Knowledge β
β Search β β Agent β β Graph β
β (Qdrant, β β Search β β Query β
β topic-aware)β β (shared KB) β β (neighbors) β
ββββββββ¬ββββββββ ββββββββ¬βββββββ ββββββββ¬ββββββββ
β β β
ββββββββββββββββββββΌββββββββββββββββββββ
βΌ
βββββββββββββββββββββ
β 5. LLM Rerank β Score each result 0.0-1.0 by
β (configurable) β semantic relevance to query
βββββββββ¬ββββββββββββ
β
βΌ
RANKED RESULTS
Unlike batch summarization that processes groups of messages, Memolo extracts atomic facts from every individual exchange in real-time. Each fact is a standalone, searchable unit of knowledge. Facts from both user messages and agent responses (configurable) are extracted.
Example:
User: "Tao dang lam project ecommerce bang Next.js va Prisma ORM, database la PostgreSQL"
Agent: "Hay lam! Stack rat manh."
Extracted Facts:
1. "User Δang lΓ m project ecommerce"
2. "Project sα» dα»₯ng Next.js framework"
3. "Database lΓ PostgreSQL"
When a new exchange arrives, Memolo performs extraction AND deduplication in a single LLM call (optimized for cloud providers like MiniMax to minimize API costs):
- Extract atomic facts from user + agent messages
- Compare against existing memories (fetched via vector search)
- Decide action for each fact: ADD / UPDATE / DELETE / NONE
This prevents memory bloat and handles contradictions automatically:
Existing: "Database lΓ PostgreSQL"
New fact: "ΔΓ£ chuyα»n sang MySQL thay vΓ¬ PostgreSQL"
LLM Decision: UPDATE
Result: "ΔΓ£ chuyα»n sang sα» dα»₯ng MySQL thay vΓ¬ PostgreSQL" (old superseded)
Key technique: UUIDs are mapped to integers [0], [1], [2]... before sending to the LLM to prevent hallucination (inspired by mem0).
Exchanges are queued and processed in batches (configurable interval + max size) to dramatically reduce LLM API calls for cloud providers. A batch of 10 exchanges β 1 LLM call instead of 10.
Entities mentioned in conversations are automatically extracted and linked:
Entities: [Next.js, TypeScript, PostgreSQL, Vercel]
Relations: Next.js --related_to--> TypeScript
PostgreSQL --related_to--> Next.js
During recall, the graph provides contextual connections β asking about "Next.js" also surfaces related technologies, preferences, and decisions.
After initial vector similarity search, an LLM scores each result's relevance (0.0-1.0) to the actual query. This catches cases where vector similarity alone misses semantic nuance. Can be disabled via config.
Every ADD, UPDATE, and DELETE operation is logged with:
- Before/after content
- Who changed it (agent ID or system)
- Why (dedup_merge, contradiction, manual, etc.)
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β Agent 1 β β Agent 2 β β Agent N β
β (Device A) β β (Device B) β β (Device C) β
ββββββββ¬ββββββββ ββββββββ¬ββββββββ ββββββββ¬ββββββββ
β X-API-Key β X-API-Key β X-API-Key
ββββββββββββββββββββΌβββββββββββββββββββ
β LAN (WiFi)
ββββββββΌβββββββ
β Memolo β β 0.0.0.0:7437
β Server β API + Dashboard
βββββββββββββββ€
β Batch Queue β β queue + flush periodically
β Fact Extractβ β per-exchange atomic facts
β Deduplicatorβ β LLM ADD/UPDATE/DELETE
β Graph Engineβ β entities + relationships
β Reranker β β LLM relevance scoring
β Contradict. β β detect & supersede conflicts
β Intelligenceβ β decay, dedup
β LLM Service β β MiniMax M2.5
β Auth Layer β β master + per-agent keys
β Config API β β live runtime settings
ββββββββ¬βββββββ
βββββββββββββΌββββββββββββ
ββββββΌβββββ ββββββΌβββββ ββββββΌβββββ
βPostgreSQLβ β Qdrant β β Ollama β
β 9 tables β β vectors β β (host) β
β + graph β β 4096dim β βembed onlyβ
βββββββββββ βββββββββββ βββββββββββ
| Component | Technology |
|---|---|
| Server | Node.js + Express 4.18 |
| Database | PostgreSQL 16 (9 tables, 11 migrations) |
| Vector Store | Qdrant (Cosine similarity, 4096 dim) |
| Embeddings | Ollama qwen3-embedding:8b (local) |
| LLM (Facts/Dedup/Rerank) | MiniMax M2.5 (cloud, Anthropic-compatible API) |
| Auth | API key (master + per-agent) via X-API-Key header |
| Dashboard | Next.js 16 + TailwindCSS v4 + shadcn/ui (dark theme) |
| Deployment | Docker Compose (single command) |
| Table | Purpose |
|---|---|
agents |
Registered AI agents with API keys |
conversations |
Conversation sessions per agent |
exchanges |
Raw user/agent message pairs |
memories |
Extracted facts, decisions, insights (with content_hash, actor_id, superseded_by) |
knowledge_base |
Curated knowledge entries |
memory_history |
Audit trail for all memory mutations |
entities |
Named entities from the knowledge graph |
relationships |
Typed links between entities |
memory_conversations |
Many-to-many memory β conversation linking |
| Key Type | Set In | Purpose |
|---|---|---|
| Master key | .env (MEMOLO_MASTER_KEY) |
Admin: register agents, full access |
| Per-agent key | Auto-generated on register | Agent: store, recall, search |
GET /api/healthβ no auth required- If
MEMOLO_MASTER_KEYnot set β auth disabled (dev mode)
const { MemoryClient } = require('memolo');
const memory = new MemoryClient({
agentId: 'my-agent',
apiKey: 'agent-api-key-from-register',
serverUrl: 'http://192.168.1.100:7437',
});
const ctx = await memory.recall('user question', { format: 'context' });
const result = await memory.store({ userMessage: '...', agentResponse: '...' });{
"memolo": {
"agentId": "my-agent",
"apiKey": "${MEMOLO_API_KEY}",
"serverUrl": "http://192.168.1.100:7437"
}
}| Method | Path | Description |
|---|---|---|
POST |
/api/memory/store |
Store exchange β triggers fact extraction |
POST |
/api/memory/recall |
Recall memories (semantic + graph + rerank) |
POST |
/api/memory/search |
Full-text + semantic search |
POST |
/api/memory/summarize |
Manual summarization trigger |
GET |
/api/memory/history |
Global memory audit log |
GET |
/api/memory/memories/:id/history |
Per-memory audit trail |
GET |
/api/memory/memories |
List memories (filterable by topic/scope/type/agent) |
GET |
/api/memory/topics |
List unique topics with counts |
GET |
/api/memory/exchanges |
List all exchanges |
GET |
/api/memory/conversations |
List all conversations |
GET |
/api/memory/conversations/:id |
Get conversation details |
POST |
/api/memory/conversations/:id/end |
End conversation |
PATCH |
/api/memory/:id |
Update memory (confirm/reject/supersede/update) |
DELETE |
/api/memory/:id |
Delete memory |
| Method | Path | Description |
|---|---|---|
POST |
/api/memory/agents/register |
Register agent β returns API key |
POST |
/api/memory/agents/:id/regenerate-key |
Rotate API key |
GET |
/api/memory/agents |
List agents |
GET |
/api/memory/agents/:agentId/recent |
Recent memories for agent |
| Method | Path | Description |
|---|---|---|
GET |
/api/graph/entities/:agentId |
List entities for agent |
GET |
/api/graph/entities/search?query=X |
Search entities by name |
GET |
/api/graph/neighborhood/:id?agentId=X |
Entity + connections |
GET |
/api/graph/:agentId |
Full agent graph (visualization) |
| Method | Path | Description |
|---|---|---|
POST |
/api/intelligence/run |
Run intelligence tasks (decay/dedup) |
POST |
/api/intelligence/permissions/grant |
Grant read permission |
POST |
/api/intelligence/permissions/revoke |
Revoke read permission |
POST |
/api/intelligence/permissions/team |
Grant all-to-all team access |
GET |
/api/intelligence/knowledge |
Knowledge base entries |
GET |
/api/intelligence/knowledge/search?q=X |
Search knowledge base |
GET |
/api/intelligence/stats |
System stats |
GET |
/api/health |
Health check (no auth) |
GET |
/api/logs/stream |
SSE live event stream |
GET |
/api/logs |
Recent logs |
GET |
/api/logs/events |
Recent typed events |
| Method | Path | Description |
|---|---|---|
GET |
/api/config |
Get all runtime settings with metadata |
PUT |
/api/config |
Update settings (live, no restart needed) |
POST |
/api/config/reset |
Reset one or all settings to defaults |
# Required
MEMOLO_MASTER_KEY=your-secret-key
# MiniMax M2.5 (Required β LLM for fact extraction, dedup, reranking)
MINIMAX_API_KEY=your-minimax-api-key
MINIMAX_MODEL=MiniMax-M2.5
MINIMAX_BASE_URL=https://api.minimax.io/anthropic/v1/messages
# Server
PORT=7437 # Server port (default: 7437)
# Ollama (Embeddings only)
OLLAMA_BASE_URL=http://host.docker.internal:11434
OLLAMA_EMBED_MODEL=qwen3-embedding:8b
# Feature Flags (all default: true)
ENABLE_FACT_EXTRACTION=true # Per-exchange atomic fact extraction
ENABLE_RERANKING=true # LLM search result reranking
ENABLE_GRAPH=true # Knowledge graph processing
# Tuning
EMBEDDING_DIMENSIONS=4096 # Embedding vector dimensions
FACT_EXTRACT_TIMEOUT=60000 # Fact extraction timeout (ms)
DEDUP_TIMEOUT=60000 # Dedup decision timeout (ms)
RERANK_TIMEOUT=30000 # Reranking timeout (ms)
# Database (no need to change for Docker)
PG_HOST=postgres
PG_PORT=5432
PG_USER=memolo
PG_PASSWORD=memolo_secret
PG_DATABASE=memolo
QDRANT_HOST=qdrant
QDRANT_PORT=6333| Script | Platform | Purpose |
|---|---|---|
setup.sh |
Linux/macOS | Automated full setup (Docker, Ollama, .env, start services) |
setup.bat |
Windows | Same as above for Windows |
update.sh |
Linux/macOS | Pull latest code from Git and rebuild Docker image |
scripts/install-plugin.sh |
Linux/macOS | Install Memolo plugin into OpenClaw |
# Linux/macOS
bash setup.sh
# Windows
setup.batThe setup script will:
- Check prerequisites (Docker, Ollama)
- Generate
.envwith random master key - Pull required embedding model
- Start all Docker services
- Register a default agent
bash update.sh
# Or manually:
git pull origin master
docker compose up -d --build memoloFrom inside your OpenClaw project directory:
curl -sL https://raw.githubusercontent.com/thdeptrai/memolo/master/scripts/install-plugin.sh | bashThis downloads the plugin, installs dependencies, and registers it with OpenClaw CLI.
- π SETUP.md β Detailed setup & troubleshooting
- π¦ SDK README β Node.js client SDK
- π Plugin README β OpenClaw plugin integration docs