raven-memory

Adaptive Memory Field for Agentic Systems

Track 1: MemoryAgent · Qwen Cloud Hackathon

Live demo & architecture: https://raven-memory.vercel.app Repo: https://github.com/annatchijova/raven-memory

"The agent doesn't find memories — it resonates with them."


Inspiration

Almost every "memory" layer shipping today collapses to one line:

query → embed → top-k cosine search → return k documents

That's a database lookup wearing a memory costume. It has no dynamics. It can't tell a validated fact from an unconfirmed rumor. It never notices that two of the documents it just returned contradict each other. It never forgets, never reinforces, never strengthens an association between two ideas that keep showing up together. Every recall is exactly as shallow as the first one.

We wanted to know: what does memory look like if you take the neuroscience seriously — Hebbian reinforcement, contradiction inhibition, sleep consolidation — but hold it to the evidentiary discipline of a forensic audit trail, not a demo-day hand-wave?

What it does

raven-memory replaces the lookup with a field. Every stored embedding becomes a cell in a KDTree-indexed neighborhood (Voronoi-like, we're precise about that in the docs). Recall doesn't stop at the nearest cell — it BFS-expands through the neighborhood, and every hit is scored dynamically:

score = (cosine_sim × state_boost × exp(-λ · hop))
      + resonant_boost
      + synaptic_weight × 0.3
      + recency_bonus (24h half-life)

Memories live in one of three ternary states — REINFORCED (×1.5), NEUTRAL (×1.0), FORGOTTEN (×0.0) — and when two memories contradict each other, the field doesn't average them into mush. It collapses around the validated truth:

Before reinforcement:
  VIGIA is deterministic   [NEUTRAL]  score=0.447
  VIGIA uses ML            [NEUTRAL]  score=0.441   ← nearly tied

User reinforces the first claim ↓

After reinforcement:
  VIGIA is deterministic   [REINFORCED]  score=1.493  ← dominates
  VIGIA uses ML            [NEUTRAL]     ← silenced by the INHIBITORY link

The INHIBITORY link was already there — created automatically the moment the conflicting claim was stored. Reinforcement just switches it on.

Beyond recall, the field:

  • Reinforces itself — co-activated cells strengthen their link (STDP / Hebbian LTP); links that never fire together decay (LTD).
  • Detects impostors — a stylometric fingerprint (function-word frequencies, sentence length, punctuation profile) flags text that doesn't match the claimed author's historical voice and auto-demotes it to FORGOTTEN. Language-aware, so a bilingual author isn't flagged for switching from English to Spanish.
  • Sleeps — an offline consolidator clusters near-duplicate episodic memories (agglomerative cosine clustering) into a single semantic node with a recall-frequency-weighted centroid, atomically, inside one BEGIN IMMEDIATE transaction.
  • Proves itself — every recall writes an immutable, SHA-256-chained audit entry over a canonical payload (query, activated cells, each memory's content hash, the previous entry's hash). verify_audit_chain() recomputes the whole chain from the database alone — no side channel to trust. Two classic audit forgeries are closed by construction: editing stored content without invalidating the chain, and re-hashing with a different timestamp than the one actually stored.
  • Reports its own health — the Memory Stability Score, MSS = 1.5R / (1.5R + N), tells you whether the agent's worldview is mostly validated truth (→1.0) or mostly unconfirmed noise (→0.0).
  • Speaks MCP — the full engine (store, recall, reinforce, forget, create_link, stats, audit_trail, export_graph) is exposed as an MCP server, so Claude Code or any MCP-capable agent can use raven-memory as its memory tool directly.

It runs fully offline with deterministic SHA-256-seeded fallback embeddings, and lights up with Qwen Cloud (text-embedding-v3 for embeddings, qwen-max for chat) the moment a DASHSCOPE_API_KEY is set — deployed live on Alibaba Cloud ECS via Docker.

How we built it

  • Core engine (raven/memory_engine.py): Python, NumPy/SciPy KDTree, SQLite in WAL mode with indices on cell_id, layer, author_id, state, scikit-learn for agglomerative clustering.
  • Spectral field (raven/spectral.py): an optional SVD-based epistemic layer — resonance and coherence scores computed after the recall ranking is already fixed, so a downstream agent can judge structural consistency without the field ever reordering a result. It declares its own determinism honestly: bit-for-bit stable within a process, best-effort across processes, and its cross-process self-test reports a distinct WARN rather than a false PASS.
  • AI & Cloud: Qwen Cloud (text-embedding-v3, qwen-max) via the Alibaba DashScope international endpoint, with Claude (claude-sonnet-4-6) as an alternate chat backend — the orchestrator is provider-agnostic by design. Docker + Alibaba Cloud ECS (Singapore) for the live deployment. Embeddings fall back three-tier: local all-MiniLM-L6-v2 → Qwen Cloud → deterministic SHA-256 dummy, with every degraded response stamped degraded: true — never a silent wrong answer.
  • Interfaces: FastAPI + WebSocket REST API (Swagger at /docs), a 4-tab Gradio demo with live MSS and collapse visualization, an MCP server over stdio, and a static site (EN/ZH) on Vercel.
  • Tests: 20 integration tests covering the P0 behaviors, plus a multi-phase adversarial stress test.

Challenges we ran into

  • Making "collapse around truth" real, not scripted. The INHIBITORY link has to be created automatically when a contradicting claim is stored, and reinforcement has to actually flip the field state — not just tag a row. Getting BFS expansion, hop decay, and state boosts to interact so that a 4-thousandths score gap becomes a 3x dominance after one reinforcement took several passes at the scoring formula.
  • Consolidation that can't half-happen. Sleep consolidation touches three things at once — insert the merged node, delete the sources, delete orphaned links. A crash between any two of those steps would leave duplicated content or dangling references. It now runs inside a single BEGIN IMMEDIATE transaction with rollback, and it verifies the hash chain tail before appending, so it can never silently launder a break that already existed.
  • Honest determinism, not claimed determinism. The spectral module is reproducible bit-for-bit within one process but only best-effort across different BLAS builds (OpenBLAS vs MKL vs Accelerate) on degenerate eigenspaces. Rather than paper over that, we made the module say so in its own schema (determinism_level: best_effort) and gave its self-test a real third state — PASS / WARN / FAIL — instead of folding a failed child check into a green light.
  • A 55-finding internal security pass. Concurrent readers/writers against SQLite without WAL mode produced transient lock failures; unbounded graph export and unchunked IN (...) queries would have blown past SQLite's 999-parameter limit at scale; and conversation history fed to the LLM needed sanitizing against prompt injection and a hard context-size cap so retrieved memories could never evict the actual query from the model's window. All 55 findings were resolved (see docs/FIXES_v1.1.md).
  • sklearn API driftmetric="precomputed" plus explicit cosine_distances() instead of the deprecated affinity path.

Accomplishments that we're proud of

  • A memory system whose signature demo — two contradictory claims resolving into a dominant truth and a silenced falsehood — is not a canned animation; it's the actual scoring math responding to a single reinforce call.
  • An audit chain that doesn't just log — it's built to survive someone actively trying to falsify it, and we can point to exactly which two forgery techniques it closes and why.
  • Treating "best-effort" as a first-class, honestly-labeled state instead of rounding it up to "works." The spectral field says what it guarantees and what it doesn't, in its own output.
  • Running the same field logic identically offline (deterministic dummy embeddings) and live on Qwen Cloud against Alibaba Cloud ECS — provider swap only changes vector quality, never the field's behavior.

What we learned

  • Reproducibility and "it works on my machine" are different claims, and a system that seals its own honesty about which one it can make (per module, in the schema) is more trustworthy than one that claims determinism everywhere and hopes nobody checks.
  • A contradiction-aware memory needs the inhibitory structure to exist before the contradiction is ever queried — building the link at store time, not at recall time, is what makes the collapse instantaneous instead of computed-on-the-fly.
  • Security review pays for itself fastest in exactly the code nobody demos: the consolidator, the graph export, the conversation sanitizer.

What's next

  • Cap STDP synaptic growth with a decay/normalization term so repeated co-activation can't climb without bound (currently documented as a known limitation).
  • Expose a /consolidate endpoint so sleep consolidation can run without restarting the engine process.
  • Stratified spectral fields per memory layer, once corpus size justifies the added complexity over a single global SVD.

Built with

Qwen Cloud (text-embedding-v3, qwen-max) via Alibaba Cloud DashScope · Python · NumPy/SciPy (KDTree) · scikit-learn (agglomerative clustering) · SQLite (WAL mode) · FastAPI + WebSocket · Gradio · Model Context Protocol (MCP server) · Docker · Alibaba Cloud ECS · Vercel (static site, EN/ZH)

Authors

Anna Tchijova + Claude + Qwen License: Apache 2.0

Built With

Share this project:

Updates