Alaya
The 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.
Alaya (Sanskrit: alaya-vijnana, "storehouse consciousness") is an embeddable Rust library. One SQLite file. No external services. Your agent stores conversations, retrieves what matters, and lets the rest fade. The graph reshapes through use, like biological memory.
let alaya = Alaya::open("memory.db")?;
alaya.episodes().store(&episode)?; // store
let results = alaya.knowledge().query(&query)?; // retrieve
alaya.lifecycle().consolidate(&provider)?; // distill knowledge
alaya.lifecycle().transform()?; // dedup, LTD, discover categories
alaya.lifecycle().forget()?; // decay what's stale
let cats = alaya.admin().categories(None)?; // emergent ontology
alaya.admin().purge(PurgeFilter::Session("s1"))?; // cascade delete + tombstonesThe Problem
Most AI agents treat memory as flat files. OpenClaw writes to MEMORY.md.
Claudesidian writes to Obsidian. Hand-rolled systems write to JSON or
Markdown. It works at first.
Then the files grow. Context windows fill. The agent dumps everything into the prompt and hopes the LLM finds what matters.
The cost is measurable. OpenClaw injects ~35,600 tokens of workspace files into every message, 93.5% of which is irrelevant (#9157). Heavy users report $3,600/month in token costs. Community tools like QMD and memsearch cut 70-96% of that waste by replacing full-context injection with ranked retrieval (Levine, 2026).
The structure problem compounds the cost. MEMORY.md conflates decisions,
preferences, and knowledge into one unstructured blob. Users independently
invent decision.md
files, working-context.md snapshots, and
12-layer memory architectures
to compensate. Monday you mention "Alice manages the auth team." Wednesday
you ask "who handles auth permissions?" The agent retrieves both memories
by text similarity but cannot connect them
(Chawla, 2026).
How Alaya Solves It
| Problem | File-based memory | Alaya |
|---|---|---|
| Token waste | Full-context injection (~35K tokens/message) | Ranked retrieval returns only top-k relevant memories |
| No structure | Everything in one file (users invent decision.md workarounds) | Three typed stores: episodes, knowledge, preferences |
| 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 |
| No associations | Flat files, no links between memories | Hebbian co-retrieval strengthening (LTP/LTD): memories retrieved together strengthen connections; spreading activation finds indirect associations |
| Brittle preferences | Agent-authored summary, easily drifts | Implicit preferences emerge from accumulated impressions via vasana (perfuming), no LLM required; crystallize at threshold |
| LLM required | Can't function without one | Graceful degradation at every level. No embeddings? BM25-only. No LLM? Episodes accumulate. Each capability independently optional |
Getting Started
MCP Server (recommended for agents)
The fastest way to add Alaya memory to any MCP-compatible agent (Claude Desktop, Claude Code, Cursor, Cline, etc.):
Via npm (no Rust toolchain needed)
Add to your Claude Code config (~/.claude/claude_code_config.json):
{
"mcpServers": {
"alaya": {
"command": "npx",
"args": ["-y", "alaya-mcp"]
}
}
}Or for Claude Desktop / other MCP clients (with optional LLM auto-consolidation):
{
"mcpServers": {
"alaya": {
"command": "npx",
"args": ["-y", "alaya-mcp"],
"env": {
"ALAYA_LLM_API_KEY": "sk-...",
"ALAYA_LLM_API_URL": "https://api.openai.com/v1/chat/completions",
"ALAYA_LLM_MODEL": "gpt-4o-mini"
}
}
}
}From source (requires Rust 1.75+)
git clone https://github.com/SecurityRonin/alaya.git
cd alaya
cargo build --release --features "mcp llm"Then add to your MCP config:
{
"mcpServers": {
"alaya": {
"command": "/path/to/alaya/target/release/alaya-mcp"
}
}
}The ALAYA_LLM_* env vars are optional — without them, the server works in
prompt mode (reminds the agent to call learn after 10 episodes). With an API
key and the llm feature, it auto-consolidates instead.
That's it. Your agent now has 13 memory tools:
| Tool | What it does |
|---|---|
remember | Store a conversation message (auto-prompts consolidation after 10 episodes) |
recall | Search memory with hybrid retrieval (+ category boost) |
learn | Teach extracted knowledge directly — agent extracts facts and calls this |
status | Rich memory statistics: episodes, knowledge breakdown, categories, graph, embeddings |
preferences | Get learned user preferences |
knowledge | Get distilled semantic facts (+ category filter) |
maintain | Run memory cleanup (dedup, decay) |
purge | Delete memories by session, age, or all |
categories | List emergent categories with stability filter |
neighbors | Graph neighbors via spreading activation |
node_category | Which category a node belongs to |
import_claude_mem | Import observations from a claude-mem database |
import_claude_code | Import conversation history from Claude Code JSONL files |
See docs/mcp-quickstart.md for a full walkthrough with sample interactions and recommended system prompt.
Data is stored in ~/.alaya/memory.db (override with ALAYA_DB env var).
Single SQLite file, no external services.
Example interaction — what your agent sees when using Alaya:
Agent: [calls remember(content="User prefers dark mode", role="user", session_id="s1")]
Alaya: Stored episode 1 in session 's1'
Agent: [calls recall(query="user preferences")]
Alaya: Found 1 memories:
1. [user] (score: 0.847) User prefers dark mode
Agent: [calls status()]
Alaya: Memory Status:
Episodes: 1 (1 this session, 1 unconsolidated)
Knowledge: none
Categories: 0
Preferences: 0 crystallized, 0 impressions accumulating
Graph: 0 links
Embedding coverage: 0/1 nodes (0%)Environment variables:
| Variable | Default | Description |
|---|---|---|
ALAYA_DB | ~/.alaya/memory.db | Path to SQLite database |
ALAYA_LLM_API_KEY | (none) | API key for auto-consolidation (enables ExtractionProvider). Requires llm feature. |
ALAYA_LLM_API_URL | https://api.openai.com/v1/chat/completions | OpenAI-compatible chat completions endpoint |
ALAYA_LLM_MODEL | gpt-4o-mini | Model name. Any small/fast model works (GPT-4o-mini, Haiku, Gemini Flash, etc.) |
Python Bindings
pip install alaya-memorySee alaya-py/README.md for the full Python API.
Rust Library
For embedding Alaya directly into a Rust application:
[dependencies]
alaya = "0.2.2"Quick Start (Rust)
use alaya::{Alaya, NewEpisode, Role, EpisodeContext, Query, NoOpProvider};
// Open a persistent database (or use open_in_memory() for tests)
let alaya = Alaya::open("memory.db")?;
// Store a conversation episode
alaya.episodes().store(&NewEpisode {
content: "I've been learning Rust for about six months now".into(),
role: Role::User,
session_id: "session-1".into(),
timestamp: 1740000000,
context: EpisodeContext::default(),
embedding: None, // pass Some(vec![...]) if you have embeddings
})?;
// Query with hybrid retrieval (BM25 + vector + graph + RRF)
let results = alaya.knowledge().query(&Query::simple("Rust experience"))?;
for mem in &results {
println!("[{:.2}] {}", mem.score, mem.content);
}
// Get crystallized preferences
let prefs = alaya.admin().preferences(Some("communication_style"))?;
// Run lifecycle (NoOpProvider works without an LLM)
alaya.lifecycle().consolidate(&NoOpProvider)?;
alaya.lifecycle().transform()?;
alaya.lifecycle().forget()?;Run the Demo
The demo walks through all eleven capabilities with annotated output and no external dependencies:
git clone https://github.com/SecurityRonin/alaya.git
cd alaya
cargo run --example demoArchitecture
Alaya is a library, not a framework. Your agent owns the conversation loop, the LLM, and the embedding model. Alaya owns memory.
Your Agent Alaya
───────── ─────
Via MCP (stdio): alaya-mcp binary
remember(content, role, session) ──▶ episodic store + graph links
recall(query, boost_category?) ──▶ BM25 + vector + graph → RRF → rerank
learn(facts, session_id?) ──▶ agent-driven knowledge extraction
status() ──▶ rich stats (episodes, knowledge, graph, embeddings)
preferences(domain?) ──▶ crystallized behavioral patterns
knowledge(type?, category?) ──▶ consolidated semantic nodes
maintain() ──▶ dedup + decay
purge(scope) ──▶ selective or full deletion
categories(min_stability?) ──▶ emergent ontology with hierarchy
neighbors(node, depth?) ──▶ graph spreading activation
node_category(node_id) ──▶ category assignment lookup
import_claude_mem(path?) ──▶ import from claude-mem.db
import_claude_code(path) ──▶ import from Claude Code JSONL
Via Rust library: Alaya coordinator
alaya.episodes().store(ep) ──▶ episodic store + graph links
alaya.knowledge().query(q) ──▶ BM25 + vector + graph → RRF → rerank
alaya.admin().preferences(domain?) ──▶ crystallized behavioral patterns
alaya.knowledge().filter(f?) ──▶ consolidated semantic nodes
alaya.admin().categories(min?) ──▶ emergent ontology with hierarchy
alaya.admin().subcategories(id)
…