engram
Provides agents with cross-session memory by compressing run trajectories into reusable conclusions and strategies and recalling relevant priors via MCP.
README
Engram
The memory-trace layer for agents. Make any agent loop learn from its own runs.
Every multi-attempt agent today throws its raw trajectory back into context on retry — burning tokens and degrading quality. The June-2026 research frontier showed the fix is to inject a distillate of what happened, not the transcript, and to bank reusable conclusions across tasks. Engram is that layer, framework-agnostic and dependency-free.
Built directly on two results:
- RTV + PDR — Scaling Test-Time Compute for Agentic Coding (arXiv 2604.16529). Compress each rollout into hypotheses + failures + leads; vote across attempts (Recursive Tournament Voting); condition the next attempt on the distillate (Parallel-Distill-Refine). +12 pts on Terminal-Bench v2.0.
- TMAS two-bank memory — Scaling Test-Time Compute via Multi-Agent Synergy (arXiv 2605.10344). One bank of reliable conclusions, one of meta-strategies, shared across runs.
Why
The bottleneck on hard agent tasks is not the model — it's that agents don't reuse what they already learned. Engram gives them a memory trace: compress → bank → recall → select.
Use it as an MCP server (no code)
Engram ships an MCP server, so any agent that speaks MCP — Claude Code, Claude Desktop, Cursor — gets cross-session memory without you writing a line.
{
"mcpServers": {
"engram": { "command": "node", "args": ["/abs/path/to/engram/mcp.mjs"] }
}
}
Clone-and-point for now; the npm package name is agent-engram, not yet published. (engram, engram-mcp and engram-memory are all taken on npm by unrelated authors — worth knowing before you go looking for this by name.)
Five tools:
| tool | when the agent calls it |
|---|---|
engram_recall |
first, on any non-trivial task — returns a priors block to paste into its own reasoning |
engram_ingest |
when a task ends, succeeded or failed — compresses the trajectory and banks the durable parts |
engram_compress |
to hand a long transcript to another model without paying for the whole thing |
engram_note |
to bank one fact or strategy directly, no trajectory needed |
engram_stats |
how much is banked, and where on disk |
Memory is JSON under ~/.engram-store (override with ENGRAM_STORE). Nothing leaves the machine.
What Engram banks, and one measured negative result
Two kinds of thing come out of a finished run, and Engram keeps them in separate banks per TMAS:
- "The auth token lives in
.env.local" — a conclusion, true about this codebase. - "When a test fails on CI but not locally, diff the env first" — a strategy, true about how to work, and reusable on a task that has nothing to do with auth.
Failed runs are worth more than successful ones here. ingest turns each failure into an avoid-strategy carrying its root cause, which is the difference between the next session solving something and rediscovering it.
The honest part. The obvious argument for the split is that in one undifferentiated pile the codebase-specific conclusions out-match the transferable strategy on keywords and crowd it out of the top-k. I tested that claim against this implementation before writing it down, at 10:1, 13 items, and 200:5 conclusions-to-strategies. It did not hold. The single pile surfaced the same strategy, at rank #1 in two of the three runs — because TF-IDF's IDF term already boosts an item whose vocabulary is rare in the corpus, which is exactly what a lone strategy among many similar conclusions looks like.
So the split here buys structural things — a guaranteed recall budget for strategies, the ability to ask for one kind without the other, and fidelity to the paper — and not a retrieval win I can demonstrate. Reproduce it yourself: node bench/two-bank.mjs. If you find a store shape where the split does win, that is a genuinely interesting issue to open.
Install
# zero runtime dependencies; Node 18+
npm install # nothing to build — pure ESM
npm test # node --test
npm run demo # offline, deterministic
Use
import { Engram } from 'agent-engram';
const engram = new Engram({ store: './engram-store' });
// 1. Recall priors before an attempt — inject the block into your prompt.
const priors = engram.recallPriors('Fix the failing checkout test');
// priors.block -> "# Relevant priors from past runs ..."
// 2. Learn from a finished attempt.
await engram.ingest({
goal: 'Fix the failing checkout test',
steps: [
{ type: 'error', content: 'TypeError: total is undefined — cart was empty' },
{ type: 'result', content: 'Guard added: default cart to [] before reducing.' },
],
outcome: 'success',
});
// 3. Or hand Engram the whole loop: it runs N attempts and selects the best.
const { winner } = await engram.solve(
'Fix the failing checkout test',
async (priorsBlock, attempt) => myAgent.run({ context: priorsBlock }),
{ attempts: 3 },
);
Step types
A trajectory is an array of { type, content }. Types: thought, action, observation, error, result. The compressor routes errors → failures (with root cause), results → artifacts, actions → leads, thoughts → hypotheses.
Model-backed compression (optional)
By default compression is deterministic and offline. Pass an llm to let a model write richer distillates:
const engram = new Engram({
store: './engram-store',
llm: async (prompt) => callYourModel(prompt), // returns the JSON distillate
});
API
| Call | Does |
|---|---|
recallPriors(goal) |
TF-IDF recall from both banks → { block, conclusions, strategies, tokens } |
ingest(run) |
Compress a run, bank its conclusions + strategies, return the distillate |
compress(run) |
Compress only (no banking) |
solve(goal, runner, { attempts }) |
Run N attempts, tournament-select the winner, learn from it |
compressTrajectory(run) |
Standalone trajectory → distillate |
MemoryBank |
Standalone two-field TF-IDF memory store |
tournament(candidates, judge?) |
RTV selection over distillates |
License
MIT.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.