Your AI agents forget everything. x-gun-memory fixes that. Agent-isolated, scalable, vector-powered knowledge sharing. Your AI agents finally share a brain - safely.
Works seamlessly with any MCP-compatible AI system:
- Claude Desktop - stdio mode
- Claude Code - stdio mode
- OpenClaw - HTTP/SSE mode
- Cursor - stdio mode
- Hermes Agent - stdio mode
- Any custom AI agent supporting MCP
Supports both:
- stdio mode: single client connections
- HTTP/SSE mode: multiple concurrent clients
See setup instructions below for each platform.
- Agent Isolation - Complete memory separation per AI agent. No data leakage between agents.
- Semi-Structured Memory - Automatic feature extraction (type, tags, entities, summary, importance)
- Multi-Agent Support - Concurrent agents via HTTP-SSE with thread-safe operations
- Global Knowledge Sharing - Optional shared memory space (
agentId="global") for cross-agent knowledge - Pluggable Storage - SQLite (local), PostgreSQL (cloud), or in-memory. Swap with one config change.
- Smart Deduplication - Automatically merges near-duplicate memories (>=0.95), links related ones (0.75-0.95), creates fresh for new content. Maintains version history of original content before each merge.
- Relevance-based Retrieval - Full content for high similarity (>=0.85), smart sentence-boundary summary for medium (0.60-0.85), noise filtered below 0.60
- Fast Embeddings - LRU cache + batch processing (configurable
embeddings.batchSize, default128) with runtime cached/uncached latency stats - Native Vector Search - O(log N) via sqlite-vec / pgvector. Not brute force.
- Universal MCP - Works as stdio (Cursor, Claude Code, Claude Desktop, Hermes) AND HTTP/SSE (Claude.ai, OpenClaw)
- Batch Operations - Store multiple memories in one call
- Token Efficient - Returns only what's needed, not full node dumps
- Background Processing - Asynchronous embedding generation queue
- Hybrid Scoring - Combines semantic similarity with graph relationships
- Database Migrations - Automatic schema versioning and upgrades
- Structured Logging - JSON logging with agent tracking and performance metrics
- Rate Limiting - Built-in protection against abuse (100 requests/15min per agent)
- Conflict Safety - Optimistic locking prevents concurrent write conflicts
- Nodes: Store conversations, files, code, context, knowledge with embeddings + agent metadata
agentId: Agent identifier (required)sessionId: Session identifier (optional)namespace: Logical grouping (optional)
- Edges: Relationships between nodes (references, similar_to, etc.)
- Embeddings: Local vector generation with caching
- Metadata: Configuration and statistics
- MCP Server: Universal MCP with stdio + HTTP/SSE support
- REST API: Endpoints for storage, retrieval, and management
x-gun-memory/
|-- src/
| |-- storage/
| | |-- adapters/
| | | |-- base-adapter.js # Abstract adapter interface
| | | |-- sqlite-adapter.js # SQLite + sqlite-vec
| | | |-- postgres-adapter.js # PostgreSQL + pgvector
| | | |-- memory-adapter.js # In-memory (testing)
| | | `-- README.md # Build your own adapter
| | |-- adapter-factory.js # Auto-select from config
| | |-- graph-db.js # Orchestration layer
| | `-- embeddings.js # Local embeddings + LRU cache
| |-- mcp/
| | `-- server.js # MCP stdio + HTTP/SSE
| |-- api/
| | `-- rest-server.js # REST API
| `-- utils/
| |-- retrieval.js # Smart relevance retrieval
| |-- deduplication.js # Merge/update/create logic
| |-- graph-traversal.js # BFS/DFS traversal
| `-- logger.js # Logging
|-- data/
| `-- x-gun-memory.db # SQLite database (default fallback)
|-- config.json # All configuration
`-- package.json
git clone https://github.com/swamy18/x-gun-memory
cd x-gun-memory
npm installNote: npm install may report security vulnerabilities. Run npm audit fix to attempt automatic fixes, or npm audit for details.
better-sqlite3may fail to install/load on Windows with Node 24 due to missing prebuilt binaries or build toolchain requirements.- If SQLite startup fails with missing native bindings, use Node 18/20 LTS, install Visual Studio C++ workload on Windows, or switch to PostgreSQL mode.
- PostgreSQL mode avoids the
better-sqlite3native dependency path.
git clone https://github.com/swamy18/x-gun-memory
cd x-gun-memory
npm install
npm run start:mcpTo run the test suite:
npm testNote: Currently, no tests are implemented. This is a placeholder command.
Full configuration in config.json:
{
"storage": {
"type": "sqlite",
"sqlite": { "path": "./data/x-gun-memory.db" },
"postgres": {
"connectionString": "postgresql://user:pass@localhost:5432/xgunmemory"
}
},
"embeddings": {
"model": "Xenova/all-MiniLM-L6-v2",
"cacheDir": "./data/embeddings-cache",
"batchSize": 128,
"lruCacheSize": 1000
},
"retrieval": {
"defaultMaxNodes": 5,
"defaultTraverseDepth": 2,
"highRelevanceThreshold": 0.85,
"lowRelevanceThreshold": 0.60,
"summaryLength": 400
},
"deduplication": {
"enabled": true,
"similarityThreshold": 0.75,
"mergeThreshold": 0.95,
"updateThreshold": 0.75
},
"mcp": { "port": 3001, "host": "localhost" },
"api": {
"port": 3000,
"host": "localhost",
"rateLimit": {
"windowMs": 900000,
"maxRequests": 100
}
},
"logging": { "level": "info", "file": "./logs/app.log" },
"agents": {
"allowGlobalWrites": ["admin-agent"],
"defaultAgentId": "global"
},
"redis": {
"enabled": true,
"host": "127.0.0.1",
"port": 6379
}
}Switch to Postgres: Change storage.type to "postgres". Zero code changes needed.
Environment Variables: Override config values with environment variables.
-
Copy
.env.exampleto.env:cp .env.example .env
-
Edit
.envwith your desired values.
Supported variables:
STORAGE_TYPE: Storage backend (sqlite,postgres,memory)POSTGRES_CONNECTION_STRING: PostgreSQL connection stringREDIS_HOST,REDIS_PORT,REDIS_ENABLED: Redis configurationMCP_PORT,API_PORT,API_HOST: Server configurationLOG_LEVEL: Logging level (info,debug, etc.)DEFAULT_AGENT_ID: Default agent identifierAUTH_ENABLED: Enable/disable authentication
# Start MCP server (for Claude, Cursor)
npm run start:mcp
# Start REST API server
npm run start:api
# Start MCP with HTTP/SSE mode
npm run start:mcp:httpcurl -X POST http://localhost:3000/store \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_AGENT_KEY" \
-d '{
"agentId": "my-agent",
"type": "conversation",
"content": "User asked: What is the weather?"
}'curl -H "X-API-Key: YOUR_AGENT_KEY" \
"http://localhost:3000/retrieve?agentId=my-agent&q=weather&max_nodes=3"curl -H "X-API-Key: YOUR_AGENT_KEY" \
"http://localhost:3000/retrieve?agentId=my-agent&q=explain+the+weather+pattern&highAccuracy=true"{
"method": "tools/call",
"params": {
"name": "store_context",
"arguments": {
"agentId": "claude-desktop",
"type": "code",
"content": "Fixed the bug in user authentication"
}
}
}In ~/.cursor/mcp.json or claude_desktop_config.json:
{
"mcpServers": {
"x-gun-memory": {
"command": "node",
"args": ["/absolute/path/to/x-gun-memory/src/mcp/server.js"],
"env": {}
}
}
}Start the server in HTTP mode:
npm run start:mcp:httpThen add connector URL: http://localhost:3001/sse
In openclaw.json or config:
{
"plugins": {
"x-gun-memory": {
"mcp": "http://localhost:3001/sse"
}
}
}In ~/.hermes/config.yaml:
mcp_servers:
x-gun-memory:
command: "node"
args: ["/absolute/path/to/x-gun-memory/src/mcp/server.js"]Each AI agent gets its own memory space. Specify agentId in all operations:
{
"agentId": "claude-assistant",
"type": "conversation",
"content": "User asked about weather"
}Use agentId: "global" for shared knowledge:
{
"agentId": "global",
"type": "knowledge",
"content": "Paris is the capital of France"
}All agents can read global memories. Write controls depend on transport:
- REST API uses API-key permissions (
global) via auth middleware, orcallerAgentId/X-Agent-Idallowlisted inagents.allowGlobalWrites. - MCP write tools require
callerAgentIdforagentId: "global"and validate it againstagents.allowGlobalWrites.
Optional grouping for better organization:
{
"agentId": "my-chatbot",
"sessionId": "session-123",
"namespace": "customer-support",
"type": "conversation",
"content": "How can I help you today?"
}- HTTP-SSE mode supports multiple concurrent agents
- Thread-safe operations with write locking
- Rate limiting per agent prevents abuse
Store any data in the graph.
Parameters: {agentId, callerAgentId?, sessionId?, namespace?, type, content, relationships?, metadata?}
Required: agentId, type, content
Returns:
- "Context stored successfully with ID: Z" (new)
- "Memory already exists (ID: X, similarity: 0.97). Updated." (merge)
- "Stored as new memory (ID: Y). Linked to related ID: X (similarity: 0.82)." (update)
Get relevant context using semantic + graph search.
Parameters: {agentId, sessionId?, namespace?, query, max_nodes?, traverse_depth?, highAccuracy?}
Required: agentId, query
Returns: [{id, type, content, contentType: "full"|"summary", similarity, source}]
Direct graph queries with filters.
Parameters: {agentId, node_type?, relationship?, time_range?: {start?, end?}}
Returns: {nodes, edges}
Store multiple memories at once. Much faster than calling store_context repeatedly.
Parameters: {agentId, callerAgentId?, sessionId?, namespace?, items: [{type, content, metadata?}]}
Required: agentId, items
Returns: "Stored X memories. Node IDs: ..."
Store structured memory with automatic feature extraction.
Parameters: {agentId, callerAgentId?, sessionId?, namespace?, content, memoryType?, tags?, entities?, summary?, importance?, confidence?, autoExtract?}
Required: agentId, content
Returns: Structured memory with extracted features
All endpoints require agentId in request body/query parameters.
POST /store/memory- Store structured memory with auto-extraction- Body:
{agentId, callerAgentId?, content, memoryType?, tags?, entities?, summary?, importance?, confidence?, autoExtract?}
- Body:
POST /store- Store single memory (with dedup)- Body:
{agentId, callerAgentId?, sessionId?, namespace?, type, content, relationships?, metadata?}
- Body:
POST /store/batch- Store multiple memories at once- Body:
{agentId, callerAgentId?, sessionId?, namespace?, items: [{type, content, metadata?}]}
- Body:
GET /retrieve?agentId=X&sessionId=Y&namespace=Z&q=query&max_nodes=5&traverse_depth=2&highAccuracy=false- Semantic + graph search (optional session/namespace scope)POST /query- Filter by type/relationship/time- Body:
{agentId, node_type?, relationship?, time_range?}
- Body:
GET /graph?node_id=123&depth=2- Traverse from node ID (within agent scope)GET /health- Basic health checkGET /health/detailed- Storage + embeddings stats
{
"status": "ok",
"storage": { "type": "sqlite", "status": "ok", "latencyMs": 2 },
"embeddings": {
"cacheHits": 142,
"cacheMisses": 23,
"lruCacheSize": 321,
"redisEnabled": true,
"avgLatencyMs": 45,
"avgCachedLatencyMs": 8,
"avgUncachedLatencyMs": 220,
"batchSize": 128
},
"uptime": 3600,
"version": "1.0.0"
}No changes needed. Works out of the box.
- Install pgvector:
CREATE EXTENSION vector; - Ensure planner stats are current so vector/text indexes are used efficiently:
ANALYZE nodes; ANALYZE edges; - Update config.json:
{ "storage": { "type": "postgres", "postgres": { "connectionString": "your connection string" } } } - Restart server. Done.
{
"storage": {
"type": "memory"
}
}Data lost on restart. No dependencies needed.
See src/storage/adapters/README.md
- All data stored locally
- No external API calls for core functionality
- SQLite database file permissions apply
- Embeddings cached locally
- Agent isolation prevents data leakage
- Rate limiting protects against abuse
- Thread Safety: Write operations serialized with mutexes (SQLite) or connection pooling (PostgreSQL)
- Optimistic Locking: Prevents conflicts in deduplication merges
- Agent-Level Rate Limiting: 100 requests per 15 minutes per agent
- Concurrent Reads: Multiple agents can read simultaneously
- Conflict Resolution: Automatic retry logic for transient failures
- Durable Queue: Redis-backed embedding processing with at-least-once delivery (RPOPLPUSH pattern)
- Distributed Cache: Multi-level caching (Redis + LRU) with stampede protection
- Job Deduplication: Redis sets prevent duplicate embedding jobs
- Safe Pattern Deletion: SCAN-based cache invalidation (non-blocking)
- TTL Strategy: Intelligent cache expiration based on data freshness
- High Availability: System works without Redis (graceful degradation)
Embeddings are processed asynchronously to prevent blocking:
// Automatic queue processing
await embeddings.generateBatch(texts); // Non-blockingTwo-stage retrieval for optimal performance:
- Fast Keyword Filtering: Full-text search (FTS5/PostgreSQL tsvector)
- Embedding Reranking: Semantic similarity on filtered candidates
{
"retrieval": {
"useHybrid": true,
"fastLimit": 50,
"finalLimit": 10
}
}Performance: 5-10x faster than pure vector search, same or better accuracy.
Automatic Mode Selection:
- Fast Mode (default): Summary + light context for quick responses
- High Accuracy Mode: Full content + graph expansion for complex queries
Auto-Detection Triggers:
- Explicit
highAccuracy: trueflag - Query length > 80 characters
- Keywords: "why", "explain", "analyze", "compare", "reason", "how"
Configuration:
{
"retrieval": {
"dualMode": true,
"highAccuracyLimit": 100,
"graphDepth": 2
}
}dualMode: false forces fast mode unless the request explicitly sets highAccuracy: true.
Performance Comparison:
- Fast Mode: 50-100ms, summary content
- High Accuracy Mode: 200-500ms, full content + context
Embedding throughput note (local benchmark example):
- On this project setup,
embeddings.batchSize=128outperformed64for a 256-item uncached run (3389msvs3851mstotal). - Prefer
POST /store/batchover repeatedPOST /storefor higher write throughput.
Combines semantic similarity with graph relationships:
{
"retrieval": {
"useHybridScoring": true,
"hybridWeights": {
"semantic": 0.7,
"graph": 0.3
}
}
}Store memories with automatic feature extraction and lightweight structure:
- Type:
fact,event,preference,task,general - Tags: Up to 5 relevant keywords (auto-extracted)
- Entities: People, places, organizations (auto-extracted)
- Summary: One-line summary (first sentence)
- Importance: 0-1 score based on keywords and urgency
- Confidence: 0-1 extraction confidence score
# Store structured memory with auto-extraction
curl -X POST http://localhost:3000/store/memory \
-H "X-API-Key: YOUR_AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentId": "my-agent",
"content": "I need to finish the project report by Friday. This is urgent!"
}'Response:
{
"success": true,
"nodeId": 123,
"features": {
"memory_type": "task",
"tags": ["urgent", "project", "deadline"],
"entities": [],
"summary": "I need to finish the project report by Friday.",
"importance": 0.8,
"confidence": 0.8
}
}{
"method": "tools/call",
"params": {
"name": "store_memory",
"arguments": {
"agentId": "claude-assistant",
"content": "Paris is the capital of France",
"memoryType": "fact",
"importance": 0.9
}
}
}{
"memory": {
"autoExtract": true,
"maxTags": 5,
"maxEntities": 5
}
}{
"storage": { "type": "memory" },
"auth": { "enabled": false },
"redis": { "enabled": false }
}{
"storage": {
"type": "sqlite",
"sqlite": { "path": "./data/x-gun-memory.db" }
},
"auth": { "enabled": true },
"redis": { "enabled": false }
}{
"storage": {
"type": "postgres",
"postgres": { "connectionString": "postgresql://user:pass@host:5432/db" }
},
"auth": { "enabled": true },
"redis": { "enabled": true, "host": "127.0.0.1", "port": 6379 }
}Invalid API keyorPermission 'write' required: checkauth.enabled,X-API-Key, and key permissions inconfig.json.Global access not permitted: your key needs"global"permission for REST global writes.SQLite adapter failed to load: installbetter-sqlite3and ensure native build support.PostgreSQL adapter failed to load: installpgand verify connection string.Redis disabled: ioredis module not available: installioredisor set"redis": { "enabled": false }.- Slow first request: embedding model initialization is cold-start heavy on first run.
- MCP HTTP connector issues: confirm server started with
npm run start:mcp:httpand use/sseendpoint.
Latency and throughput numbers in this README are environment-dependent and vary by model, hardware, storage backend, and network conditions. Use your own workload benchmarks for production sizing.
- Connection Pooling: Redis handles connection pooling automatically
- Memory Management: Monitor Redis memory usage with
INFO memory - Persistence: Configure Redis AOF/RDB for data durability
- Monitoring: Use Redis
INFOcommand and keyspace notifications
- TTL-Based Expiration: Reduces need for manual invalidation
- Stampede Protection: Prevents thundering herd on cache misses
- Hierarchical Caching: LRU + Redis for optimal performance
- At-Least-Once Delivery: RPOPLPUSH ensures jobs aren't lost
- Deduplication: Redis sets prevent duplicate job processing
- Monitoring: Track queue lengths and processing times
- Read Replicas: Use Redis replication for read-heavy workloads
- Sharding: Consider Redis Cluster for massive scale
- Backup: Regular Redis backups for disaster recovery
Automatic schema upgrades with version tracking:
-- Automatically applied on startup
ALTER TABLE nodes ADD COLUMN agent_id TEXT;
CREATE INDEX idx_nodes_agent_id ON nodes(agent_id);API key-based authentication with granular permissions:
{
"auth": {
"apiKeys": {
"agent-key": ["read", "write", "global"]
}
}
}JSON logging for monitoring and debugging:
{
"timestamp": "2026-04-29T18:30:50.000Z",
"level": "INFO",
"message": "Memory stored",
"agentId": "claude-assistant",
"action": "store",
"duration": 45
}MIT