The Problem
Long agent conversations consume context windows linearly — 174 messages can eat 95K tokens, forcing truncation and lost state. New sessions start with amnesia; yesterday's solved problems are gone. The repo addresses both by extracting a typed knowledge graph from conversation history and recalling relevant subgraphs on demand.
What This Does
graph-memory is a plugin for OpenClaw that converts conversation transcripts into a SQLite-backed property graph. It extracts triples (subject-predicate-object) from user/assistant turns via src/extractor/extract.ts, stores nodes and edges in src/store/db.ts, and compresses context by replacing raw history with graph nodes. The README claims 75% token reduction (95K → 24K over 7 rounds).
The recall path (src/recaller/recall.ts) runs two parallel searches: precise vector/FTS5 matching with graph traversal, and generalized community-summary matching. Top-ranked nodes pull original conversation snippets back into context. The graph runs community detection (src/graph/community.ts) and PageRank (src/graph/pagerank.ts) for ranking.
How It Is Wired
Execution starts at index.ts, which exposes the plugin entry points: register, ingest, assemble, compact, afterTurn, and execute. The main path is execute (index.ts:601), which reaches 42 functions and calls upsertNode, writing to SQLite via db.prepare("UPDATE gm_nodes SET content=?, description=?, va..."). Only 3 hops from entry to database write.
The hub is src/types.ts — 13 modules depend on it, so changes there have high blast radius. src/store/store.ts is the operational core: 42 functions, called from 6 files, owning uid, toNode, normalizeName, and findByName. The most-called functions are normalizeName (7 call sites) and findByName (5 sites) — changing either ripples widely. index.ts is the entry-point file (22 functions) but also calls into 11 modules and reads/writes the database directly.
The module graph has no circular dependencies (21 modules, 57 edges). The database is SQLite with FTS5; the model calls go through src/engine/embed.ts (raw fetch to any OpenAI-compatible endpoint) and src/engine/llm.ts for extraction.
How To Use It
git clone https://github.com/moses-y/graph-memory
cd graph-memory
npm install
npm test
Configuration lives in openclaw.plugin.json and index.ts. The embedding endpoint is set via cfg.baseURL (defaults to https://api.openai.com/v1). The plugin registers as plugins.slots.contextEngine in OpenClaw. The repo ships a Windows installer per the README, but no Dockerfile or CI pipeline exists.
Real-World Use
A 7-round session installing bilibili-mcp and logging in: without the plugin, tokens grow linearly to 95K; with it, they stabilize around 24K. Cross-session, the graph links "installed libgl1" to "ImportError: libGL.so.1" via a SOLVED_BY edge, so a new session recalls the fix without re-diagnosing.
Code Health & Issues
Static analysis found 8 issues (1 high, 7 medium). The high finding is duplicated code blocks: 53 repeated 6-line blocks across 7 files, including src/engine/embed.ts, src/engine/llm.ts, and src/extractor/extract.ts — extract shared helpers. Medium findings: high branching density (168 branch points over 516 lines in src/store/store.ts, src/engine/embed.ts, src/engine/llm.ts), the src/types.ts hub module, and index.ts at 718 lines (split by responsibility).
SDLC gaps: no CI pipeline, no lockfile (declared ranges reach vitest@1.4.0 with a published CVE), no dependency update bot. Tests exist (7 files) but nothing runs them automatically. Five of seven dependencies are behind current major versions.
The Bottom Line
The architecture is sound: a clean module graph, no cycles, and a clear separation between extraction, storage, and recall. The main risks are maintainability — the duplicated logic and oversized index.ts — and the missing lockfile, which makes builds non-reproducible. Suitable for teams running OpenClaw who need persistent memory; not yet production-hardened for broader use.