Skip to main content

Engram AI 🧠

Neuroscience-grounded memory for AI agents — ACT-R activation, Hebbian learning, cognitive consolidation

License Python PyPI

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:

  1. Memory → SOUL: Negative emotional patterns trigger drive suggestions
  2. SOUL → Memory: Memories aligned with drives get importance boost
  3. Behavior → HEARTBEAT: Failed actions get deprioritization suggestions
  4. 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

🤖 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:

  1. Decays weak memories (Ebbinghaus forgetting curve)
  2. Strengthens frequently-used ones (move working → core → long-term)
  3. 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


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.

GitHub · PyPI · crates.io · Issues

Metadata

Release files for engramai 2.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for engramai 2.1.0
File Size Uploaded
engramai-2.1.0.tar.gz 152.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for engramai 2.1.0
File Interpreter ABI Platform
engramai-2.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 276.5 kB

Release files / engramai-2.1.0.tar.gz

Download URL engramai-2.1.0.tar.gz
Size 152.7 kB
Tags Source
SHA-256 checksum
How to use checksums
3c14818c0912b15a802b56af48f353492f321bf3668292b3962255b1b03dbd78
BLAKE2b-256 checksum
How to use checksums
a201c09815b14b0174dd27616e5ae00d62e605f61f2cac63c56055218d1afe8b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / engramai-2.1.0-py3-none-any.whl

Download URL engramai-2.1.0-py3-none-any.whl
Size 123.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
187a07fec3320d5a96f6ad8a9c089d3ca958524b4f3e5ecf54b87f7dd9308047
BLAKE2b-256 checksum
How to use checksums
c694580fa844c81194d171a01d9a6e08b5317e78a0aa2a5b244835e5f0ed012f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

2.1.0 This release

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page