{
  "markdown": "<p align=\"center\">\n  <img src=\"docs/assets/logo.svg\" alt=\"Alaya logo\" width=\"180\">\n</p>\n\n# Alaya\n\n[![DOI](https://zenodo.org/badge/1167077192.svg)](https://zenodo.org/badge/latestdoi/1167077192)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n[![Rust](https://img.shields.io/badge/Rust-1.85%2B-orange.svg)](https://www.rust-lang.org/)\n[![crates.io](https://img.shields.io/crates/v/alaya.svg)](https://crates.io/crates/alaya)\n[![docs.rs](https://docs.rs/alaya/badge.svg)](https://docs.rs/alaya)\n[![npm](https://img.shields.io/npm/v/alaya-mcp.svg)](https://www.npmjs.com/package/alaya-mcp)\n[![PyPI](https://img.shields.io/pypi/v/alaya-memory.svg)](https://pypi.org/project/alaya-memory/)\n[![MCP](https://img.shields.io/badge/MCP-compatible-green.svg)](https://modelcontextprotocol.io/)\n[![alaya MCP server](https://glama.ai/mcp/servers/SecurityRonin/alaya/badges/score.svg)](https://glama.ai/mcp/servers/SecurityRonin/alaya)\n[![GitHub stars](https://img.shields.io/github/stars/SecurityRonin/alaya?style=social)](https://github.com/SecurityRonin/alaya)\n[![GitHub Sponsors](https://img.shields.io/badge/Sponsor-GitHub-ea4aaa?logo=github)](https://github.com/sponsors/h4x0r)\n[![CI](https://github.com/SecurityRonin/alaya/actions/workflows/ci.yml/badge.svg)](https://github.com/SecurityRonin/alaya/actions)\n\nThe only memory engine with neuroscience-grounded memory dynamics — Bjork dual-strength forgetting, retrieval-induced suppression, and Hebbian co-activation — in a zero-dependency embeddable Rust library.\n\n**Alaya** (Sanskrit: *alaya-vijnana*, \"storehouse consciousness\") is an\nembeddable Rust library. One SQLite file. No external services. Your agent\nstores conversations, retrieves what matters, and lets the rest fade. The\ngraph reshapes through use, like biological memory.\n\n```rust\nlet alaya = Alaya::open(\"memory.db\")?;\nalaya.episodes().store(&episode)?;           // store\nlet results = alaya.knowledge().query(&query)?; // retrieve\nalaya.lifecycle().consolidate(&provider)?;   // distill knowledge\nalaya.lifecycle().transform()?;              // dedup, LTD, discover categories\nalaya.lifecycle().forget()?;                 // decay what's stale\nlet cats = alaya.admin().categories(None)?;  // emergent ontology\nalaya.admin().purge(PurgeFilter::Session(\"s1\"))?; // cascade delete + tombstones\n```\n\n## The Problem\n\nMost AI agents treat memory as flat files. OpenClaw writes to `MEMORY.md`.\nClaudesidian writes to Obsidian. Hand-rolled systems write to JSON or\nMarkdown. It works at first.\n\nThen the files grow. Context windows fill. The agent dumps everything into\nthe prompt and hopes the LLM finds what matters.\n\n**The cost is measurable.** OpenClaw injects ~35,600 tokens of workspace\nfiles into every message, 93.5% of which is irrelevant\n([#9157](https://github.com/openclaw/openclaw/issues/9157)). Heavy users\nreport [$3,600/month](https://milvus.io/blog/why-ai-agents-like-openclaw-burn-through-tokens-and-how-to-cut-costs.md)\nin token costs. Community tools like\n[QMD](https://github.com/tobi/qmd) and\n[memsearch](https://github.com/zilliztech/memsearch) cut 70-96% of that\nwaste by replacing full-context injection with ranked retrieval\n([Levine, 2026](https://x.com/andrarchy/status/2015783856087929254)).\n\n**The structure problem compounds the cost.** MEMORY.md conflates decisions,\npreferences, and knowledge into one unstructured blob. Users independently\ninvent [`decision.md`](https://www.chatprd.ai/how-i-ai/jesse-genets-5-openclaw-agents-for-homeschooling-app-building-and-physical-inventories)\nfiles, `working-context.md` snapshots, and\n[12-layer memory architectures](https://github.com/coolmanns/openclaw-memory-architecture)\nto compensate. Monday you mention \"Alice manages the auth team.\" Wednesday\nyou ask \"who handles auth permissions?\" The agent retrieves both memories\nby text similarity but cannot connect them\n([Chawla, 2026](https://blog.dailydoseofds.com/p/openclaws-memory-is-broken-heres)).\n\n## How Alaya Solves It\n\n| Problem | File-based memory | Alaya |\n|---|---|---|\n| **Token waste** | Full-context injection (~35K tokens/message) | Ranked retrieval returns only top-k relevant memories |\n| **No structure** | Everything in one file (users invent `decision.md` workarounds) | Three typed stores: episodes, knowledge, preferences |\n| **No forgetting** | Files grow until you manually curate | Bjork dual-strength decay separates storage strength from retrieval strength; retrieval-induced forgetting (RIF) actively suppresses competing memories |\n| **No associations** | Flat files, no links between memories | Hebbian co-retrieval strengthening (LTP/LTD): memories retrieved together strengthen connections; spreading activation finds indirect associations |\n| **Brittle preferences** | Agent-authored summary, easily drifts | Implicit preferences emerge from accumulated impressions via vasana (perfuming), no LLM required; crystallize at threshold |\n| **LLM required** | Can't function without one | Graceful degradation at every level. No embeddings? BM25-only. No LLM? Episodes accumulate. Each capability independently optional |\n\n## Getting Started\n\n### MCP Server (recommended for agents)\n\nThe fastest way to add Alaya memory to any MCP-compatible agent (Claude Desktop,\nClaude Code, Cursor, Cline, etc.):\n\n#### Via npm (no Rust toolchain needed)\n\nAdd to your Claude Code config (`~/.claude/claude_code_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"alaya\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"alaya-mcp\"]\n    }\n  }\n}\n```\n\nOr for Claude Desktop / other MCP clients (with optional LLM auto-consolidation):\n\n```json\n{\n  \"mcpServers\": {\n    \"alaya\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"alaya-mcp\"],\n      \"env\": {\n        \"ALAYA_LLM_API_KEY\": \"sk-...\",\n        \"ALAYA_LLM_API_URL\": \"https://api.openai.com/v1/chat/completions\",\n        \"ALAYA_LLM_MODEL\": \"gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n#### From source (requires Rust 1.75+)\n\n```bash\ngit clone https://github.com/SecurityRonin/alaya.git\ncd alaya\ncargo build --release --features \"mcp llm\"\n```\n\nThen add to your MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"alaya\": {\n      \"command\": \"/path/to/alaya/target/release/alaya-mcp\"\n    }\n  }\n}\n```\n\nThe `ALAYA_LLM_*` env vars are optional — without them, the server works in\nprompt mode (reminds the agent to call `learn` after 10 episodes). With an API\nkey and the `llm` feature, it auto-consolidates instead.\n\nThat's it. Your agent now has 13 memory tools:\n\n| Tool | What it does |\n|------|-------------|\n| `remember` | Store a conversation message (auto-prompts consolidation after 10 episodes) |\n| `recall` | Search memory with hybrid retrieval (+ category boost) |\n| `learn` | Teach extracted knowledge directly — agent extracts facts and calls this |\n| `status` | Rich memory statistics: episodes, knowledge breakdown, categories, graph, embeddings |\n| `preferences` | Get learned user preferences |\n| `knowledge` | Get distilled semantic facts (+ category filter) |\n| `maintain` | Run memory cleanup (dedup, decay) |\n| `purge` | Delete memories by session, age, or all |\n| `categories` | List emergent categories with stability filter |\n| `neighbors` | Graph neighbors via spreading activation |\n| `node_category` | Which category a node belongs to |\n| `import_claude_mem` | Import observations from a claude-mem database |\n| `import_claude_code` | Import conversation history from Claude Code JSONL files |\n\nSee [docs/mcp-quickstart.md](docs/mcp-quickstart.md) for a full walkthrough\nwith sample interactions and recommended system prompt.\n\nData is stored in `~/.alaya/memory.db` (override with `ALAYA_DB` env var).\nSingle SQLite file, no external services.\n\n**Example interaction** — what your agent sees when using Alaya:\n\n```\nAgent: [calls remember(content=\"User prefers dark mode\", role=\"user\", session_id=\"s1\")]\nAlaya: Stored episode 1 in session 's1'\n\nAgent: [calls recall(query=\"user preferences\")]\nAlaya: Found 1 memories:\n  1. [user] (score: 0.847) User prefers dark mode\n\nAgent: [calls status()]\nAlaya: Memory Status:\n  Episodes: 1 (1 this session, 1 unconsolidated)\n  Knowledge: none\n  Categories: 0\n  Preferences: 0 crystallized, 0 impressions accumulating\n  Graph: 0 links\n  Embedding coverage: 0/1 nodes (0%)\n```\n\n**Environment variables:**\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `ALAYA_DB` | `~/.alaya/memory.db` | Path to SQLite database |\n| `ALAYA_LLM_API_KEY` | *(none)* | API key for auto-consolidation (enables `ExtractionProvider`). Requires `llm` feature. |\n| `ALAYA_LLM_API_URL` | `https://api.openai.com/v1/chat/completions` | OpenAI-compatible chat completions endpoint |\n| `ALAYA_LLM_MODEL` | `gpt-4o-mini` | Model name. Any small/fast model works (GPT-4o-mini, Haiku, Gemini Flash, etc.) |\n\n### Python Bindings\n\n```bash\npip install alaya-memory\n```\n\nSee [alaya-py/README.md](alaya-py/README.md) for the full Python API.\n\n### Rust Library\n\nFor embedding Alaya directly into a Rust application:\n\n```toml\n[dependencies]\nalaya = \"0.2.2\"\n```\n\n### Quick Start (Rust)\n\n```rust\nuse alaya::{Alaya, NewEpisode, Role, EpisodeContext, Query, NoOpProvider};\n\n// Open a persistent database (or use open_in_memory() for tests)\nlet alaya = Alaya::open(\"memory.db\")?;\n\n// Store a conversation episode\nalaya.episodes().store(&NewEpisode {\n    content: \"I've been learning Rust for about six months now\".into(),\n    role: Role::User,\n    session_id: \"session-1\".into(),\n    timestamp: 1740000000,\n    context: EpisodeContext::default(),\n    embedding: None, // pass Some(vec![...]) if you have embeddings\n})?;\n\n// Query with hybrid retrieval (BM25 + vector + graph + RRF)\nlet results = alaya.knowledge().query(&Query::simple(\"Rust experience\"))?;\nfor mem in &results {\n    println!(\"[{:.2}] {}\", mem.score, mem.content);\n}\n\n// Get crystallized preferences\nlet prefs = alaya.admin().preferences(Some(\"communication_style\"))?;\n\n// Run lifecycle (NoOpProvider works without an LLM)\nalaya.lifecycle().consolidate(&NoOpProvider)?;\nalaya.lifecycle().transform()?;\nalaya.lifecycle().forget()?;\n```\n\n### Run the Demo\n\nThe demo walks through all eleven capabilities with annotated output and no\nexternal dependencies:\n\n```bash\ngit clone https://github.com/SecurityRonin/alaya.git\ncd alaya\ncargo run --example demo\n```\n\n## Architecture\n\nAlaya is a library, not a framework. Your agent owns the conversation loop,\nthe LLM, and the embedding model. Alaya owns memory.\n\n```\nYour Agent                          Alaya\n─────────                           ─────\n\nVia MCP (stdio):                    alaya-mcp binary\n  remember(content, role, session)    ──▶ episodic store + graph links\n  recall(query, boost_category?)      ──▶ BM25 + vector + graph → RRF → rerank\n  learn(facts, session_id?)           ──▶ agent-driven knowledge extraction\n  status()                            ──▶ rich stats (episodes, knowledge, graph, embeddings)\n  preferences(domain?)                ──▶ crystallized behavioral patterns\n  knowledge(type?, category?)         ──▶ consolidated semantic nodes\n  maintain()                          ──▶ dedup + decay\n  purge(scope)                        ──▶ selective or full deletion\n  categories(min_stability?)          ──▶ emergent ontology with hierarchy\n  neighbors(node, depth?)             ──▶ graph spreading activation\n  node_category(node_id)              ──▶ category assignment lookup\n  import_claude_mem(path?)            ──▶ import from claude-mem.db\n  import_claude_code(path)            ──▶ import from Claude Code JSONL\n\nVia Rust library:                   Alaya coordinator\n  alaya.episodes().store(ep)           ──▶ episodic store + graph links\n  alaya.knowledge().query(q)           ──▶ BM25 + vector + graph → RRF → rerank\n  alaya.admin().preferences(domain?)   ──▶ crystallized behavioral patterns\n  alaya.knowledge().filter(f?)         ──▶ consolidated semantic nodes\n  alaya.admin().categories(min?)       ──▶ emergent ontology with hierarchy\n  alaya.admin().subcategories(id)      ──▶ children of a parent category\n  alaya.graph().neighbors(node, d)     ──▶ graph spreading activation\n  alaya.admin().node_category(id)      ──▶ category assignment lookup\n  alaya.set_embedding_provider(p)      ──▶ auto-embed in store + query\n  alaya.set_extraction_provider(p)     ──▶ enable auto-consolidation\n  alaya.lifecycle().consolidate(p)     ──▶ episodes → semantic knowledge\n  alaya.knowledge().learn(nodes)       ──▶ provider-less knowledge injection\n  alaya.lifecycle().auto_consolidate() ──▶ extract + learn (needs ExtractionProvider)\n  alaya.lifecycle().perfume(i, p)      ──▶ impressions → preferences\n  alaya.lifecycle().transform()        ──▶ dedup, LTD, prune, split categories\n  alaya.lifecycle().forget()           ──▶ Bjork strength decay + archival\n  alaya.admin().purge(scope)           ──▶ cascade deletion + tombstones\n```\n\n### Three Stores\n\n| Store | Analog | Purpose |\n|-------|--------|---------|\n| **Episodic** | Hippocampus | Raw conversation events with full context |\n| **Semantic** | Neocortex | Distilled knowledge extracted through consolidation |\n| **Implicit** | Alaya-vijnana | Preferences and habits that emerge through perfuming |\n\n### Retrieval Pipeline\n\n```mermaid\nflowchart LR\n    Q[Query] --> BM25[BM25 / FTS5]\n    Q --> VEC[Vector / Cosine]\n    Q --> GR[Graph Neighbors]\n\n    BM25 --> RRF[Reciprocal Rank Fusion]\n    VEC --> RRF\n    GR --> RRF\n\n    RRF --> RR[Context-Weighted Reranking]\n    RR --> SA[Spreading Activation + Enrichment]\n    SA --> RIF[Retrieval-Induced Forgetting]\n    RIF --> OUT[Top 3-5 Results<br/>Episodes + Semantic + Preferences]\n```\n\n### Lifecycle Processes\n\n| Process | Inspiration | What it does |\n|---------|-------------|--------------|\n| **Consolidation** | CLS theory (McClelland et al.) | Distills episodes into semantic knowledge |\n| **Perfuming** | Vasana (Yogacara Buddhist psychology) | Accumulates impressions, crystallizes preferences |\n| **Transformation** | Asraya-paravrtti | Deduplicates, LTD link decay, prunes, discovers categories |\n| **Forgetting** | Bjork & Bjork (1992) | Decays retrieval strength, archives weak nodes |\n| **RIF** | Anderson et al. (1994) | Retrieval-induced forgetting suppresses competing memories |\n| **Emergent Ontology** | Vikalpa (conceptual construction) | Hierarchical categories emerge from clustering; auto-split when too broad |\n\n## Integration Guide\n\n### Implementing ConsolidationProvider\n\nThe `ConsolidationProvider` trait connects Alaya to your LLM for knowledge\nextraction:\n\n```rust\nuse alaya::*;\n\nstruct MyProvider { /* your LLM client */ }\n\nimpl ConsolidationProvider for MyProvider {\n    fn extract_knowledge(&self, episodes: &[Episode]) -> Result<Vec<NewSemanticNode>> {\n        // Ask your LLM: \"What facts/relationships can you extract?\"\n        todo!()\n    }\n\n    fn extract_impressions(&self, interaction: &Interaction) -> Result<Vec<NewImpression>> {\n        // Ask your LLM: \"What behavioral signals does this contain?\"\n        todo!()\n    }\n\n    fn detect_contradiction(&self, a: &SemanticNode, b: &SemanticNode) -> Result<bool> {\n        // Ask your LLM: \"Do these two facts contradict each other?\"\n        todo!()\n    }\n}\n```\n\nUse `NoOpProvider` without an LLM. Episodes accumulate and BM25 retrieval\nworks without consolidation.\n\n### Implementing ExtractionProvider (auto-consolidation)\n\nThe `ExtractionProvider` trait enables automatic knowledge extraction without\nmanual `consolidate()` calls. When configured, the MCP server auto-consolidates\nafter 10 unconsolidated episodes:\n\n```rust\nuse alaya::*;\n\nstruct MyExtractor { /* your LLM client */ }\n\nimpl ExtractionProvider for MyExtractor {\n    fn extract(&self, episodes: &[Episode]) -> Result<Vec<NewSemanticNode>> {\n        // Ask your LLM: \"Extract facts from these conversations\"\n        todo!()\n    }\n}\n\nlet mut alaya = Alaya::open(\"memory.db\")?;\nalaya.set_extraction_provider(Box::new(MyExtractor { /* ... */ }));\n\n// Now auto_consolidate() works without a ConsolidationProvider\nlet report = alaya.lifecycle().auto_consolidate()?;\n```\n\nThe `llm` feature flag provides a ready-to-use `LlmExtractionProvider` that\ncalls any OpenAI-compatible API:\n\n```rust\nuse alaya::LlmExtractionProvider;\n\nlet provider = LlmExtractionProvider::builder()\n    .api_key(\"sk-...\")\n    .model(\"gpt-4o-mini\")      // default; any small model works\n    .build()?;\n```\n\n### Lifecycle Scheduling\n\n| Method | When to call | What it does |\n|--------|-------------|--------------|\n| `consolidate()` | After accumulating 10+ episodes | Extracts semantic knowledge from episodes |\n| `perfume()` | On every user interaction | Extracts behavioral impressions, crystallizes preferences |\n| `transform()` | Daily or weekly | Deduplicates, LTD link decay, prunes weak links, discovers categories |\n| `forget()` | Daily or weekly | Decays retrieval strength, archives truly forgotten nodes |\n| `purge()` | On user request | Cascade deletes by session/age/all with tombstone tracking |\n\n## API Reference\n\n```rust\nimpl Alaya {\n    // Open / create\n    pub fn open(path: impl AsRef<Path>) -> Result<Self>;\n    pub fn open_in_memory() -> Result<Self>;\n\n    // Providers (on coordinator)\n    pub fn set_embedding_provider(&mut self, provider: Box<dyn EmbeddingProvider>);\n    pub fn set_extraction_provider(&mut self, provider: Box<dyn ExtractionProvider>);\n\n    // Sub-manager accessors\n    pub fn episodes(&self) -> Episodes<'_>;\n    pub fn knowledge(&self) -> Knowledge<'_>;\n    pub fn lifecycle(&self) -> Lifecycle<'_>;\n    pub fn graph(&self) -> Graph<'_>;\n    pub fn admin(&self) -> Admin<'_>;\n}\n\nimpl Episodes<'_> {\n    pub fn store(&self, episode: &NewEpisode) -> Result<EpisodeId>;\n    pub fn by_session(&self, session_id: &str) -> Result<Vec<Episode>>;\n    pub fn unconsolidated(&self, limit: u32) -> Result<Vec<Episode>>;\n}\n\nimpl Knowledge<'_> {\n    pub fn query(&self, q: &Query) -> Result<Vec<ScoredMemory>>;\n    pub fn learn(&self, nodes: Vec<NewSemanticNode>) -> Result<ConsolidationReport>;\n    pub fn filter(&self, filter: Option<KnowledgeFilter>) -> Result<Vec<SemanticNode>>;\n}\n\nimpl Lifecycle<'_> {\n    pub fn consolidate(&self, provider: &dyn ConsolidationProvider) -> Result<ConsolidationReport>;\n    pub fn auto_consolidate(&self) -> Result<ConsolidationReport>;\n    pub fn transform(&self) -> Result<TransformationReport>;\n    pub fn forget(&self) -> Result<ForgettingReport>;\n    pub fn perfume(&self, interaction: &Interaction, provider: &dyn ConsolidationProvider) -> Result<PerfumingReport>;\n    pub fn dream(&self, provider: &dyn ConsolidationProvider, interaction: Option<&Interaction>) -> Result<DreamReport>;\n}\n\nimpl Admin<'_> {\n    pub fn status(&self) -> Result<MemoryStatus>;\n    pub fn purge(&self, filter: PurgeFilter) -> Result<PurgeReport>;\n    pub fn preferences(&self, domain: Option<&str>) -> Result<Vec<Preference>>;\n    pub fn categories(&self, min_stability: Option<f32>) -> Result<Vec<Category>>;\n    pub fn subcategories(&self, parent_id: CategoryId) -> Result<Vec<Category>>;\n    pub fn node_category(&self, node_id: NodeId) -> Result<Option<Category>>;\n}\n```\n\n## Design Principles\n\n1. **Memory is a process, not a database.** Every retrieval changes what is\n   remembered. The graph reshapes through use.\n\n2. **Forgetting is a feature.** Bjork dual-strength decay separates storage\n   strength from retrieval strength. Retrieval-induced forgetting (RIF)\n   actively suppresses competing memories. Both improve retrieval quality\n   over time.\n\n3. **Preferences emerge, they are not declared.** Behavioral patterns\n   crystallize from accumulated impressions via vasana (perfuming), no LLM\n   required.\n\n4. **The agent owns identity.** Alaya stores seeds. The agent decides which\n   seeds matter and how to present them.\n\n5. **Graceful degradation.** No embeddings? BM25-only. No LLM? Episodes\n   accumulate. Every feature works independently.\n\n## Research Foundations\n\nArchitecture grounded in neuroscience, Buddhist psychology, and information\nretrieval. For detailed mappings, see\n[docs/theoretical-foundations.md](docs/theoretical-foundations.md).\n\n**Neuroscience:** Hebbian LTP/LTD (Hebb 1949, Bliss & Lomo 1973),\nComplementary Learning Systems (McClelland et al. 1995), spreading\nactivation (Collins & Loftus 1975), encoding specificity (Tulving & Thomson\n1973), dual-strength forgetting (Bjork & Bjork 1992), retrieval-induced\nforgetting (Anderson et al. 1994), working memory limits (Cowan 2001).\n\n**Yogacara Buddhist Psychology:** Alaya-vijnana (storehouse consciousness),\nbija (seeds), vasana (perfuming), asraya-paravrtti (transformation),\nvijnaptimatrata (perspective-relative memory).\n\n**Information Retrieval:** Reciprocal Rank Fusion (Cormack et al. 2009),\nBM25 via FTS5, cosine similarity vector search.\n\n## Comparison with Alternatives\n\n```mermaid\ngraph LR\n    AGENT[\"AI Agent\"]\n\n    subgraph SIMPLE[\"Simple\"]\n        FILE[\"File-Based<br/><i>MEMORY.md<br/>OpenClaw</i>\"]\n    end\n\n    subgraph INTEGRATED[\"Integrated\"]\n        FW[\"Framework Memory<br/><i>LangChain · CrewAI<br/>Letta</i>\"]\n        CODE[\"Coding Agent<br/><i>Beads · Engram<br/>via MCP</i>\"]\n    end\n\n    subgraph ENGINES[\"Memory Engines\"]\n        DED[\"Dedicated Systems<br/><i><b>Alaya</b> · Vestige<br/>mem0 · Zep</i>\"]\n    end\n\n    subgraph INFRA[\"Infrastructure\"]\n        VDB[\"Vector DBs<br/><i>Pinecone · Chroma<br/>Weaviate</i>\"]\n    end\n\n    RESEARCH[\"Research<br/><i>Generative Agents<br/>SYNAPSE · HippoRAG</i>\"]\n\n    AGENT <--> FILE\n    AGENT <--> FW\n    AGENT <--> CODE\n    AGENT <--> DED\n    DED -.->|storage| VDB\n    FW -.->|storage| VDB\n    RESEARCH -.->|ideas| DED\n    RESEARCH -.->|ideas| FW\n```\n\nAlaya is a **dedicated memory engine** with neuroscience-grounded memory\ndynamics. What differentiates it from every other system: Bjork dual-strength\nforgetting (separating storage from retrieval strength), retrieval-induced\nforgetting (retrieving A suppresses competing B and C), Hebbian co-retrieval\nstrengthening (LTP/LTD), and implicit preference emergence without an LLM --\nall in a single embeddable Rust + SQLite library. Closest peers: **Vestige**\n(Rust, FSRS-6, spreading activation) and **SYNAPSE** (unified\nepisodic-semantic graph, lateral inhibition).\n\n### Why Alaya over...\n\n| Alternative | What it does well | What Alaya adds |\n|---|---|---|\n| **MEMORY.md** | Zero setup | Ranked retrieval (not full-context injection), typed stores, Bjork dual-strength decay |\n| **mem0** | Managed cloud memory with auto-extraction | Local-only (single SQLite file), no API keys, Hebbian graph dynamics, RIF suppression |\n| **Zep** | Production-ready with cloud/self-hosted options | No external services, Hebbian co-retrieval graph, implicit preference emergence without LLM |\n| **Vestige** | Rust, FSRS-6 spaced repetition | Bjork dual-strength (not FSRS), RIF, Hebbian LTP/LTD, vasana preference crystallization |\n| **LangChain Memory** | Framework-integrated, many backends | Framework-agnostic, seven lifecycle operations, graceful degradation to BM25-only |\n\n- [Full comparison: 90+ systems](docs/related-work.md), grounded in the CoALA taxonomy (Sumers et al., 2024)\n- [Interactive landscape](https://SecurityRonin.github.io/alaya/docs/memory-landscape.html) (D3.js force-directed graph)\n- [Theoretical foundations](docs/theoretical-foundations.md) (neuroscience and Buddhist psychology)\n- [The MEMORY.md problem](docs/related-work.md#the-memorymd-problem-why-file-based-memory-breaks-at-scale) (community workarounds and how Alaya addresses each)\n\n## What's In v0.4\n\n- **Three-store architecture** (episodic/semantic/implicit) + Hebbian graph overlay\n- **7 lifecycle operations:** consolidate, transform, forget, perfume, emergent ontology, RIF, purge\n- **Modular RAG retrieval:** BM25 + vector + graph + RRF fusion + semantic/preference enrichment\n- **Bjork dual-strength forgetting** with retrieval-induced suppression (RIF)\n- **LTD (Long-Term Depression):** Hebbian link decay weakens unused associations each transform cycle\n- **Enriched retrieval:** query results include semantic knowledge and preferences alongside episodes\n- **Tombstone tracking:** cascade deletion records audit trail for every purged node\n- **Zero-dependency Rust library** with SQLite WAL + FTS5\n- **Category hierarchy** with `parent_id` — categories form tree structures; auto-split when too broad\n- **Cross-domain bridging** via `MemberOf` links — spreading activation traverses category boundaries\n- **EmbeddingProvider trait** — `embed()` + `embed_batch()` wired into `store_episode()` and `query()`\n- **ExtractionProvider trait** — `extract()` enables auto-consolidation; `LlmExtractionProvider` (behind `llm` feature flag) calls any OpenAI-compatible API\n- **13 MCP tools** — `remember`, `recall`, `learn`, `status`, `preferences`, `knowledge`, `maintain`, `purge`, `categories`, `neighbors`, `node_category`, `import_claude_mem`, `import_claude_code`\n- **Auto-lifecycle** — auto-maintenance every 25 episodes; auto-consolidation (or prompt) after 10 unconsolidated\n- **442 tests** across unit, integration, property-based (proptest), and doc tests\n\n## Benchmark Evaluation\n\nWe evaluate two canonical baselines — full-context injection and naive\nvector RAG — on three benchmarks: LoCoMo (1,540 questions), LongMemEval\n(500 questions), and MemoryAgentBench (734 questions across 4\ncompetencies). Generator: Gemini-2.0-Flash-001; Judge: GPT-4o-mini. Full\nmethodology and statistical analysis:\n[docs/benchmark-evaluation.md](docs/benchmark-evaluation.md).\n\n![Benchmark Results](https://raw.githubusercontent.com/SecurityRonin/alaya/main/docs/assets/benchmark-chart.svg)\n\n**Key findings:**\n- **Retrieval crossover:** Full-context dominates on shorter conversations\n  (LoCoMo, 16–26K tokens) but naive RAG wins on longer histories\n  (LongMemEval, ~115K tokens). Both differences statistically significant\n  (McNemar's test, p < 0.001).\n- **Test-time learning gap:** The largest gap across all benchmarks — 86%\n  vs 44% (+42pp) — RAG destroys the sequential structure needed for\n  in-context learning.\n- **Conflict resolution is unsolved:** Both baselines score ~50% on\n  contradiction handling, confirming that neither full-context nor\n  retrieval provides a mechanism for resolving conflicting information.\n- Neither baseline addresses what lifecycle management is designed for.\n\n## Development\n\n```bash\n# Run all library tests\ncargo test\n\n# Run MCP integration tests\ncargo test --features mcp\n\n# Run LLM extraction tests\ncargo test --features llm\n\n# Run all tests\ncargo test --features \"mcp llm\"\n\n# Build the MCP server\ncargo build --release --features mcp\n\n# Build with auto-consolidation support\ncargo build --release --features \"mcp llm\"\n\n# Run the demo (no external dependencies)\ncargo run --example demo\n```\n\n## License\n\nMIT",
  "bytes": 26717,
  "sha": "84305551576650ac944822a003969f5b29e5c344e2a6440302917a4ea5ca3b2a",
  "repo_slug": "securityronin/alaya",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_securityronin_alaya_mcp_cb6a6188/readme"
}