Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ AWS_REGION=us-east-1

# Ollama Local Embeddings
OLLAMA_URL=http://localhost:11434
OM_OLLAMA_MODEL=bge-m3:latest

# Local Model Path (for custom embedding models)
LOCAL_MODEL_PATH=/path/to/your/local/model
Expand Down Expand Up @@ -167,6 +168,57 @@ OM_KEYWORD_MIN_LENGTH=3

OM_MIN_SCORE=0.3

# --------------------------------------------
# Optional FalkorDB GraphRAG bridge
# --------------------------------------------
# Keep disabled until FalkorDB + tools/openmemory-graphrag-bridge are running.
OM_GRAPHRAG_ENABLED=false
OM_GRAPHRAG_URL=http://127.0.0.1:8765
# Local GraphRAG + Ollama can take well over 15s on first ingest/query.
OM_GRAPHRAG_TIMEOUT_MS=120000
OM_GRAPHRAG_BRIDGE_API_KEY=

# Explicit write gate for /graphrag/sync and GraphRAG mirroring.
OM_GRAPHRAG_WRITE_ENABLED=false
# Keep false unless the server is strictly loopback/firewalled and the caller is trusted.
OM_GRAPHRAG_ALLOW_UNAUTH_WRITE=false
# Keep false unless the graph is intentionally global and safe to query without user/project filtering.
OM_GRAPHRAG_ALLOW_GLOBAL_QUERY=false
# Legacy compatibility flag. Ordinary scoped queries no longer require this once
# the graph has structured scope properties on Document/Chunk nodes.
OM_GRAPHRAG_ALLOW_UNFILTERED_SCOPED_QUERY=false

# Best-effort mirror of new /memory/add writes into GraphRAG.
# Keep false until redaction/allowlist policy is explicit for the source.
OM_GRAPHRAG_SYNC_ON_ADD=false

# Include GraphRAG bridge output in /api/ide/context responses.
OM_GRAPHRAG_CONTEXT_ENABLED=false

FALKORDB_HOST=127.0.0.1
FALKORDB_PORT=6379
OM_GRAPHRAG_GRAPH_NAME=openmemory
OM_GRAPHRAG_LLM_MODEL=
# Optional guardrail for the GraphRAG LLM completion path.
OM_GRAPHRAG_LLM_MAX_TOKENS=
OM_GRAPHRAG_EMBEDDER_MODEL=
# Match this to the chosen embedder output dimension. Example:
# local `ollama/bge-m3:latest` returns 1024 dimensions.
OM_GRAPHRAG_EMBEDDER_DIMENSIONS=256
OLLAMA_API_BASE=http://host.docker.internal:11434
HF_HOME=/root/.cache/huggingface
TRANSFORMERS_CACHE=/root/.cache/huggingface/transformers
OM_GRAPHRAG_GLINER_MODEL=urchade/gliner_medium-v2.1
OM_GRAPHRAG_GLINER_CACHE_DIR=/root/.cache/huggingface
OM_GRAPHRAG_GLINER_PREWARM=true
# Keep false for deterministic cached startup. Set true only if you explicitly
# want startup-time Hugging Face network fallback when the local cache misses or
# the cached snapshot cannot be loaded.
OM_GRAPHRAG_GLINER_ALLOW_ONLINE_FALLBACK=false
# Keep false for normal operation. Set true only if you intentionally need the
# stale-corpus compatibility fallback during scoped queries before backfill.
OM_GRAPHRAG_ENABLE_LEGACY_SCOPE_RECOVERY=false

# ============================================
# Smart Decay Settings (Time-Based Algorithm)
# ============================================
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ jobs:
OM_VEC_DIM: "1536"
steps:
- uses: actions/checkout@v4

- name: Check models mirror
run: node tools/sync-openmemory-models.mjs --check

- name: Set up Node.js
uses: actions/setup-node@v4
Expand All @@ -57,3 +60,22 @@ jobs:
run: |
cd packages/openmemory-js
npx tsx tests/test_omnibus.ts

test-graphrag-bridge:
name: Test GraphRAG bridge
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Build GraphRAG bridge image
run: |
docker build -t openmemory-graphrag-bridge:latest tools/openmemory-graphrag-bridge

- name: Run hermetic bridge E2E
run: |
python tools/openmemory-graphrag-bridge/tests/test_e2e_bridge_stack.py
7 changes: 5 additions & 2 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Check models mirror
run: node tools/sync-openmemory-models.mjs --check

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

Expand Down Expand Up @@ -47,7 +50,7 @@ jobs:
run: |
max_attempts=30
attempt=0
until curl -f http://localhost:8080/health || [ $attempt -eq $max_attempts ]; do
until curl -f http://localhost:8180/health || [ $attempt -eq $max_attempts ]; do
echo "Waiting for service to be healthy... (attempt $((attempt+1))/$max_attempts)"
sleep 2
attempt=$((attempt+1))
Expand All @@ -60,7 +63,7 @@ jobs:
fi

echo "✅ Service is healthy!"
curl -v http://localhost:8080/health
curl -v http://localhost:8180/health

- name: Show Container Logs
if: failure()
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ OpenMemory is a **cognitive memory engine** for LLMs and agents.
- 🧩 Integrations: LangChain, CrewAI, AutoGen, Streamlit, MCP, VS Code
- 📥 Sources: GitHub, Notion, Google Drive, OneDrive, Web Crawler
- 🔍 Explainable traces (see *why* something was recalled)
- 🕸 Optional FalkorDB GraphRAG sidecar for relationship-heavy retrieval

Your model stays stateless. **Your app stops being amnesiac.**

Expand Down Expand Up @@ -78,6 +79,28 @@ See the integrations section in the docs for concrete patterns.

---

### Optional FalkorDB GraphRAG

OpenMemory can mirror selected memories into a FalkorDB GraphRAG-SDK sidecar for
relationship-heavy and multi-hop retrieval. The existing HSG and temporal memory
systems stay enabled, and GraphRAG is off by default.

When enabled, OpenMemory uses the GraphRAG SDK incremental document APIs for
upserts and deletes, so memory updates can be propagated without rebuilding the
entire graph. Finalization remains explicit and should be batched deliberately.

See [docs/graphrag.md](docs/graphrag.md) for the bridge, Docker profile, API,
and MCP tools.

### Codex IDE/CLI autouse

Codex can use OpenMemory through MCP, the IDE context provider, and bounded
redacted hooks that store session/prompt events through `/api/ide/events`.

See [docs/codex-autouse.md](docs/codex-autouse.md).

---

### 🟦 Node / JavaScript (local-first)

Install:
Expand Down
72 changes: 67 additions & 5 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ services:
context: ./packages/openmemory-js
dockerfile: Dockerfile
ports:
- '8080:8080'
- '127.0.0.1:8180:8180'
environment:
# Core Configuration
- OM_PORT=${OM_PORT:-8080}
- OM_PORT=${OM_PORT:-8180}
- OM_MODE=${OM_MODE:-standard}
- OM_TIER=${OM_TIER:-hybrid}
- OM_DB_PATH=${OM_DB_PATH:-/data/openmemory.sqlite}
Expand Down Expand Up @@ -51,6 +51,7 @@ services:
# Ollama Provider
- OLLAMA_URL=${OLLAMA_URL:-http://localhost:11434}
- OM_OLLAMA_URL=${OM_OLLAMA_URL:-http://localhost:11434}
- OM_OLLAMA_MODEL=${OM_OLLAMA_MODEL:-}

# Local Model
- LOCAL_MODEL_PATH=${LOCAL_MODEL_PATH:-}
Expand Down Expand Up @@ -116,6 +117,18 @@ services:
# Keyword Extraction
- OM_KEYWORD_BOOST=${OM_KEYWORD_BOOST:-2.5}
- OM_KEYWORD_MIN_LENGTH=${OM_KEYWORD_MIN_LENGTH:-3}

# Optional FalkorDB GraphRAG bridge
- OM_GRAPHRAG_ENABLED=${OM_GRAPHRAG_ENABLED:-false}
- OM_GRAPHRAG_URL=${OM_GRAPHRAG_URL:-http://graphrag-bridge:8765}
- OM_GRAPHRAG_TIMEOUT_MS=${OM_GRAPHRAG_TIMEOUT_MS:-120000}
- OM_GRAPHRAG_BRIDGE_API_KEY=${OM_GRAPHRAG_BRIDGE_API_KEY:-}
- OM_GRAPHRAG_WRITE_ENABLED=${OM_GRAPHRAG_WRITE_ENABLED:-false}
- OM_GRAPHRAG_ALLOW_UNAUTH_WRITE=${OM_GRAPHRAG_ALLOW_UNAUTH_WRITE:-false}
- OM_GRAPHRAG_ALLOW_GLOBAL_QUERY=${OM_GRAPHRAG_ALLOW_GLOBAL_QUERY:-false}
- OM_GRAPHRAG_ALLOW_UNFILTERED_SCOPED_QUERY=${OM_GRAPHRAG_ALLOW_UNFILTERED_SCOPED_QUERY:-false}
- OM_GRAPHRAG_SYNC_ON_ADD=${OM_GRAPHRAG_SYNC_ON_ADD:-false}
- OM_GRAPHRAG_CONTEXT_ENABLED=${OM_GRAPHRAG_CONTEXT_ENABLED:-false}
volumes:
- openmemory_data:/data
restart: unless-stopped
Expand All @@ -125,7 +138,7 @@ services:
'CMD',
'node',
'-e',
'require("http").get("http://localhost:8080/health",(res)=>process.exit(res.statusCode===200?0:1)).on("error",()=>process.exit(1))',
'require("http").get("http://localhost:8180/health",(res)=>process.exit(res.statusCode===200?0:1)).on("error",()=>process.exit(1))',
]
interval: 30s
timeout: 10s
Expand All @@ -140,12 +153,12 @@ services:
context: ./dashboard
dockerfile: Dockerfile
args:
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-http://localhost:8080}
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-http://localhost:8180}
- NEXT_PUBLIC_API_KEY=${NEXT_PUBLIC_API_KEY:-}
ports:
- '3000:3000'
environment:
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-http://localhost:8080}
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-http://localhost:8180}
- NEXT_PUBLIC_API_KEY=${NEXT_PUBLIC_API_KEY:-}
depends_on:
openmemory:
Expand Down Expand Up @@ -175,9 +188,58 @@ services:
# retries: 3
# start_period: 30s

# Optional: FalkorDB + GraphRAG-SDK bridge for relationship-heavy retrieval.
# Start with: docker compose --profile graphrag up -d falkordb graphrag-bridge openmemory
falkordb:
profiles:
- graphrag
image: falkordb/falkordb:latest
ports:
- '127.0.0.1:${FALKORDB_HOST_PORT:-6379}:6379'
- '127.0.0.1:${FALKORDB_DASHBOARD_PORT:-3001}:3000'
volumes:
- falkordb_data:/data
restart: unless-stopped

graphrag-bridge:
profiles:
- graphrag
build:
context: ./tools/openmemory-graphrag-bridge
dockerfile: Dockerfile
ports:
- '127.0.0.1:${GRAPHRAG_BRIDGE_HOST_PORT:-8765}:8765'
environment:
- FALKORDB_HOST=falkordb
- FALKORDB_PORT=6379
- OM_GRAPHRAG_BRIDGE_API_KEY=${OM_GRAPHRAG_BRIDGE_API_KEY:-}
- OM_GRAPHRAG_GRAPH_NAME=${OM_GRAPHRAG_GRAPH_NAME:-openmemory}
- OM_GRAPHRAG_LLM_MODEL=${OM_GRAPHRAG_LLM_MODEL:-}
- OM_GRAPHRAG_LLM_MAX_TOKENS=${OM_GRAPHRAG_LLM_MAX_TOKENS:-}
- OM_GRAPHRAG_EMBEDDER_MODEL=${OM_GRAPHRAG_EMBEDDER_MODEL:-}
- OM_GRAPHRAG_EMBEDDER_DIMENSIONS=${OM_GRAPHRAG_EMBEDDER_DIMENSIONS:-256}
- OLLAMA_API_BASE=${OLLAMA_API_BASE:-http://host.docker.internal:11434}
- OM_GRAPHRAG_API_BASE=${OM_GRAPHRAG_API_BASE:-}
- HF_HOME=${HF_HOME:-/root/.cache/huggingface}
- TRANSFORMERS_CACHE=${TRANSFORMERS_CACHE:-/root/.cache/huggingface/transformers}
- OM_GRAPHRAG_GLINER_MODEL=${OM_GRAPHRAG_GLINER_MODEL:-urchade/gliner_medium-v2.1}
- OM_GRAPHRAG_GLINER_CACHE_DIR=${OM_GRAPHRAG_GLINER_CACHE_DIR:-/root/.cache/huggingface}
- OM_GRAPHRAG_GLINER_PREWARM=${OM_GRAPHRAG_GLINER_PREWARM:-true}
- OM_GRAPHRAG_GLINER_ALLOW_ONLINE_FALLBACK=${OM_GRAPHRAG_GLINER_ALLOW_ONLINE_FALLBACK:-false}
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
volumes:
- graphrag_bridge_hf_cache:/root/.cache/huggingface
depends_on:
- falkordb
restart: unless-stopped

volumes:
openmemory_data:
driver: local
falkordb_data:
driver: local
graphrag_bridge_hf_cache:
driver: local
# Uncomment if using Valkey
# valkey_data:
# driver: local
55 changes: 55 additions & 0 deletions docs/codex-autouse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Codex IDE/CLI Autouse

OpenMemory can be used by Codex through three layers:

1. MCP tools via `~/.codex/config.toml`:
`mcp_servers.openmemory.url = "http://localhost:8180/mcp"` plus
`bearer_token_env_var = "OPENMEMORY_API_KEY"` when server auth is enabled.
2. IDE context provider via `~/.codex/context.json`:
preferably through a local proxy such as
`http://127.0.0.1:8181/api/ide/context`, so `context.json` does not need to
carry a literal API key.
3. Codex hooks via `~/.codex/hooks/openmemory-active-bridge.js`.

The hook bridge is bounded and fail-open. It checks `/health`, emits
SessionStart `additionalContext` when OpenMemory is up, tries one bounded
`/api/ide/context` recall for the current project, falls back to recent
project memories through the local MCP surface when semantic recall is empty,
and stores only small redacted/truncated session or prompt events through
`/api/ide/events`.

## Safety Defaults

- High-confidence token-like strings are redacted before storage.
- Prompt excerpts are capped by `OPENMEMORY_HOOK_MAX_CONTENT` (`900` by
default).
- The hook uses `OPENMEMORY_API_KEY` or `OM_API_KEY` when present, and falls
back to `~/.codex/openmemory-api-key.txt` for local no-restart operation.
- A small local context proxy can read the same key file and inject `x-api-key`
for IDE context calls, removing the plaintext secret from `context.json`.
- Any timeout or OpenMemory failure exits `0` and does not block Codex.
- GraphRAG writes remain controlled separately by `OM_GRAPHRAG_WRITE_ENABLED`
and the authenticated write gate.

## Smoke

```powershell
node --check C:/Users/Михаило/.codex/hooks/openmemory-active-bridge.js
Invoke-RestMethod -Uri http://127.0.0.1:8180/health -TimeoutSec 5
```

Manual redaction smoke:

```powershell
$payload = '{"session_id":"codex-hook-smoke","cwd":"D:/BooksDocs/Project Astra","prompt":"Smoke sk-REDACTED-EXAMPLE"}'
$payload | node C:/Users/Михаило/.codex/hooks/openmemory-active-bridge.js prompt
```

Then query:

```powershell
Invoke-RestMethod -Uri http://127.0.0.1:8181/api/ide/context `
-Method Post `
-ContentType 'application/json' `
-Body '{"query":"OpenMemory hook redacted excerpt","project_id":"D:/BooksDocs/Project Astra","user_id":"codex","k":5}'
```
Loading