## 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 **[nullure@cavira.app](mailto:nullure@cavira.app)**

## OpenMemory

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

[](https://marketplace.visualstudio.com/items?itemName=Nullure.openmemory-vscode)
[](https://discord.gg/93M9XSuEj6)
[](https://pypi.org/project/openmemory-py/)
[](https://www.npmjs.com/package/openmemory-js)
[](LICENSE)



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](https://www.orcarouter.ai), 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.

```
/* 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.

- Bugs: https://github.com/CaviraOSS/OpenMemory/issues
- Feature requests: use the GitHub issue templates
- Before large changes, open a discussion or small design PR

---

## 13. License

OpenMemory is licensed under **Apache 2.0**. See [LICENSE](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](https://github.com/CaviraOSS/OpenMemory/issues)

## Links

- [GitHub](https://github.com/CaviraOSS/OpenMemory)
- [Documentation](https://github.com/CaviraOSS/OpenMemory/blob/main/README.md)
- [Changelog](https://github.com/CaviraOSS/OpenMemory/blob/main/CHANGELOG.md)

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.

## Related docs

- `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:

```
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`:

```
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

- [Node SDK](./node-sdk.md) - Direct API usage in Node.js applications
- [Python SDK](./python-sdk.md) - Direct API usage in Python applications
- [Getting Started](./getting-started.md) - Installation and setup guide