Sandbox
@JingxuanC/causal-memory

MCP memory server for agent decision history

causal-memory adds a persistent causal memory store to agent workflows. It keeps facts, decision→outcome records, and causal chains in SQLite, then exposes them through MCP tools, HTTP, and integrations for Claude Code, Codex, Cursor, and other clients.

71 stars8 forksRustUpdated 7d ago
Who it's for

Builders who want their agent to recall past decisions, outcomes, and lessons instead of re-deriving them after compaction.

What it delivers

You can ask an agent to look up what happened before, predict what may happen next, and avoid repeating the same mistake.

What it does

Decision and outcome logging

Records `decision → outcome` links with relation types like caused, enabled, and prevented.

Causal and fact search

Offers `search_causal`, `search_facts`, and unified `search_memory` over the stored memory graph.

Forward and reverse reasoning

Includes `intervention_query`, `counterfactual_query`, `trace_cause`, and `trace_cause_chain` for prediction and root-cause lookup.

Memory consolidation

Runs a sleep consolidation cycle that replays, strengthens, weakens, and prunes memory without compacting the original graph.

Agent integrations

Ships Claude Code and Codex setup paths, plus Hermes and DeepSeek Harness plugins and a bundled skill.

How to get it

  1. 1Run
    git clone https://github.com/JingxuanC/causal-memory.git
    cd causal-memory
    cargo build --release
  2. 2Guided installer (recommended) — one command installs the skill, the causal-memory…
    ./install.sh                     # interactive, walks you through each step
    ./install.sh --yes               # non-interactive, accept all defaults
    ./install.sh --uninstall         # remove the skill (+ optional MCP)
  3. 3Or via the Skills CLI, or by hand
    # Skills CLI (skills.sh ecosystem) — works with Claude Code, Cursor,
    # Kimi Code CLI, Codex, Copilot and more:
    npx skills add JingxuanC/causal-memory@causal-memory
  4. 4Run
    ./target/release/causal-memory http --port 9938   # MCP Streamable HTTP
  5. 5Run
    cargo build --release --features local-embed
    # Uses BAAI/bge-small-en-v1.5 (384 dims, ~130MB, downloads once then offline)
  6. 6Run
    export CAUSAL_MEMORY_EMBED_API=https://open.bigmodel.cn/api/paas/v4
    export CAUSAL_MEMORY_EMBED_KEY=your-key
    export CAUSAL_MEMORY_EMBED_MODEL=embedding-3

README

causal-memory

An agent memory system with a causal core — and the only one that models inhibition.

Facts, temporal state, and decision → outcome causal edges on one SQLite store, powered by a hippocampus-style engine: typed spreading activation (excitatory and inhibitory), Hebbian co-occurrence reinforcement, Q-value dynamics, and immutable SWR consolidation. Agents recall what happened, when it was true, why it worked — and what would happen if they acted differently.

License: Apache-2.0 Status: v0.9.3 Tests: 368 Release: v0.9.3 Hermes plugin DSH plugin

English · 简体中文


Why

Every agent forgets why it made past decisions after a few context compactions. It re-fixes the same bug the same wrong way, re-debates the same architecture choice, relearns the same lesson.

This happens because causal information is the most fragile type under text compaction. Real-LLM benchmark (grok-build's production compaction prompt):

Compactions (k)Textual recallCausal-table recall
1100%100%
285%100%
355%100%
545%100%

The causal table survives because it lives outside the agent's context window — compaction cannot touch it.


Demo

30-second single scene — the agent is about to git push --no-verify; intervention_query fires a DANGER chain citing the lesson it recorded last time ("production login failed for 40 minutes; emergency rollback"):

30-second danger-warning demo

Download video · DANGER-scene screenshot · Regenerate: scripts/capture_demo30.pyscripts/render_demo30.py

A 21-second hands-on demo (real memory store, no mocks): pre-action warning (intervention_query → DANGER chain) → experience recall (search_causal) → counterfactual comparison (counterfactual_query) → write loop (record_decision → immediately searchable).

21-second demo

Download video · Warning-scene screenshot · Brand card · Regenerate: scripts/render_demo.py


Benchmarks

CausalEval — the causal memory benchmark (primary)

Most agent-memory benchmarks (LoCoMo, LongMemEval, Memora) test fact recall ("what is the user's preference"). causal-memory's differentiators — typed causal edges, inhibition, intervention prediction, cross-task transfer — are invisible on those suites. CausalEval measures them.

Design: the causal graph is the answer key. Typed DAGs are generated deterministically; conversations are narrated from the graph; gold answers are derived from graph structure — zero hand annotation, zero ambiguity.

CausalEval v13 (soft supersession) — 140 questions, 20 graphs (same LLM, same judge; v12 baseline was 70q/10 graphs; mem0 comparison ran on the 70q protocol):

Capabilitycausal-memoryv12 (70q)mem0 (70q)What it tests
C7 Update100%50%80%Supersede old belief after falsification (soft superseded_by annotation)
C3 Counterfactual95%90%80%Choosing between alternatives with known outcomes
C2 Intervention75%70%40%Forward prediction: "if X again, what happens?"
C4 Inhibition80%90%50%Distinguishing root-cause fix vs blast-radius limiter (prevented edges)
C1 Attribution85%90%90%Backward causal chain → root cause
C5 Temporal-causal90%100%90%Ordering on a causal chain
C6 Lesson transfer20%20%30%Cross-task analogy via meta edges (open limitation)
Overall78%81%65%

Key result: C7 update 50% → 100% (+50pp, 20/20 questions) and it holds at doubled sample size. Soft supersession annotates superseded edges (superseded_by) instead of hiding them — the falsification signal reaches the answer model while the old lesson stays retrievable for counterfactuals (C3 unharmed at 95%). The C6 gap (20% vs mem0 30%) is the remaining open limitation; C1/C4/C5 dips vs v12 are within re-distillation variance and new-graph difficulty (v12 and v13 do not share a distilled corpus).

Fact-recall benchmarks (not our strong suit)

On traditional fact-recall suites, causal-memory performs competitively but does not beat mem0 — this is expected, because fact recall is mem0's specialty and not where causal-memory adds value.

Benchmarkcausal-memorymem0Note
LoCoMo (strict judge)79.1%91.6%mem0's home turf
LongMemEval-S (full pipeline, deepseek-chat)76.4% @ 11.5K tok/q94.4% @ 6.8K tok/q (official) · 73.8% (ind. repro)single-model stack vs platform stack; see docs/benchmarks/longmemeval.md
Memora MPA67.4%71.8%−4.4pp
Compaction survival100%45%External table = immune to compaction
Agent repeat-mistake33%67%−34pp on trap-world

Capability tests (322 across the workspace)

These test capabilities that no fact store (mem0, Zep, Letta) can offer.

CapabilityWhat it provesTests
Prevented-edge warningprevented edge spreads −0.3 activation (GABA analogue)2
Trace-cause attributionBackward CSR traversal finds root cause2
Multi-hop causal chainForward K-hop spreading reaches 2-3 hop outcomes2
Inhibitory filteringPrevented outcomes appear as negative, not false positives1
Intervention comparisonSame outcome has +0.9 for "skip tests" and −0.3 for "add tests"4
SWR consolidationLTP strengthens replayed edges, LTD weakens unvisited, GC forgets dormant5
Q-value dynamicsGood decisions rank higher; Bellman propagates to parents3
Novelty entropyDiverse experience triggers consolidation; uniform does not3
Meta-edge miningCross-session pattern discovery (similar_to / repeated)3
Hebbian co-occurrenceRepeated co-activation strengthens connection3

What makes it different

Capabilitycausal-memorymem0ZepLettaHeLa-Mem
Typed causal semantics (caused/enabled/prevented)
prevented negative spread (inhibitory)
Hebbian co-occurrence edges (excitatory)
Immutable consolidation (delta + clone)
Q-value dynamic utility
Forward simulation (intervention_query)
SWR offline consolidation (LTP/LTD/GC)
Novelty-entropy consolidation trigger
Meta-edge cross-session pattern mining
Compaction survival evidence✅ +20.8pp
One graph unifying all memory types⚠️⚠️
Write-time gatekeeping (raw → session_logs)
Local ONNX embedding (offline)

Core innovation: the excitatory/inhibitory duality. HeLa-Mem (ACL 2026) builds the excitatory side (Hebbian co-activation, positive spread). causal-memory adds the inhibitory side (prevented edges spread negative activation — a GABA analogue). A complete memory needs both: "what caused this" and "what prevents this from happening again."


Architecture

architecture

Interactive version: docs/architecture.html

  ┌───────────────────────────────────────────────┐
  │           causal-memory (Rust, MCP)            │
  │                                                │
  │  14 tools ← Agent (stdio / HTTP)                 │
  │    ↓                                           │
  │  Write-time gatekeeping                        │
  │    raw turns → session_logs (audit only)       │
  │    distill → facts + causal edges (searchable) │
  │    ↓                                           │
  │  Unified retrieval (RRF fusion)                │
  │    BM25 + semantic cosine → RRF merge          │
  │    Fact layer (BM25 + embeddings)              │
  │    ↓                                           │
  │  ┌──── Hippocampus engine ──────────────────┐  │
  │  │ CSR graph + spreading activation          │  │
  │  │  caused (+1.0)   enabled (+0.5)           │  │
  │  │  prevented (−0.3) ← GABA inhibitory       │  │
  │  │  fact (+0.8)     meta (+0.6)              │  │
  │  │  co_occurrence (Hebbian, dynamic)         │  │
  │  │                                            │  │
  │  │ DG: SimHash pattern separation             │  │
  │  │ CA3: K-hop spreading (forward + reverse)   │  │
  │  │ CA1: Novelty entropy trigger               │  │
  │  │ SWR: LTP/LTD/GC (immutable delta + clone)  │  │
  │  │ Q-value: Bellman dynamics (MemRL-style)    │  │
  │  └────────────────────────────────────────────┘  │
  │    ↓                                           │
  │  SQLite (causal.db) — never compacted          │
  └───────────────────────────────────────────────┘

The causal_edges table is never compacted — it lives outside the agent's context window. That's the entire point.


Edge types

Edge typeSpread coeffBiological analogueMeaning
caused+1.0Glutamate (strong excitatory)"Doing X caused Y"
fact+0.8Semantic association"User is/has Z"
meta+0.6Cortical top-downCross-task pattern link
enabled+0.5Weak excitatory"Doing X enabled Y"
co_occurrencedynamicHebbian LTP"X and Y frequently co-occur"
prevented−0.3GABA (inhibitory)"Doing X prevented Y"
no_effect0.0No causal relationship

Quick start

git clone https://github.com/JingxuanC/causal-memory.git
cd causal-memory
cargo build --release

MCP integration (Claude Code, Cursor, grok-build, etc.)

First-class installers: Claude Code (integrations/claude-code/) and Codex CLI (integrations/codex/) — MCP registration + activation prompt/skill in one idempotent script each.

{
  "mcpServers": {
    "causal-memory": {
      "command": "/path/to/causal-memory/target/release/causal-memory",
      "env": {
        "CAUSAL_MEMORY_DB": "~/.local/share/causal-memory/causal.db"
      }
    }
  }
}

No Rust toolchain? pip install causal-memory puts the same causal-memory console script on your PATH (the full CLI — bare invocation is the stdio MCP server), so "command": "causal-memory" works as the MCP entry too.

To teach the agent when to use the memory tools (agents don't call them proactively without instruction), install the bundled agent skill skills/causal-memory/SKILL.md:

Guided installer (recommended) — one command installs the skill, the causal-memory server, and the MCP registration across every detected client (Claude Code / Cursor / Opencode / Claude Desktop / Kimi Code):

./install.sh                     # interactive, walks you through each step
./install.sh --yes               # non-interactive, accept all defaults
./install.sh --uninstall         # remove the skill (+ optional MCP)

Or via the Skills CLI, or by hand:

# Skills CLI (skills.sh ecosystem) — works with Claude Code, Cursor,
# Kimi Code CLI, Codex, Copilot and more:
npx skills add JingxuanC/causal-memory@causal-memory

…or copy skills/causal-memory/ into your agent's skills directory (e.g. ~/.agents/skills/causal-memory/), or paste CLAUDE.md into your system prompt / AGENTS.md.

HTTP transport (remote agents, multi-agent shared memory)

./target/release/causal-memory http --port 9938   # MCP Streamable HTTP

Observability endpoints on the same port:

GET /metrics                    Prometheus text (RED + recall metrics)
GET /healthz / /readyz          liveness / readiness (readiness probes the store)
GET /debug/recall?query=...     run a recall now, return the full JSON trace
                                (seeds, hop summary, per-result provenance)
GET /debug/recalls              newest-first recall audit rows (persisted,
                                schema v13 recall_audit table; survives restarts)

/metrics and /debug/* expose the recall corpus, so they accept opt-in bearer auth: set CAUSAL_MEMORY_HTTP_AUTH_TOKEN (env or causal-memory setconfig) and they require Authorization: Bearer <token> (unset = open, the previous behavior). /healthz / /readyz stay open on purpose — kubelet probes cannot send bearer headers and leak nothing. /mcp client auth is a separate mechanism: per-tenant bearer tokens (see Multi-tenant HTTP below). Without the token, do not expose the port to the public internet.

Structured JSON logs on stderr: CAUSAL_MEMORY_LOG_FORMAT=json.

Multi-tenant HTTP (per-tenant databases)

Point CAUSAL_MEMORY_TOKENS_FILE (env or causal-memory setconfig) at a JSON file mapping bearer tokens to tenant names:

{ "token-for-alice": "alice", "token-for-bob": "bob" }

With the file configured and non-empty, /mcp requires Authorization: Bearer <token>, and each tenant reads and writes its own SQLite store at <db-dir>/tenants/<tenant>.<fnv1a-hash>.db — one database per tenant, opened lazily on first request, so one tenant can never see another's facts or causal edges (covered by an end-to-end isolation test). Missing or unknown tokens get 401 and never create a database file. The file is reloaded when its mtime changes, so tenants can be added or revoked without a restart; if the file turns unreadable at runtime the last-good map stays in force (fail closed).

Unset (or an empty/unreadable file) keeps the previous behavior: no /mcp auth, one shared store — local and stdio usage are unaffected. The startup log states the mode: auth=multi-tenant (N tokens) vs auth=open.

Memory residency: every active tenant holds its own CausalStore and in-memory graph, so RSS grows with the tenant count — see docs/design/enterprise-scaling.md before packing many tenants into one process. The observability endpoints (/metrics, /debug/*) keep reporting on the default store and are still gated by CAUSAL_MEMORY_HTTP_AUTH_TOKEN, independently of tenant auth.

With local embeddings (no API key needed)

cargo build --release --features local-embed
# Uses BAAI/bge-small-en-v1.5 (384 dims, ~130MB, downloads once then offline)

With HTTP embeddings (OpenAI/ZhiPu/etc.)

export CAUSAL_MEMORY_EMBED_API=https://open.bigmodel.cn/api/paas/v4
export CAUSAL_MEMORY_EMBED_KEY=your-key
export CAUSAL_MEMORY_EMBED_MODEL=embedding-3

Python bindings (PyO3)

All 14 memory operations are also available as a Python package, built on the same causal_memory::memory::Memory facade the MCP server uses:

cd crates/causal-memory-py
pip install maturin
maturin develop          # builds and installs into the active venv
from causal_memory import CausalMemory

mem = CausalMemory("~/.local/share/causal-memory/causal.db")  # or CausalMemory.in_memory()
mem.record_decision("used Redis mutex for cache stampede protection",
                    "deadlock under load", "caused", "concurrency",
                    context="go 1.22, single redis, 5k rps")
print(mem.search_causal(query="cache stampede protection"))
print(mem.intervention_query("skip the test suite before shipping"))

Methods mirror the 17 MCP tools one-to-one and return the same text. Embedding and LLM features use the same CAUSAL_MEMORY_EMBED_* / CAUSAL_MEMORY_LLM_* environment variables; without them the bindings degrade gracefully to BM25-only retrieval. Smoke tests: maturin develop && pytest tests/.

macOS note: always build the bindings through maturin. Plain cargo build -p causal-memory-py --release fails to link — the Xcode CLT Python ships no libpython3.9 dylib (this is why the py crate sits outside the workspace default-members).


Integrations

Hermes memory provider

hermes-plugin/ turns causal-memory into a drop-in Hermes MemoryProvider — flat facts + decision→outcome causal lessons on one local SQLite store, per-profile by construction (<hermes_home>/causal-memory/causal.db). Wired hooks: system-prompt causal directory, budgeted prefetch recall, non-blocking sync_turn write-behind, and a hermes causal-memory stats CLI. Because the store lives outside the context window, Hermes compaction can't touch it. Install and configuration: hermes-plugin/README.md.

DeepSeek Harness (DSH) native plugin

dsh-plugin/ mounts all 16 causal-memory tools onto DSH's ctx.tools with clean names (no mcp__ prefix) and injects a system-prompt block telling the model when to consult the causal store. Zero runtime dependencies — JSON-RPC over stdio straight to the causal-memory binary. One-line install: dsh plugin --profile web add "$PWD/dsh-plugin" (needs the causal-memory binary — pip install causal-memory, or a repo cargo build --release). Details: dsh-plugin/README.md.


Seventeen MCP tools

ToolWhen to callWhat it does
record_decisionAfter acting on a decisionLogs decision → outcome as a causal edge with relation type; optional context records the world state — same task_tag + context becomes a comparable branch (fork)
rememberAfter any meaningful exchangeZero-friction alternative: paste conversation text, LLM auto-extracts facts/lessons/causal edges
search_causalBefore a non-trivial decisionBM25 + semantic retrieval of past causal episodes
record_factWhen learning a stable factRecords flat facts with scope + confidence; idempotent
search_factsWhen you need "what is" infoBM25 + semantic retrieval over the fact layer
search_memoryWhen unsure which typeUnified: facts + causal lessons fused by RRF
trace_causeWhen something failsSingle-hop reverse: which decision caused this outcome
trace_cause_chainDeep failure analysisMulti-hop backward traversal through the causal graph
invalidate_decisionWhen a lesson is wrongSoft-invalidate (hidden from search, kept for audit)
invalidate_patternWhen a mined pattern is wrongSoft-invalidate a meta edge (the #N handle from search_patterns)
resolve_updatesAfter contradicting outcomesLLM-judged supersession pass over diverged repeated decisions
search_patternsTo recall cross-task lessonsMined meta edges: similar_to / repeated / contradicts / refines
causal_directoryPinned in system promptL0 compact pointer list of what the agent knows
intervention_queryBefore taking an actionForward simulation: predicts outcomes (safe/warning/danger)
counterfactual_queryWhen choosing between optionsContrastive: compares recorded outcomes of two alternatives; renders same-context branches (natural experiments) when they exist; every verdict logs a falsifiable prediction
prediction_reportPeriodic calibration checkPrediction-ledger accuracy overall / per method / per task_tag + pending list
reconstruct_lessonWhen you want the distilled lessonReconstructive retrieval: Markov-blanket subgraph → coherent narrative, with optional N-way calibration

Sleep consolidation

causal-memory sleep --dry-run   # preview what would change
causal-memory sleep             # run consolidation cycle

Immutable SWR 2.0: produces a delta + clone (original graph untouched), with full audit log. Triple-criterion GC (weak AND dormant AND zero-access). Triggers automatically when novelty entropy exceeds threshold.


Causal distill pipeline

The distiller extracts structured memories from raw conversations:

Raw conversation → V3 extraction prompt (130 lines, 6 rules, 5 few-shot)
                   ↓
  Fact/Preference → agent_facts table (BM25 + embedding searchable)
  Lesson/Event    → causal edges (self-referential, searchable)
  Causal          → proper directed edge: decision → outcome
                    with relation type (caused/enabled/prevented)

Raw turns go to session_logs (audit/replay only) — they never enter the retrieval pool. This write-time gatekeeping keeps BM25 precision high.


System layer coverage

All 16 designed layers have end-to-end validation (322 workspace tests):

LayerBenchmarkTests
Fact layerMemora / LoCoMo
Causal edges (caused/enabled/prevented)Capability12
Hippocampus spreading activationCapability
SWR consolidation (LTP/LTD/GC)Longitudinal5
Q-value dynamicsLongitudinal3
Novelty entropy triggerLongitudinal3
Sleep-wake cycleLongitudinal1
Meta-edge pattern miningAdvanced3
Co-occurrence HebbianAdvanced3
Intervention query (forward sim)Advanced4
Trace cause chainCapability2
Inhibitory ablationInhibition2
Distill / retrieval / factsMemora / LoCoMo / LME
Compaction survivalCompact
Agent trap-worldAgent
Pipeline e2eMigration / Pipeline2

Build & test

cargo build --release                    # Build binary
cargo test --workspace --no-fail-fast  # Run 322 tests
cargo test --features local-embed     # Run with ONNX embedding tests
cargo clippy --workspace -- -D warnings # Lint

Agent Memory Challenge (AMC/01)

causal-memory enters the Agent Memory Leaderboard first evaluation cycle via an Add/Search integration server — a thin HTTP frontend over the same Memory facade the MCP server runs (BM25 + semantic + entity retrieval, RRF-fused; one store per user_id):

cargo build --release --bin causal-memory-amc
./target/release/causal-memory-amc --db-dir amc_data --port 8787 --write-mode raw
# --write-mode raw (no LLM, platform default) | distill (write-time LLM extraction)
# POST /add (store memory, user_id-isolated) · POST /search (ordered evidence) · GET /health

Docker route: docker build -t causal-memory-amc . && docker run -p 8787:8787 -v amc-data:/data causal-memory-amc. Submission details, method description, and the participation checklist live in docs/benchmarks/amc-2026.md.

Test suite breakdown:

  • 186 library unit tests (types, store, distill, patterns, hippocampus)
  • 45 library integration tests (capability, longitudinal, advanced, pipeline)
  • 91 CLI, benchmark-harness & MCP e2e tests

Research background

Full documentation map: docs/README.md — design docs, benchmark protocols, evaluation reports, paper drafts, and the literature survey.

This project is the engineering output of 17 research notes on agent memory architecture ([insights/01-17](https://github.com/Jin

Files in the repo

Repository payload29 top-level entries
  • .claude-plugin
  • .github
  • benches
  • crates
  • docs
  • dsh-plugin
  • hermes-plugin
  • integrations
  • plugins
  • scripts
  • skills
  • .dockerignore
  • .gitignore
  • .rustfmt.toml
  • Cargo.lock
  • Cargo.toml
  • CHANGELOG.md
  • CLAUDE.md
  • clippy.toml
  • Dockerfile
  • generate_promo.py
  • install.sh
  • LICENSE
  • Makefile
  • PROFILE.md
  • promo.html
  • README.md
  • README.zh-CN.md
  • rustfmt.toml

Discussion (0)

Ask about usage, or say what you built with it

Sign in to join the discussion.

No comments yet. Be the first to say what this is good for.

More connectors

Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface

86k

High-performance code intelligence MCP server. Indexes codebases into a persistent knowledge graph — average repo in milliseconds. 158 languages, sub-ms queries, 99% fewer tokens. Single static binary, zero dependencies.

43k

Universal provider proxy for OpenAI Codex & Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code

14k
okf-memory/
okf-agent-memory

Git-native persistent memory for AI coding agents. Implements Google OKF v0.2 with sub-300µs in-memory BM25 search, embedded MCP server, and progressive disclosure. Slashes token bloat by 80% with zero external databases or dependencies. Built in pure Go.

547
tirth8205/
code-review-graph

Local-first code intelligence graph for MCP and CLI. Builds a persistent map of your codebase so AI coding tools read only what matters, with benchmarked context reductions on reviews and large-repo workflows.

31k
2akouwu/
reverify

Stop your AI from making things up — it proposes, deterministic tools decide, every claim checked against ground truth with evidence. Grounded facts and context survive resets. Reverse engineering is the proving ground. MCP server + CLI.

1.1k