Neuroscience-grounded memory system for AI agents with multi-agent support, emotional feedback, and semantic search
Project description
Engram AI ๐ง
Neuroscience-grounded memory for AI agents โ ACT-R activation, Hebbian learning, cognitive consolidation
Give your AI agent a brain that actually remembers, associates, and forgets like a human.
Available in 3 runtimes:
| Runtime | Package | Use When |
|---|---|---|
| ๐ Python | engramai on PyPI |
Python agents, MCP server, Claude Desktop |
| ๐ฆ Rust | engramai on crates.io โ GitHub |
Performance-critical, embedded, zero-dependency |
| ๐ฆ TypeScript | engram-ts/ |
Node.js agents, OpenClaw |
| ๐ OpenClaw Plugin | openclaw-plugin/ |
Drop-in replacement for OpenClaw's default context engine |
What is Engram?
Most AI agents use a dumb FIFO window for context โ keep the last N messages, throw away the rest. Engram replaces this with a cognitive memory system based on how human brains actually work:
- ๐ง ACT-R Activation โ Memories strengthen with use, decay with time (not a fixed window)
- ๐ Hebbian Learning โ "Neurons that fire together, wire together" โ related memories auto-associate
- ๐ค Consolidation โ Periodic forgetting + strengthening cycles (like sleep)
- ๐ฏ Working Memory โ Miller's Law 7ยฑ2 chunks, automatic topic-change detection
- ๐ Cross-Language Search โ Recall memories across 50+ languages
- ๐ฐ Zero Cost โ Heuristic capture + prompt caching = $0 additional spend
๐ OpenClaw Context Engine Plugin
The fastest way to use Engram โ replace OpenClaw's default FIFO context with cognitive scoring in one config line:
# openclaw.yaml
plugins:
slots:
contextEngine: engram
entries:
engram:
autoCapture: true
Instead of keeping the last N messages, Engram scores every message by ACT-R activation ร Hebbian association ร content importance, then packs the most cognitively relevant ones into the token budget. Long-term memories persist across sessions automatically.
| Default (Legacy) | Engram | |
|---|---|---|
| Strategy | Keep last N messages (FIFO) | Score by cognitive relevance |
| Long-term memory | None | ACT-R + Hebbian |
| Cross-session | Compaction summaries (LLM cost) | Persistent recall (zero cost) |
| Topic awareness | None | Working memory + topic detection |
| Auto-capture | None | Preferences, facts, decisions, corrections |
| Cost | LLM summarization tokens | Zero (heuristic) |
โ Full plugin docs | Source
๐ Battle-Tested in Production
Real numbers from a live AI agent running 24/7:
| Metric | Value |
|---|---|
| Memories stored | 3,846 |
| Recalls served | 230,103 |
| Hebbian links formed | 12,510 (automatic) |
| Consolidation layers | 320 working โ 224 core โ 3,302 archive |
| Database size | 48 MB |
| Recall latency | ~90ms |
| Additional cost | $0 (prompt caching absorbs overhead) |
Quick Start
Python
pip install engramai
from engram import Memory
memory = Memory("./my-agent.db")
# Store
memory.add("User prefers detailed explanations", type="relational", importance=0.8)
memory.add("Project deadline: Feb 10", type="factual")
# Recall (ACT-R activation + Hebbian association + semantic similarity)
results = memory.recall("user preferences", limit=5)
# Consolidate (Ebbinghaus forgetting + strengthening)
memory.consolidate(days=1.0)
TypeScript
import { Memory } from 'neuromemory-ai';
const memory = new Memory('./my-agent.db');
memory.add("User prefers TypeScript over JavaScript", { type: "preference", importance: 0.8 });
const results = memory.recall("user language preferences", { limit: 5 });
Rust
use engramai::Memory;
let mut memory = Memory::new("./my-agent.db", None)?;
memory.add("User prefers Rust for systems programming", "preference", 0.8, None)?;
let results = memory.recall("user preferences", 5, None, None)?;
MCP Server (Claude Desktop, etc.)
export ENGRAM_DB_PATH=./my-agent.db
python3 -m engram.mcp_server
๐ Engram v2: Multi-Agent Intelligence
Engram v2 adds powerful features for building multi-agent systems with shared memory, emotional feedback, and cross-agent intelligence:
๐ Namespace Isolation & ACL
Separate memory spaces for different agents/domains with fine-grained access control:
from engram import Memory
from engram.acl import Permission
memory = Memory("./shared.db")
memory.set_agent_id("trading_agent")
# Store in namespace
memory.add_to_namespace(
"Oil prices spiked 15%",
type="factual",
importance=0.9,
namespace="trading"
)
# ACL: Grant read permission to another agent
memory.grant("ceo_agent", "trading", Permission.READ)
# Subscribe to high-importance events
memory.subscribe("ceo_agent", "*", min_importance=0.8)
# Check for notifications
notifications = memory.check_notifications("ceo_agent")
# โ [{memory_id: "...", namespace: "trading", content: "Oil prices...", importance: 0.9}]
Use cases:
- CEO pattern โ Supervisor agent monitors specialist agents' discoveries
- Team collaboration โ Agents share knowledge in topic-specific namespaces
- Privacy isolation โ Sensitive memories stay in restricted namespaces
๐ญ Emotional Bus โ Memory โ Personality Feedback Loop
The Emotional Bus connects memory to agent workspace files (SOUL.md, HEARTBEAT.md), creating a closed-loop between what the agent experiences and how it evolves:
from engram import Memory
from engram.bus import EmotionalBus
memory = Memory.with_emotional_bus(
db_path="./agent.db",
workspace_dir="./workspace"
)
# Store memory with emotional tracking
memory.add_with_emotion(
"Debugging session took 3 hours with no progress",
type="episodic",
emotion=-0.8, # Negative experience
domain="debugging"
)
# Bus accumulates emotional trends
bus = memory.emotional_bus()
trends = bus.get_trends()
# โ [EmotionalTrend(domain="debugging", valence=-0.75, count=5)]
# Suggest SOUL updates based on patterns
suggestions = bus.suggest_soul_updates()
# โ [SoulUpdate(domain="debugging", action="add drive",
# content="Avoid lengthy debugging sessions without breaks")]
# Drive alignment boosts importance
# Memory matching SOUL drives gets automatic importance boost
bus.drives # โ [Drive(name="curiosity", description="...")]
Workspace files:
SOUL.md โ Core drives/values:
# Core Drives
curiosity: Always seek to understand new things
efficiency: Prefer action over endless discussion
HEARTBEAT.md โ Periodic tasks:
- [ ] Check email
- [x] Run consolidation
How it works:
- Memory โ SOUL: Negative emotional patterns trigger drive suggestions
- SOUL โ Memory: Memories aligned with drives get importance boost
- Behavior โ HEARTBEAT: Failed actions get deprioritization suggestions
- HEARTBEAT โ Behavior: Successful patterns get reinforced
Use cases:
- Self-improving agents โ Personality evolves from experience
- Emotional coherence โ Agent behavior aligns with "values"
- Adaptive task scheduling โ HEARTBEAT learns what works
๐ Cross-Namespace Intelligence
Hebbian links can span namespaces, enabling cross-domain insights:
# Recall with cross-namespace associations
result = memory.recall_with_associations(
"market volatility",
namespace="*", # Search all namespaces
limit=5
)
# Returns both memories + cross-links
for link in result.cross_links:
print(f"{link.source_ns}:{link.source_id} โ {link.target_ns}:{link.target_id}")
# trading:abc123 โ geopolitics:def456 (strength: 0.85)
Discovery pattern:
# Find connections between two domains
links = memory.discover_cross_links("trading", "geopolitics")
# โ Reveals how trading events correlate with political events
๐ v2.1.0: LLM Extraction & Hybrid Search
๐ค LLM-Powered Memory Extraction
Instead of storing raw conversation text, extract key facts automatically:
from engram import Memory, AnthropicExtractor
memory = Memory("./agent.db")
# Option 1: Auto-configure from environment
# Just set ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN and it works automatically
# Option 2: Explicit setup
memory.set_extractor(AnthropicExtractor(api_key="sk-ant-..."))
# Now add() extracts facts automatically
memory.add("I had pizza yesterday and it was great, but my girlfriend didn't like it")
# Stores two separate facts:
# 1. "User likes pizza" (relational, importance 0.6)
# 2. "User's girlfriend doesn't like pizza" (relational, importance 0.6)
Why it matters:
- Better recall: Search for "user food preferences" finds "pizza" even if the word "preference" wasn't in the original text
- Cleaner memory: Facts are normalized, not duplicated across conversations
- Cost-effective: Uses Claude Haiku (~$0.0001 per memory) or local Ollama models (free)
๐ง Config Hierarchy
Engram now supports layered configuration with clear priority:
| Priority | Source | Use Case |
|---|---|---|
| 1. Code | memory.set_extractor(...) |
Agent harnesses (RustClaw, etc.) |
| 2. Env vars | ANTHROPIC_AUTH_TOKEN / ANTHROPIC_API_KEY |
Local dev, Docker |
| 3. Config file | ~/.config/engram/config.json |
User preferences |
| 4. No extractor | Falls back to raw text storage | Backward compatible |
# Initialize config interactively
python3 -m engram init
Config file (~/.config/engram/config.json):
{
"embedding": {
"provider": "ollama",
"model": "nomic-embed-text"
},
"extractor": {
"provider": "anthropic",
"model": "claude-haiku-4-5-20251001"
}
}
โ ๏ธ Security: Never store API keys in config files. Use environment variables.
๐ฏ Hybrid Search (FTS + Embedding + ACT-R)
recall() now uses triple scoring by default:
results = memory.recall("user preferences", limit=5)
# Automatically combines:
# 15% FTS (exact term matching)
# 60% Embedding (semantic similarity)
# 25% ACT-R (recency/frequency/importance)
Why three signals?
- FTS: Catches exact matches (project names, technical terms)
- Embedding: Catches semantically similar concepts ("preference" โ "like")
- ACT-R: Prioritizes recently/frequently accessed memories
Configurable weights (Rust crate only, Python coming soon):
let mut config = MemoryConfig::default();
config.fts_weight = 0.30; // 30% exact matching
config.embedding_weight = 0.50; // 50% semantic
config.actr_weight = 0.20; // 20% temporal
๐ถ CJK Tokenization (Rust only, Python coming soon)
Chinese/Japanese/Korean text now gets intelligent word segmentation via jieba:
โ Before:
"engramๆฏ่ฎค็ฅ่ฎฐๅฟ็ณป็ป" โ split into 8 characters
Search "่ฎฐๅฟ็ณป็ป" matches poorly
โ
After (with jieba):
"engramๆฏ่ฎค็ฅ่ฎฐๅฟ็ณป็ป" โ ["engram", "ๆฏ", "่ฎค็ฅ", "่ฎฐๅฟ็ณป็ป"]
Search "่ฎฐๅฟ็ณป็ป" matches precisely
Performance impact: Negligible (~0.02ms per memory vs ~50ms for embedding generation)
Core Concepts
๐ง ACT-R Activation
Every memory has an activation level that decays over time but strengthens with each access:
activation = base_level + spreading + importance_boost
base_level = ln(ฮฃ tแตข^(-d)) # frequency ร recency decay
spreading = ฮฃ wโฑผ ร Sโฑผแตข # context similarity
This means frequently-accessed, recent memories surface first โ but old important memories can still be recalled if they're relevant to the current context.
๐ Hebbian Learning
Memories that are recalled together form automatic associations:
ฮW = ฮท ร aแตข ร aโฑผ # co-activation strengthens links
Ask about "Docker" and "deployment" in the same conversation โ they become linked. Next time you ask about deployment, Docker memories get boosted automatically.
๐ค Consolidation
Like human sleep, periodic consolidation:
- Decays weak memories (Ebbinghaus forgetting curve)
- Strengthens frequently-used ones (move working โ core โ long-term)
- Prunes noise (below-threshold memories removed)
๐ฏ Working Memory (TypeScript / OpenClaw Plugin)
Session-level state based on Miller's Law (7ยฑ2 chunks):
- Tracks what's "active" in the current conversation
- Detects topic changes โ triggers full recall
- Continuous topic โ reuses cached memories (70-80% fewer DB queries)
๐งฉ Memory Types
| Type | Use For | Example |
|---|---|---|
factual |
Facts and knowledge | "Project uses Python 3.12" |
episodic |
Events | "Shipped v2.0 on Jan 15" |
preference |
User preferences | "Prefers concise answers" |
procedural |
How-to knowledge | "Deploy: run tests first, then push" |
semantic |
Concepts and relationships | "Causal inference relates to Pearl" |
causal |
Cause-effect relationships | "Rate hikes โ USD strengthens" |
Architecture
Query
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Vector Search (semantic)โ โ optional embedding provider
โ FTS5 Search (lexical) โ โ always available, zero-cost
โ Merge & Dedupe โ
โโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ACT-R Activation โ โ frequency ร recency decay
โ Hebbian Spreading โ โ association boost from linked memories
โ Importance Weighting โ โ user-set priority
โ Confidence Scoring โ โ metacognition layer
โโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โ
Ranked Results
Configuration
Embedding Providers
Engram works without any embedding provider (FTS5 keyword search). Add one for cross-language semantic search:
| Provider | Cost | Setup | Best For |
|---|---|---|---|
| None / FTS5 | Free | Zero config | Simple agents, testing |
| Sentence Transformers | Free | pip install "engramai[sentence-transformers]" |
Privacy, offline |
| Ollama | Free | Ollama + embedding model | Already using Ollama |
| OpenAI | ~$0.0001/query | OPENAI_API_KEY |
Highest quality |
Environment Variables
| Variable | Default | Description |
|---|---|---|
ENGRAM_EMBEDDING |
auto |
Provider: auto, sentence-transformers, ollama, openai, none |
ENGRAM_DB_PATH |
./engram.db |
Database path |
ENGRAM_ST_MODEL |
paraphrase-multilingual-MiniLM-L12-v2 |
Sentence Transformers model |
OPENAI_API_KEY |
โ | Required for OpenAI embeddings |
CLI
neuromem add "User prefers dark mode" --type preference --importance 0.8
neuromem recall "user preferences"
neuromem stats
neuromem consolidate
neuromem forget --threshold 0.01
neuromem hebbian "dark mode"
๐ Documentation
- OpenClaw Plugin Guide โ Drop-in context engine replacement
- Integration Guide โ Level 3 auto-recall/store implementation
- Performance Analysis โ Production metrics and optimization
- Embedding Configuration โ Provider setup and tuning
- Vision โ Where Engram is heading
Development
git clone https://github.com/tonitangpotato/engram-ai.git
cd engram-ai
# Python
pip install -e ".[dev,all]"
pytest
# TypeScript
cd engram-ts && npm install && npm test
# OpenClaw Plugin
cd openclaw-plugin && npm install && npm test
Credits
Built on research from:
- ACT-R (Adaptive Control of Thought-Rational) โ Anderson, Carnegie Mellon
- Hebbian Learning โ Donald Hebb, 1949
- Memory Consolidation โ Walker & Stickgold (sleep research)
- Forgetting Curve โ Hermann Ebbinghaus, 1885
- Working Memory โ Baddeley & Hitch, 1974
- Miller's Law โ George Miller, 1956 ("The Magical Number Seven")
License
AGPL-3.0-or-later โ see LICENSE for details. Commercial licensing available, see COMMERCIAL-LICENSE.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file engramai-2.1.0.tar.gz.
File metadata
- Download URL: engramai-2.1.0.tar.gz
- Upload date:
- Size: 152.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c14818c0912b15a802b56af48f353492f321bf3668292b3962255b1b03dbd78
|
|
| MD5 |
5ea47fdbc38835a7ddfebf9337e4fc8a
|
|
| BLAKE2b-256 |
a201c09815b14b0174dd27616e5ae00d62e605f61f2cac63c56055218d1afe8b
|
File details
Details for the file engramai-2.1.0-py3-none-any.whl.
File metadata
- Download URL: engramai-2.1.0-py3-none-any.whl
- Upload date:
- Size: 123.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
187a07fec3320d5a96f6ad8a9c089d3ca958524b4f3e5ecf54b87f7dd9308047
|
|
| MD5 |
649f366673d3979ebec6e8794d037a7e
|
|
| BLAKE2b-256 |
c694580fa844c81194d171a01d9a6e08b5317e78a0aa2a5b244835e5f0ed012f
|