OpenMemory Documentation

Local persistent memory store for LLM applications including claude desktop, github copilot, codex, antigravity, etc.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy OpenMemory on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name openmemory -p 7331:7331 --restart always ghcr.io/caviraoss/longmemory:${LONGMEMORY_IMAGE_TAG:-latest}
Configured Services & Ports
βš™οΈ longmemory
image: ghcr.io/caviraoss/longmemory:${LONGMEMORY_IMAGE_TAG:-latest}
πŸ”Œ Ports: ${LONGMEMORY_PORT:-7331}:7331
βš™οΈ dashboard
image: build locally
πŸ”Œ Ports: ${LONGMEMORY_DASHBOARD_PORT:-3000}:3000
docker-compose.yml
yaml (docker-compose.yml)
#      __                      __  ___
#     / /   ____  ____  ____ _/  |/  /__  ____ ___  ____  _______  __
#    / /   / __ \/ __ \/ __ `/ /|_/ / _ \/ __ `__ \/ __ \/ ___/ / / /
#   / /___/ /_/ / / / / /_/ / /  / /  __/ / / / / / /_/ / /  / /_/ /
#  /_____/\____/_/ /_/\__, /_/  /_/\___/_/ /_/ /_/\____/_/   \__, /
#                      /____/                                 /____/
#
#  cavira oss (c) 2026  -  nullure (c) 2026
#  ----------------------------------------------------------
#  file  : docker-compose.yml
#  usage : supports LongMemory docker compose

services:
    longmemory:
        build:
            context: .
            dockerfile: Dockerfile
        image: ghcr.io/caviraoss/longmemory:${LONGMEMORY_IMAGE_TAG:-latest}
        ports:
            - '${LONGMEMORY_PORT:-7331}:7331'
        environment:
            LONGMEMORY_HOST: 0.0.0.0
            LONGMEMORY_PORT: 7331
            LONGMEMORY_DB_PATH: /data/longmemory.db
            LONGMEMORY_API_KEY: ${LONGMEMORY_API_KEY:-}
            LONGMEMORY_MCP_HTTP: ${LONGMEMORY_MCP_HTTP:-true}
            LONGMEMORY_ALLOWED_ORIGINS: ${LONGMEMORY_ALLOWED_ORIGINS:-http://127.0.0.1:3000}
            LONGMEMORY_RATE_LIMIT_ENABLED: ${LONGMEMORY_RATE_LIMIT_ENABLED:-false}
            LONGMEMORY_RATE_LIMIT_MAX_REQUESTS: ${LONGMEMORY_RATE_LIMIT_MAX_REQUESTS:-100}
            LONGMEMORY_EMBEDDING_PROVIDER: ${LONGMEMORY_EMBEDDING_PROVIDER:-}
            LONGMEMORY_EMBEDDING_TIER: ${LONGMEMORY_EMBEDDING_TIER:-deep}
            LONGMEMORY_EMBEDDING_DIMENSION: ${LONGMEMORY_EMBEDDING_DIMENSION:-1536}
            LONGMEMORY_OLLAMA_URL: ${LONGMEMORY_OLLAMA_URL:-http://host.docker.internal:11434}
            LONGMEMORY_OLLAMA_EMBEDDING_MODEL: ${LONGMEMORY_OLLAMA_EMBEDDING_MODEL:-nomic-embed-text}
            OPENAI_API_KEY: ${OPENAI_API_KEY:-}
            GEMINI_API_KEY: ${GEMINI_API_KEY:-}
            AWS_REGION: ${AWS_REGION:-}
            AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-}
            AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-}
        volumes:
            - longmemory_data:/data
        restart: unless-stopped
        healthcheck:
            test:
                [
                    'CMD',
                    'node',
                    '-e',
                    "fetch('http://127.0.0.1:7331/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
                ]
            interval: 30s
            timeout: 5s
            retries: 3
            start_period: 20s

    dashboard:
        profiles: ['ui']
        build:
            context: ./dashboard
            dockerfile: Dockerfile
        ports:
            - '${LONGMEMORY_DASHBOARD_PORT:-3000}:3000'
        environment:
            LONGMEMORY_API_URL: http://longmemory:7331
            LONGMEMORY_API_KEY: ${LONGMEMORY_API_KEY:-}
        depends_on:
            longmemory:
                condition: service_healthy
        restart: unless-stopped

volumes:
    longmemory_data:
        name: longmemory_data

File: README.md

🚧 This project is currently being rewritten.

Expect breaking changes and potential bugs.

πŸš€ **We’re actively accepting volunteers!**

We’re looking for developers, social media volunteers, designers, content creators, community helpers, and more. If you’d like to contribute and be part of what we’re building, we’d love to have you!

πŸ“© Interested? Reach out at [email protected]

OpenMemory

Real long-term memory for AI agents. Not RAG. Not a vector DB. Self-hosted, Python + Node.





OpenMemory is a cognitive memory engine for LLMs and agents.

  • 🧠 Real long-term memory (not just embeddings in a table)
  • πŸ’Ύ Self-hosted, local-first (SQLite / Postgres)
  • 🐍 Python + 🟦 Node SDKs
  • 🧩 Integrations: LangChain, CrewAI, AutoGen, Streamlit, MCP, VS Code
  • πŸ“₯ Sources: GitHub, Notion, Google Drive, OneDrive, Web Crawler
  • πŸ” Explainable traces (see why something was recalled)

Your model stays stateless. Your app stops being amnesiac.


1. TL;DR – Use It in 10 Seconds

🐍 Python (local-first)

Install:

bash
pip install openmemory-py

Use:

python
from openmemory.client import Memory

mem = Memory()
mem.add("user prefers dark mode", user_id="u1")
results = mem.search("preferences", user_id="u1")
await mem.delete("memory_id")

Note: add, search, get, delete are async. Use await in async contexts.

πŸ”— OpenAI

python
mem = Memory()
client = mem.openai.register(OpenAI(), user_id="u1")
resp = client.chat.completions.create(...)

🧱 LangChain

python
from openmemory.integrations.langchain import OpenMemoryChatMessageHistory

history = OpenMemoryChatMessageHistory(memory=mem, user_id="u1")

🀝 CrewAI / AutoGen / Streamlit

OpenMemory is designed to sit behind agent frameworks and UIs:

  • Crew-style agents: use Memory as a shared long-term store
  • AutoGen-style orchestrations: store dialog + tool calls as episodic memory
  • Streamlit apps: give each user a persistent memory by user_id

See the integrations section in the docs for concrete patterns.


🟦 Node / JavaScript (local-first)

Install:

bash
npm install openmemory-js

Use:

ts
import { Memory } from "openmemory-js"

const mem = new Memory()
await mem.add("user likes spicy food", { user_id: "u1" })
const results = await mem.search("food?", { user_id: "u1" })
await mem.delete("memory_id")

Drop this into:

  • Node backends
  • CLIs
  • local tools
  • anything that needs durable memory without running a separate service.

πŸ“₯ Connectors

Ingest data from external sources directly into memory:

python
# python
github = mem.source("github")
await github.connect(token="ghp_...")
await github.ingest_all(repo="owner/repo")
ts
// javascript
const github = await mem.source("github")
await github.connect({ token: "ghp_..." })
await github.ingest_all({ repo: "owner/repo" })

Available connectors: github, notion, google_drive, google_sheets, google_slides, onedrive, web_crawler


2. Modes: SDKs, Server, MCP

OpenMemory can run inside your app or as a central service.

2.1 Python SDK

  • βœ… Local SQLite by default
  • βœ… Supports external DBs (via config)
  • βœ… Great fit for LangChain / LangGraph / CrewAI / notebooks

Docs: https://openmemory.cavira.app/docs/sdks/python


2.2 Node SDK

  • Same cognitive model as Python
  • Ideal for JS/TS applications
  • Can either run fully local or talk to a central backend

Docs: https://openmemory.cavira.app/docs/sdks/javascript


2.3 Backend server (multi-user + dashboard + MCP)

Use when you want:

  • org‑wide memory
  • HTTP API
  • dashboard
  • MCP server for Claude / Cursor / Windsurf

Run from source:

bash
git clone https://github.com/CaviraOSS/OpenMemory.git
cd OpenMemory
cp .env.example .env

cd packages/openmemory-js
npm install
npm run dev   # default :8080

Or with Docker (API + MCP):

bash
docker compose up --build -d

Optional: include the dashboard service profile:

bash
docker compose --profile ui up --build -d

Using Doppler-managed config (recommended for hosted dashboard/API URLs):

bash
cd OpenMemory
tools/ops/compose_with_doppler.sh up -d --build

Check service status:

bash
docker compose ps
curl -f http://localhost:8080/health

The backend exposes:

  • /api/memory/* – memory operations
  • /api/temporal/* – temporal knowledge graph
  • /mcp – MCP server
  • dashboard UI (when ui profile is enabled)

3. Why OpenMemory (vs RAG, vs β€œjust vectors”)

LLMs forget everything between messages.
Most β€œmemory” solutions are really just RAG pipelines:

  • text is chunked
  • embedded into a vector store
  • retrieved by similarity

They don’t understand:

  • whether something is a fact, event, preference, or feeling
  • how recent / important it is
  • how it links to other memories
  • what was true at a specific time

Cloud memory APIs add:

  • vendor lock‑in
  • latency
  • opaque behavior
  • privacy problems

OpenMemory gives you an actual memory system:

  • 🧠 Multi‑sector memory (episodic, semantic, procedural, emotional, reflective)
  • ⏱ Temporal reasoning (what was true when)
  • πŸ“‰ Decay & reinforcement instead of dumb TTLs
  • πŸ•Έ Waypoint graph (associative, traversable links)
  • πŸ” Explainable traces (see which nodes were recalled and why)
  • 🏠 Self‑hosted, local‑first, you own the DB
  • πŸ”Œ SDKs + server + VS Code + MCP

It behaves like a memory module, not a β€œvector DB with marketing copy”.


4. The β€œOld Way” vs OpenMemory

Vector DB + LangChain (cloud-heavy, ceremony):

python
import os
import time
from langchain.chains import ConversationChain
from langchain.memory import VectorStoreRetrieverMemory
from langchain_community.vectorstores import Pinecone
from langchain_openai import ChatOpenAI, OpenAIEmbeddings

os.environ["PINECONE_API_KEY"] = "sk-..."
os.environ["OPENAI_API_KEY"] = "sk-..."
time.sleep(3)  # cloud warmup

embeddings = OpenAIEmbeddings()
pinecone = Pinecone.from_existing_index(embeddings, index_name="my-memory")
retriever = pinecone.as_retriever(search_kwargs={"k": 2})
memory = VectorStoreRetrieverMemory(retriever=retriever)
conversation = ConversationChain(llm=ChatOpenAI(), memory=memory)

conversation.predict(input="I'm allergic to peanuts")

OpenMemory (3 lines, local file, no vendor lock-in):

python
from openmemory.client import Memory

mem = Memory()
mem.add("user allergic to peanuts", user_id="user123")
results = mem.search("allergies", user_id="user123")

βœ… Zero cloud config β€’ βœ… Local SQLite β€’ βœ… Offline‑friendly β€’ βœ… Your DB, your schema


5. Features at a Glance

  • Multi-sector memory
    Episodic (events), semantic (facts), procedural (skills), emotional (feelings), reflective (insights).

  • Temporal knowledge graph
    valid_from / valid_to, point‑in‑time truth, evolution over time.

  • Composite scoring
    Salience + recency + coactivation, not just cosine distance.

  • Decay engine
    Adaptive forgetting per sector instead of hard TTLs.

  • Explainable recall
    β€œWaypoint” traces that show exactly which nodes were used in context.

  • Embeddings
    OpenAI, Gemini, Ollama, AWS, OrcaRouter, synthetic fallback.

  • Integrations
    LangChain, CrewAI, AutoGen, Streamlit, MCP, VS Code, IDEs.

  • Connectors
    Import from GitHub, Notion, Google Drive, Google Sheets/Slides, OneDrive, Web Crawler.

  • Migration tool
    Import memories from Mem0, Zep, Supermemory and more.

If you’re building agents, copilots, journaling systems, knowledge workers, or coding assistants, OpenMemory is the piece that turns them from β€œgoldfish” into something that actually remembers.


6. MCP & IDE Workflow

OpenMemory ships a native MCP server, so any MCP‑aware client can treat it as a tool.

Claude / Claude Code

bash
claude mcp add --transport http openmemory http://localhost:8080/mcp

Cursor / Windsurf

.mcp.json:

json
{
  "mcpServers": {
    "openmemory": {
      "type": "http",
      "url": "http://localhost:8080/mcp"
    }
  }
}

Available tools include:

  • openmemory_query
  • openmemory_store
  • openmemory_list
  • openmemory_get
  • openmemory_reinforce

Your IDE assistant can query, store, list, and reinforce memories without you wiring every call manually.


7. Temporal Knowledge Graph

OpenMemory treats time as a first‑class dimension.

Concepts

  • valid_from / valid_to – truth windows
  • auto‑evolution – new facts close previous ones
  • confidence decay – old facts fade gracefully
  • point‑in‑time queries – β€œwhat was true on X?”
  • timelines – reconstruct an entity’s history
  • change detection – see when something flipped

Example

http
POST /api/temporal/fact
{
  "subject": "CompanyX",
  "predicate": "has_CEO",
  "object": "Alice",
  "valid_from": "2021-01-01"
}

Then later:

http
POST /api/temporal/fact
{
  "subject": "CompanyX",
  "predicate": "has_CEO",
  "object": "Bob",
  "valid_from": "2024-04-10"
}

Alice’s term is automatically closed; timeline queries stay sane.


8. CLI (opm)

The opm CLI talks directly to the engine / server.

Install

bash
cd packages/openmemory-js
npm install
npm run build
npm link   # adds `opm` to your PATH

Usage

bash
# Start the API server
opm serve

# In another terminal:
opm health
opm add "Recall that I prefer TypeScript over Python" --tags preference
opm query "language preference"

Commands

bash
opm add "user prefers dark mode" --user u1 --tags prefs
opm query "preferences" --user u1 --limit 5
opm list --user u1
opm delete 
opm reinforce 
opm stats

Useful for scripting, debugging, and non‑LLM pipelines that still want memory.


9. Architecture (High Level)

OpenMemory uses Hierarchical Memory Decomposition with a temporal graph on top.

text
/* Detailed source-code truncated for AI context efficiency. */

10. Migration

OpenMemory ships a migration tool to import data from other memory systems.

Supported:

  • Mem0
  • Zep
  • Supermemory

Example:

bash
cd migrate
python -m migrate --from zep --api-key ZEP_KEY --verify

(See migrate/ and docs for detailed commands per provider.)


11. Roadmap

  • 🧬 Learned sector classifier (trainable on your data)
  • πŸ•Έ Federated / clustered memory nodes
  • 🀝 Deeper LangGraph / CrewAI / AutoGen integrations
  • πŸ”­ Memory visualizer 2.0
  • πŸ” Pluggable encryption at rest

Star the repo to follow along.


12. Contributing

Issues and PRs are welcome.


13. License

OpenMemory is licensed under Apache 2.0. See LICENSE for details.


File: apps/vscode-extension/README.md

OpenMemory - Persistent Memory for AI Assistants

Give your AI tools instant access to your entire coding history. OpenMemory remembers everything you code and automatically provides context to GitHub Copilot, Cursor, Claude, and other AI assistants.

Features

  • Works with GitHub Copilot, Cursor, Claude, Windsurf, Codex, and any MCP-compatible AI
  • Auto-configures all AI tools on first run with zero manual setup
  • Tracks every file edit, save, and open automatically
  • NEW: Manually add code selections to memory with a single click
  • Compresses memories to reduce tokens by 30-70%
  • Query responses under 80ms with smart caching
  • Real-time token savings and compression metrics
  • Background processing never blocks UI

Quick Start

  1. Install this extension
  2. Start backend
  3. Click OpenMemory icon in status bar to verify connection
  4. Start coding - AI tools now access your coding memory

Requirements

Backend server required.

Settings

  • openmemory.backendUrl: Backend URL (default: http://localhost:8080)
  • openmemory.apiKey: API key for auth (optional)
  • openmemory.useMCP: Use MCP protocol mode (default: false) - connects to backend MCP server with tools: openmemory_query, openmemory_store, openmemory_list, openmemory_get, openmemory_reinforce
  • openmemory.mcpServerPath: Path to backend MCP server (default: backend/dist/ai/mcp.js)
  • openmemory.userId: Custom User ID (optional, defaults to auto-generated)
  • openmemory.projectName: Custom Project Name (optional, defaults to workspace name)

Commands

  • OpenMemory: Query Context - Search your coding memory
  • OpenMemory: Add Selection to Memory - Save selected code to memory
  • OpenMemory: Quick Note - Add a manual note to memory
  • OpenMemory: View Patterns - View detected patterns
  • OpenMemory: Toggle Tracking - Pause or resume tracking
  • OpenMemory: Setup - Configure backend and settings

Privacy

All data stores locally. No telemetry. Open source code available for audit.

Troubleshooting

Check backend running: curl http://localhost:8080/health

For issues, see GitHub

Made by the Cavira team


File: dashboard/README.md

OpenMemory Dashboard

This app is the optional OpenMemory dashboard UI.

What it is

  • a separate Next.js app in dashboard/
  • designed to talk to an OpenMemory backend over HTTP
  • not bundled into the bare packages/openmemory-js npm install

If you are running OpenMemory without the dashboard, you only need the backend in packages/openmemory-js.

Backend requirement

Start the backend first:

bash
cd packages/openmemory-js
npm install
npm run dev

By default the dashboard calls its same-origin server-side proxy at /api/openmemory, which forwards requests to the OpenMemory backend.
Configure the backend URL and optional API key in .env.local:

env
OPENMEMORY_API_URL=http://localhost:8080
# OPENMEMORY_API_KEY=your-secret-api-key

This keeps authenticated backend API keys on the server. Set NEXT_PUBLIC_API_URL only when the dashboard must call a different URL directly; API keys should remain in the server-only OPENMEMORY_API_KEY or OM_API_KEY environment variables.

Run the dashboard locally

bash
cd dashboard
npm install
npm run dev

Then open http://localhost:3000.

Docker

If you want the full local stack, you can also run OpenMemory with Docker and enable the dashboard/UI profile from the repository root.

  • README.md β€” top-level project overview
  • dashboard/CHAT_SETUP.md β€” dashboard-to-backend setup details
  • packages/openmemory-js/README.md β€” backend / SDK docs

File: docs/api-server.md

API Server

OpenMemory exposes a REST API for language-agnostic integration.

Base URL: http://localhost:8080 (default)

Endpoints

`POST /memory/add`

Add a new memory.

Body:

json
{
  "content": "My cat's name is Luna",
  "user_id": "user_123",
  "tags": ["pet"]
}

`POST /memory/search`

Search for memories.

Body:

json
{
  "query": "What is the pet name?",
  "user_id": "user_123",
  "limit": 3
}

Response:

json
{
  "memories": [
    {
      "id": "mem_abc123",
      "content": "My cat's name is Luna",
      "score": 0.89
    }
  ]
}

`GET /health`

Returns 200 OK if the system is running.

Running the Server

You can run the server using Docker or the Node CLI.

Docker

bash
docker run -p 8080:8080 openmemory/server

CLI

bash
opm serve --port 9000

File: docs/concepts.md

Core Concepts

OpenMemory differs from a standard Vector DB by implementing a cognitive architecture inspired by human memory systems.

Memory Architecture

  1. Episodic Memory: Stores specific events and interactions.
  2. Semantic Memory: Stores generalized facts and knowledge derived from episodes.
  3. Procedural Memory: (Planned) Stores "how-to" knowledge and tools.

The Hierarchical Storage Graph (HSG)

Data is not just dumped into a flat index. It is organized hierarchically:

  • Sectors: High-level domains (e.g., "Personal", "Work", "Code").
  • Nodes: Individual memory units.
  • Edges: Relationships between memories (temporal, semantic, or explicit entities).

Temporal Graph

Time is a first-class citizen. OpenMemory tracks:

  • Creation Time: When the memory was formed.
  • Last Access: When it was last retrieved (used for decay).
  • Sequence: The causal chain of events (Chat History is a temporal chain).

This allows for queries like "What did we talk about last week?" or "What happened before I mentioned the bug?".

Retrieval Dynamics (Scoring)

When you call search(), memories are scored based on three factors:

  1. Relevance (Vector Similarity): How semantically similar is the query?
  2. Recency: Recent memories are weighted higher (decay function).
  3. Importance: "Core" memories (often retrieved) gain persistence.

Score = (Similarity * alpha) + (Recency * beta) + (Importance * gamma)

User Partitioning

All memories are strictly partitioned by user_id. This ensures that in multi-user applications (like a SaaS bot), User A never sees User B's memories.


File: docs/faq.md

Frequently Asked Questions

How does this differ from Chroma/Pinecone?

OpenMemory is an agentic memory layer, not just a vector database. It handles user separation, temporal tracking, and memory dynamics (decay, reinforcement) out of the box.

Can I use it with any LLM?

Yes. OpenMemory is model-agnostic. You can use OpenAI, Anthropic, or local models (Llama 3 via Ollama).

Is the data persistent?

Yes. By default, it uses SQLite which saves to a file. You can also configure Postgres for production scaling.


File: docs/getting-started.md

Getting Started with OpenMemory

OpenMemory provides a drop-in, SQL-native long-term memory layer for your AI agents. It goes beyond simple vector storage by incorporating temporal graphs, user entity tracking, and advanced retrieval dynamics (Recency, Frequency, Importance).

Installation

Python

bash
pip install openmemory-py

Node.js

bash
npm install openmemory-js

Quick Start (Python)

python
import asyncio
from openmemory.client import Memory

async def main():
    # 1. Initialize (uses local sqlite by default)
    mem = Memory()
    
    # 2. Add a memory
    await mem.add("I am a software engineer interested in AI.", user_id="user_123")
    
    # 3. Search related context
    context = await mem.search("What is my job?", user_id="user_123")
    print(context)
    # output: [{'content': 'I am a software engineer...', ...}]

if __name__ == "__main__":
    asyncio.run(main())

Quick Start (Node.js)

javascript
const { Memory } = require('openmemory-js');

async function main() {
    const mem = new Memory();
    await mem.add("I prefer coffee over tea.", { user_id: 'user_123' });
    
    const context = await mem.search("What do I drink?", { user_id: 'user_123' });
    console.log(context);
}

main();

Configuration

OpenMemory defaults to sqlite:///openmemory.db in the current directory. You can configure this via environment variables:

  • OPENMEMORY_DB_URL: Database connection string (e.g., postgresql://...)
  • OPENMEMORY_DEBUG: Set to true for verbose logging.

File: docs/mcp.md

MCP Server Reference

OpenMemory provides a Model Context Protocol (MCP) server that exposes memory operations as tools for AI assistants like Claude, Cursor, and Windsurf.

Setup

Installation

bash
# Use via npx (no installation needed)
npx -y openmemory-js mcp

# Or install globally
npm install openmemory-js
openmemory-js mcp

Configuration

Configure your MCP client (.mcp.json for Cursor/Windsurf, or Claude settings):

json
{
  "mcpServers": {
    "openmemory": {
      "command": "npx",
      "args": ["-y", "openmemory-js", "mcp"],
      "env": {
        "OM_METADATA_BACKEND": "sqlite",
        "OM_EMBEDDINGS": "openai",
        "OPENAI_API_KEY": "your-api-key"
      }
    }
  }
}

Environment Variables

  • OM_METADATA_BACKEND: Database type (sqlite or postgres)
  • OM_EMBEDDINGS: Embedding provider (openai, aws, ollama, synthetic, orcarouter)
  • Database credentials (if using Postgres): OM_PG_HOST, OM_PG_DB, OM_PG_USER, OM_PG_PASSWORD

Memory Systems

OpenMemory provides two complementary memory systems:

Contextual Memory (HSG)

Semantic memory organized into cognitive sectors (episodic, semantic, procedural, emotional, reflective) with vector-based retrieval.

Best for: Conversations, rich context, experiential memories

Temporal Facts

Structured facts (subject-predicate-object triples) with time-based validity and automatic invalidation.

Best for: Preferences, business rules, configurations that change over time

Available Tools

openmemory_store

Store content in contextual memory, temporal facts, or both.

Parameters

Parameter Type Required Default Description
content string Yes - Raw memory text
type enum No "contextual" Storage type: "contextual", "factual", or "both"
facts array Conditional - Facts array (required if type is "factual" or "both")
tags string[] No - Tags for contextual storage
metadata object No - Additional metadata
user_id string No - User identifier
project_id string No "system_global" Project identifier for isolation

Facts Array Schema

typescript
{
  subject: string,      // Entity (e.g., "user_123", "client_acme")
  predicate: string,    // Relationship (e.g., "prefers_format", "approval_limit")
  object: string,       // Value (e.g., "Excel", "50000")
  confidence?: number,  // 0-1 score (default: 1.0)
  valid_from?: string   // ISO date (default: now)
}

Examples

Store contextual memory:

json
{
  "content": "User prefers morning meetings",
  "tags": ["preference", "scheduling"],
  "user_id": "user_123"
}

Store temporal fact:

json
{
  "content": "Client prefers Excel format",
  "type": "factual",
  "facts": [{
    "subject": "client_acme",
    "predicate": "prefers_report_format",
    "object": "Excel"
  }],
  "user_id": "user_123"
}

Store in both systems:

json
{
  "content": "Approval threshold updated to $75K",
  "type": "both",
  "facts": [{
    "subject": "expense_policy",
    "predicate": "approval_threshold_usd",
    "object": "75000"
  }],
  "tags": ["policy", "threshold"],
  "user_id": "user_123"
}

openmemory_store_project

Store content in contextual memory or temporal facts, SCOPED to a specific PROJECT. Use this for project-specific designs, local variables, or scoped knowledge that should not bleed into other projects.

Parameters

Identical to openmemory_store, but project_id is RECOMMENDED to ensure proper isolation.

Example

json
{
  "content": "Project uses Tailwind CSS for styling",
  "project_id": "my_web_app",
  "user_id": "user_123"
}

openmemory_query

Query contextual memories, temporal facts, or both.

Parameters

Parameter Type Required Default Description
query string Yes - Search text
type enum No "contextual" Query type: "contextual", "factual", or "unified"
fact_pattern object No - Pattern for temporal queries
at string No now ISO date for point-in-time queries
k number No 8 Max results for contextual queries
sector enum No - Filter by sector (episodic, semantic, procedural, emotional, reflective)
min_salience number No - Minimum salience threshold (0-1)
user_id string No - User identifier
project_id string No - Project isolation filter

Fact Pattern Schema

typescript
{
  subject?: string,    // Entity to match (undefined = wildcard)
  predicate?: string,  // Relationship to match (undefined = wildcard)
  object?: string      // Value to match (undefined = wildcard)
}

Examples

Query contextual memories:

json
{
  "query": "user preferences",
  "user_id": "user_123"
}

Query current facts:

json
{
  "query": "client report format",
  "type": "factual",
  "fact_pattern": {
    "subject": "client_acme",
    "predicate": "prefers_report_format"
  }
}

Historical query:

json
{
  "query": "Q3 approval limit",
  "type": "factual",
  "fact_pattern": {
    "subject": "expense_policy",
    "predicate": "approval_threshold_usd"
  },
  "at": "2023-09-30T00:00:00Z"
}

Unified query:

json
{
  "query": "client information",
  "type": "unified",
  "fact_pattern": {
    "subject": "client_acme"
  },
  "k": 10,
  "user_id": "user_123"
}

openmemory_list

List recent memories.

Parameters

Parameter Type Required Default Description
limit number No 10 Number of memories to return (max 50)
sector enum No - Filter by sector
user_id string No - User identifier
project_id string No - Project isolation filter

Example

json
{
  "limit": 20,
  "sector": "semantic",
  "user_id": "user_123"
}

openmemory_get

Fetch a single memory by ID.

Parameters

Parameter Type Required Default Description
id string Yes - Memory identifier
include_vectors boolean No false Include sector vector metadata
user_id string No - User identifier
project_id string No - Project isolation filter

Example

json
{
  "id": "mem_abc123",
  "include_vectors": true,
  "user_id": "user_123"
}

openmemory_reinforce

Boost salience of a memory.

Parameters

Parameter Type Required Default Description
id string Yes - Memory identifier
boost number No 0.1 Salience boost amount (0.01-1.0)

Example

json
{
  "id": "mem_abc123",
  "boost": 0.15
}

Response Formats

openmemory_store

Contextual storage:

json
{
  "type": "contextual",
  "hsg": {
    "id": "mem_abc123",
    "primary_sector": "semantic",
    "sectors": ["semantic", "procedural"]
  }
}

Factual storage:

json
{
  "type": "factual",
  "temporal": [{
    "id": "fact_xyz789",
    "subject": "client_acme",
    "predicate": "prefers_format",
    "object": "Excel",
    "valid_from": "2024-01-15T10:00:00.000Z",
    "confidence": 0.95
  }]
}

openmemory_query

Contextual query:

json
{
  "type": "contextual",
  "contextual": [{
    "source": "hsg",
    "id": "mem_abc123",
    "score": 0.8921,
    "content": "User prefers morning meetings...",
    "primary_sector": "semantic",
    "salience": 0.756
  }]
}

Factual query:

json
{
  "type": "factual",
  "factual": [{
    "source": "temporal",
    "id": "fact_xyz789",
    "subject": "client_acme",
    "predicate": "prefers_format",
    "object": "Excel",
    "confidence": 0.95,
    "valid_from": "2024-01-15T10:00:00.000Z",
    "valid_to": null
  }]
}

Unified query:

json
{
  "type": "unified",
  "contextual": [...],  // HSG results
  "factual": [...]      // Temporal facts
}

Key Features

Automatic Fact Invalidation

When storing a fact with the same subject+predicate, the previous fact is automatically closed:

text
Day 1: Store (client_acme, prefers_format, PDF)
       β†’ Stored with valid_to = null

Day 2: Store (client_acme, prefers_format, Excel)  
       β†’ Old fact: valid_to = Day 2 (closed)
       β†’ New fact: valid_to = null (current)

Point-in-Time Queries

Query what was true at any historical date:

json
{
  "type": "factual",
  "fact_pattern": {"subject": "client_acme", "predicate": "prefers_format"},
  "at": "2024-01-10T00:00:00Z"
}

Returns the fact that was valid on January 10th, even if it's since been updated.

Wildcard Patterns

Use undefined fields in fact_pattern for wildcards:

json
// All facts about client_acme
{"subject": "client_acme"}

// All preferences for any subject
{"predicate": "prefers"}

// All facts with object "Excel"
{"object": "Excel"}

Best Practices

Storage Type Selection

Type Use Case Example
contextual Rich narratives, conversations "Team discussed the Q4 strategy..."
factual Structured data that changes client_acme prefers_format Excel
both Rich context with extractable facts "Client wants monthly Excel reports"

Fact Naming Conventions

Subject: Specific entity identifier

  • βœ… user_123, client_acme_corp, expense_policy
  • ❌ the user, client, policy

Predicate: Clear relationship in snake_case

  • βœ… prefers_report_format, requires_approval_at, uses_data_source
  • ❌ preference, requirement, uses

Object: Concrete value

  • βœ… Excel, 50000, Salesforce_CRM
  • ❌ file format, high, CRM system

Query Strategy

Use type="contextual" when:

  • Asking open-ended questions
  • Needing semantic similarity
  • Searching conversations

Use type="factual" when:

  • Asking for specific current values
  • Querying structured data
  • Need historical accuracy

Use type="unified" when:

  • Need comprehensive context
  • Unsure which system has the answer
  • Want both semantic context AND facts

Integration Examples

Claude Desktop

json
{
  "mcpServers": {
    "openmemory": {
      "command": "npx",
      "args": ["-y", "openmemory-js", "mcp"]
    }
  }
}

Cursor / Windsurf

Add to .cursorrules or .windsurfrules:

text
When storing user information, use openmemory_store:
- type="contextual" for conversations
- type="factual" for preferences that may change
- Always include user_id parameter

When querying, use openmemory_query:
- type="unified" for comprehensive context
- Construct fact_pattern for specific fact queries

Programmatic (Node.js)

typescript
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';

const client = new Client({
  name: 'my-app',
  version: '1.0.0'
}, { capabilities: {} });

const transport = new StdioClientTransport({
  command: 'npx',
  args: ['-y', 'openmemory-js', 'mcp']
});

await client.connect(transport);

// Store memory
await client.callTool({
  name: 'openmemory_store',
  arguments: {
    content: "User prefers concise responses",
    type: "both",
    facts: [{
      subject: "user_123",
      predicate: "prefers_response_style",
      object: "concise"
    }],
    user_id: "user_123"
  }
});

// Query
const result = await client.callTool({
  name: 'openmemory_query',
  arguments: {
    query: "user preferences",
    type: "unified",
    user_id: "user_123"
  }
});

Common Patterns

Track Evolving Preferences

json
// Initial preference
{
  "content": "Client prefers PDF reports",
  "type": "both",
  "facts": [{"subject": "client_x", "predicate": "prefers_format", "object": "PDF"}]
}

// Updated preference (automatically invalidates old fact)
{
  "content": "Client now prefers Excel reports",
  "type": "both",
  "facts": [{"subject": "client_x", "predicate": "prefers_format", "object": "Excel"}]
}

// Query current preference
{
  "query": "client report format",
  "type": "factual",
  "fact_pattern": {"subject": "client_x", "predicate": "prefers_format"}
}
// Returns: Excel

Historical Analysis

json
// What was true last quarter?
{
  "query": "approval threshold in Q3",
  "type": "factual",
  "fact_pattern": {
    "subject": "expense_policy",
    "predicate": "approval_threshold_usd"
  },
  "at": "2023-09-30T00:00:00Z"
}

Comprehensive Context

json
// Get both conversations and facts
{
  "query": "client requirements",
  "type": "unified",
  "fact_pattern": {"subject": "client_x"},
  "k": 10
}
// Returns: Discussions + current facts

Database Schema

Contextual Memory Tables

  • memories / openmemory_memories - Memory content and metadata
  • vectors / openmemory_vectors - Sector-specific embeddings
  • waypoints / openmemory_waypoints - Associative graph connections

Temporal Graph Tables

  • temporal_facts - Subject-predicate-object facts with validity periods
  • temporal_edges - Relationships between facts

Both SQLite and Postgres are supported.

Troubleshooting

"Facts array is required" Error

When using type="factual" or type="both", you must provide the facts parameter:

json
{
  "content": "...",
  "type": "factual",
  "facts": [{ "subject": "...", "predicate": "...", "object": "..." }]
}

Empty Temporal Results

If type="factual" returns no results:

  1. Verify facts were stored with correct subject/predicate
  2. Check at parameter matches validity period
  3. Use wildcards in fact_pattern to broaden search

Connection Issues

Ensure environment variables are set:

  • Postgres: OM_PG_HOST, OM_PG_DB, OM_PG_USER, OM_PG_PASSWORD
  • Embeddings: OPENAI_API_KEY (or relevant provider key, e.g. ORCAROUTER_API_KEY)

Performance

  • Contextual queries: ~50-200ms (vector similarity + graph traversal)
  • Factual queries: ~5-20ms (indexed SQL lookups)
  • Unified queries: Run in parallel, total β‰ˆ max(contextual, factual)

See Also