anneal-memory
MCP serverDocs & knowledgeGive your AI a memory that holds onto what you tell it, even between conversations. anneal-memory stores what your AI learns across two layers and includes a built-in immune system that keeps those memories healthy. It has zero dependencies, so nothing extra is needed to run it.
Unavailable. This server has no hosted endpoint yet, so Ahel can't serve it.
Ahel cannot run this one yet; its page stays here for reference.
What your AI can do with it
- Remember details from past conversations
- Recall earlier context when you ask about it again
- Organize what it learns across two memory layers
- Keep stored memories healthy with a built-in immune system
- Add memory without installing anything extra, since it has zero dependencies
Getting started
- Read the source or reference documentation for what it needs to run.
- Check this page for availability before you add it to a pipeline on Ahel.
From the project's README
As published by phillipclapham/anneal-memory in README.md.
Living memory for AI agents. Episodes compress into identity.
Memory without grounding is amplification infrastructure.
Persistent user memory profiles increase agent sycophancy 16–45% across models (Gemini 2.5 Pro at 45%, others lower). Production deployments accumulate 97.8% junk entries within weeks. Clinical research documents memory scaffolding delusions across sessions. The failure mode here isn't memory. It's memory with nothing checking what gets kept.
anneal-memory puts a check between what an agent writes down and what it comes to believe. That idea isn't rare any more. MemTxn refuses a fact update whose values don't appear in the source it cites, and Agent Zero Memory answers only from evidence its reader actually opened.
Here's what I think is actually distinct, going by the 2026 systems I've read. A pattern in anneal is an abstraction, not a copied fact, and it has to earn its rank: it moves up a level (1x → 2x → 3x, no ceiling) only when it cites real episodes its explanation is grounded in, and a failed citation drops it a level (or holds it there for a while, marked carried-forward, if it was grounded recently). The consolidator can't quietly gut the memory it rewrites, either. On a store that declares an identity layer, a save that collapses those sections is refused, and consolidators wearing down their own memory is a documented failure. Then there's the assembly. An episodic evidence store, a bounded always-loaded continuity file, a long-term pattern tier recalled on cue, prospective tasks, a single-writer consolidation gate and a hash-chained audit log all ship in one package, with zero dependencies and no embeddings. None of those pieces is unique on its own. The combination is, as far as I've found.
The citation checks are narrow and structural: cited IDs must exist, the explanation must share words with the episode it cites, fabricated citations demote (unless carryforward holds a recently grounded pattern), one episode cited too often raises a flag, and re-citing old episodes doesn't count. They are not a complete defense against memory drift. Honest scope below says what they catch and what they don't.
And it's memory you own and govern. A local store, zero dependencies, no vendor in the loop — you decide what graduates into long-term memory, every change is recorded in a tamper-evident chain (best-effort on the write side — see Hash-chained audit trail for what verify can and cannot see), and the consolidation step that rewrites an agent's identity is gated to a human, not run unbidden (the Single-consolidator gate below). Own the substrate; govern what enters it.
Four cognitive layers — episodic store, compressed continuity, Hebbian associations, affective state tracking — plus two sibling stores: prospective spores (what the agent intends to do next) and a crystallized pattern store (graduated wisdom held out of always-loaded context and recalled on cue, so a large body of proven knowledge stays effective without clogging attention). Together they implement Complementary Learning Systems — see The Memory Architecture below. The Hebbian layer records links between episodes, but in three months of measurement on my own long-running store it never changed what recall returned. The part of recall that works is the citation edge (see Associations through consolidation). Zero dependencies (Python stdlib only). Works with any agent framework.
Quick Start
pip install anneal-memory
Windows
anneal-memory runs on Windows. What to know:
- Write locking is advisory POSIX
fcntland degrades to no lock at all on Windows. The sites (grep -n "fcntl.flock" anneal_memory/*.py) includestore.py's continuity lock,crystal.py'sCrystalStore._transaction,spores.py'sSporeStore._transaction, andaudit.py's audit manifest and audit append locks. On Windows, concurrent writers to one store — whether separate processes or threads within one process — can race or lose updates, since there is no lock of any kind to serialize them there. A single writer (one process, one thread) is unaffected: the unique-tmp + atomic-replace write still prevents a torn file. - No fork support for the audit trail. POSIX
flocklocks follow the open file description, which a forked child inherits. Do not fork a process while anAuditTrailin it is in use; a child must open its ownAuditTrail. - Through v0.9.11, the CLI uses the locale's encoding for stdin, stdout and stderr. Under a Windows console codepage, or any piped, redirected or subprocess consumption, the CLI's own status glyphs raise
UnicodeEncodeError, and non-ASCII content piped torecord -orsave-continuity -can be mis-decoded into the store. Fixed in 0.9.12: the CLI's standard streams are UTF-8 on every platform. - Through v0.9.43, if
ANNEAL_MEMORY_DBwas unset and no home directory could be found (a launcher that dropsUSERPROFILE/HOMEPATH, or on POSIX a container uid with no passwd entry and noHOME), every invocation crashed at startup withRuntimeError: Could not determine home directory, even one passing--db. Fixed after 0.9.43: only a command that opens the default path needs a home, and it refuses with exit 1, naming--dbandANNEAL_MEMORY_DB. - Windows CI runs a real but reduced subset of the suite: tests that simulate an unreadable/unlistable file or directory via POSIX
chmodare skipped there, since Windows/NTFS doesn't restrict access the same way, as are the cross-process lock test (see the write-locking bullet above) and the missing-home-directory simulation that clears the whole environment (the no-home tests that patchPath.expanduserrun everywhere).
Python Library
The library is the core product. Import it, use it in any framework or script.
from anneal_memory import Store, EpisodeType, prepare_wrap, validated_save_continuity
# Initialize (creates DB + continuity file automatically)
store = Store("./memory.db", project_name="MyAgent")
# Record episodes during work
store.record("Connection pool is the real bottleneck", EpisodeType.OBSERVATION)
store.record("Chose PostgreSQL as the database because ACID outweighs speed", EpisodeType.DECISION)
# Recall before decisions
result = store.recall(episode_type=EpisodeType.DECISION, keyword="database")
for ep in result.episodes:
print(f"[{ep.type}] {ep.content}")
# Compress at session end — this is where the cognition happens
wrap = prepare_wrap(store) # fetches episodes, marks wrap in progress
if wrap["status"] == "ready":
# Feed wrap["package"] to your LLM. Compression IS the cognition —
# patterns emerge from the act of compressing, not from storage.
compressed = your_llm.compress(wrap["package"])
validated_save_continuity(store, compressed) # full immune system pipeline
# "empty" status means no new episodes to wrap — skip
store.close()
See Library Quickstart for the full guide.
CLI
Inspect, debug, and manage agent memory from the command line — a full operator CLI with machine-readable --json output. Agents with shell access (Claude Code, Aider, etc.) can use the CLI directly for the full memory workflow.
# Point the demo at its own store. Without --db or ANNEAL_MEMORY_DB every
# command uses ~/.anneal-memory/memory.db, your default store.
export ANNEAL_MEMORY_DB=./demo.db
# Initialize. Global flags such as --db and --project-name go before the
# subcommand. --project-name names the memory in the continuity header and is
# not stored: pass it on each command (the default is "Agent").
anneal-memory --project-name MyAgent init
# Record and recall
anneal-memory record "Chose PostgreSQL as the database for ACID" --type decision
anneal-memory search "database"
# Consolidation is the operator's act: a new store wraps only under a session
# you have claimed the baton for. Claim once (init --no-baton opts out).
anneal-memory baton claim me
# Agent-driven compression (same workflow as library and MCP)
anneal-memory --project-name MyAgent prepare-wrap --session-id me # Get compression package
# Agent compresses...
anneal-memory --project-name MyAgent save-continuity out.md \
--session-id me --wrap-token "$WRAP_TOKEN" # the 'Wrap token:' line
# Operator commands (things MCP can't do)
anneal-memory stats # Detailed analytics
anneal-memory graph --format dot # Association graph (Graphviz)
anneal-memory diff --wraps 5 # Wrap metric progression
anneal-memory audit --since 7d # Read audit trail
anneal-memory audit-repair # Rebuild a quarantined audit manifest, or set aside a corrupt sealed week (--set-aside-unreadable: one that only fails to read)
anneal-memory export --format json # Full store export
# Done with the demo: return the CLI to your default store
unset ANNEAL_MEMORY_DB
See examples/agent-instructions.lean.cli.example for the agent workflow snippet.
MCP Server
For MCP-capable agent harnesses — Claude Code, Codex, Gemini CLI, Cursor, Windsurf, and others.
The server is one command — anneal-memory --project-name MyProject serve — wired into the harness's MCP config. The serve subcommand starts the MCP server; --project-name (and optional --db) are global flags and come before serve. Each harness has its own config file and format:
Claude Code / Cursor / Windsurf — mcpServers JSON (the editor's MCP settings, or a project .mcp.json):
{
"mcpServers": {
"anneal_memory": {
"command": "uvx",
"args": ["anneal-memory", "--project-name", "MyProject", "serve", "--session-id", "claude-code"]
}
}
}
Codex — ~/.codex/config.toml (or a project .codex/config.toml):
[mcp_servers.anneal_memory]
command = "uvx"
args = ["anneal-memory", "--project-name", "MyProject", "serve", "--session-id", "codex"]
Gemini CLI — ~/.gemini/settings.json (or a project .gemini/settings.json):
{
"mcpServers": {
"anneal_memory": {
"command": "uvx",
"args": ["anneal-memory", "--project-name", "MyProject", "serve", "--session-id", "gemini"]
}
}
}
Gemini CLI starts MCP servers only from a folder it trusts: in an untrusted folder gemini mcp list shows the server as Disconnected even though the config is right (trust the folder, or set GEMINI_CLI_TRUST_WORKSPACE=true).
Then add the agent-instructions snippet — agent-instructions.lean.example (the always-loaded baseline) or the .full.example reference — to the harness's instructions file (CLAUDE.md for Claude Code, AGENTS.md for Codex, GEMINI.md for Gemini CLI). It teaches the agent when and how to use the memory tools; without it the tools are available but the agent won't know the cognitive workflow. (See Claude Code / agent-harness adopters below for the lean/Skill/full layering.)
Consolidation is yours. Agents record episodes freely. Rewriting the agent's identity layer (the wrap) is the operator's act, so a new store consolidates only through a server whose --session-id you have claimed the baton for, once, from your own shell: uvx anneal-memory baton claim claude-code (or anneal-memory baton claim claude-code with a pip install). Until then the agent's wrap downgrades to capture-only, and both the downgrade and the status tool say how many episodes are waiting and the command for you to run. Set the id in the client's config as above, not in a shell profile (ANNEAL_MEMORY_SESSION_ID also works, but an exported one reaches every client launched from that shell). Every conversation started from one config shares its id, so after the claim each of that client's conversations may consolidate: the claim designates a client, not a single conversation. Move the baton between clients with baton claim NAME --take; see who holds it with baton status. A store created before this policy, or with init --no-baton, ignores --session-id and wraps as before.
What the gate does and does not hold: no MCP tool lets an agent choose its id or claim the baton, so an agent following the protocol cannot consolidate on its own initiative, and parallel sessions cannot each recompose your agent's identity. It is not a lock against an agent with a shell that ignores its instructions: such an agent can run baton claim or edit its own config. Keeping the baton with you is part of the operator's job.
Pinned install:
uvxfetches the latest published version on each run. For a pinned install,pip install anneal-memory, then set"command": "anneal-memory"with"args": ["--project-name", "MyProject", "serve", "--session-id", "claude-code"]— or pointcommandat an absolute path to the installed binary.
All Three Paths, Same Cognitive Loop
CLI and MCP are thin transport adapters over the same library — not separate implementations. Every access pattern calls the same prepare_wrap(store) and validated_save_continuity(store, text) pipeline under the hood, preserving the same workflow: record episodes during work → compress at session boundaries → load continuity at session start. The agent that records is the agent that compresses; that compression can't be delegated.
| Library | CLI | MCP | |
|---|---|---|---|
| Install | pip install anneal-memory | Same | uvx anneal-memory or same |
| Record | store.record(content, type) | anneal-memory record "..." --type T | record tool |
| Recall | store.recall(keyword=...) | anneal-memory search "..." | recall tool |
| Compress | prepare_wrap(store) → agent → validated_save_continuity(store, text) | prepare-wrap → agent → save-continuity | prepare_wrap → agent → save_continuity |
| Best for | Framework integration, custom agents | Agents with shell access, operators | MCP-enabled editors |
Recall reads one committed state. A recall reads one committed state, as of its start: an episode deleted or erased before recall begins is never returned; a delete that commits while a recall runs may or may not be reflected, as with any database read.
Framework Integrations
anneal-memory works with any agent framework through the Python library. Each guide below shows where to call the four core functions — record(), recall(), prepare_wrap(), validated_save_continuity() — within the framework's lifecycle.
| Framework | Integration Point | Guide |
|---|---|---|
| LangGraph / LangChain | AgentMiddleware (before/after agent + model) | docs/integrations/langgraph.md |
| CrewAI | BaseEventListener (event bus) | docs/integrations/crewai.md |
| OpenAI Agents SDK | RunHooks (agent lifecycle) | docs/integrations/openai-agents.md |
| Anthropic Agents SDK | agent-instructions snippet + Stop hook | docs/integrations/anthropic-agents.md |
| Google ADK | Callbacks + custom MemoryService | docs/integrations/google-adk.md |
| Pydantic AI | AbstractCapability with Hooks | docs/integrations/pydantic-ai.md |
| smolagents | step_callbacks dict | docs/integrations/smolagents.md |
| LlamaIndex | Instrumentation BaseEventHandler | docs/integrations/llamaindex.md |
| Haystack | Custom Tracer | docs/integrations/haystack.md |
| CAMEL-AI | WorkforceCallback | docs/integrations/camel-ai.md |
| AutoGen / AG2 | register_hook() | docs/integrations/autogen.md |
| DSPy | BaseCallback | docs/integrations/dspy.md |
These guides show integration patterns based on each framework's current API. The library works with any Python framework — the pattern is always the same: initialize a Store, call record() at meaningful moments, recall() before decisions, and run the wrap sequence at session end. Don't see your framework? The library quickstart shows the 4-function pattern that works everywhere.
Claude Code / agent-harness adopters (Skill + snippet)
Using anneal-memory inside an agent harness — Claude Code, Codex, Gemini CLI — rather than a Python framework? The Skill and snippets are repository artifacts: they live in this GitHub repo (and the source distribution), not in the pip/uvx wheel — clone the repo or download the files directly from GitHub to use them. They layer, they aren't a menu: the lean snippet is the always-loaded baseline; the Skill adds depth on demand.
- Lean snippet — the always-loaded baseline. Paste
examples/agent-instructions.lean.example(MCP) orexamples/agent-instructions.lean.cli.example(CLI) into yourCLAUDE.md/AGENTS.md/GEMINI.md. ~45 lines, always in context — the start-of-session continuity load, recording, recall-before-decisions, and the wrap sequence, with depth delegated to the Skill. (Copy-paste text; nothing to install.) - The Skill — depth on demand. Copy the
skill/anneal-memory/directory into.claude/skills/(per-project) or~/.claude/skills/(global).SKILL.mdcarries the comprehensive workflow and is model-invoked when you're doing memory work — primarily before decisions and on wrap. It is depth-on-demand, not a replacement for the lean snippet: a model-invoked skill won't reliably fire at a bare session start, so keep the lean snippet in place for the start-of-session step. - The full reference — everything inline.
examples/agent-instructions.full.example/.full.cli.exampleare the complete snippets (immune-system internals, the affective-state shape, the operator-command catalog) for adopters who'd rather keep it all in their instructions file than install a Skill.
After upgrading the package, run anneal-memory migrate check — it proposes edits to your instructions so they don't silently drift from the substrate (it never edits your files), then anneal-memory migrate ack.
Why This Exists
Three independent production failures share one root cause: no quality mechanism between memory write and memory read.
Sycophancy amplification. Agents with persistent user memory profiles become 16–45% more sycophantic than memoryless baselines, depending on model (Gemini 2.5 Pro at 45%, others lower). Memory recalls what the user liked hearing, the agent learns to repeat it, and stored approval patterns compound across sessions (Jain et al., CHI 2026; measured with user memory profiles across Gemini and Llama variants).
Junk accumulation. A detailed production audit on Mem0's tracker documents a deployment that generated 10,134 memory entries over 32 days — 224 were usable. The rest were duplicates, self-referential loops, and hallucinated entries: recalled memories re-extracted as new memories in a feedback loop that no one designed but nothing prevented.
Harmful reinforcement. Clinical research documents AI systems with persistent memory scaffolding delusional content across sessions — stored context creates feedback loops between recalled memories and generated responses, with cases of documented real-world harm (Morrin et al., Lancet Psychiatry 2026).
Most memory servers store memories and retrieve them. Few ask: is this memory still true? Was it ever true? Is it making the agent worse?
anneal-memory asks the first two at the pattern level, and has started measuring the third (see Does a recalled memory help? below):
- Is it true? Patterns must cite specific episode IDs as evidence to graduate. The server verifies the episodes exist and the explanation references the cited content via lexical overlap (≥2 meaningful words shared between the explanation and the episode body). Ungrounded citations demote, unless the pattern was grounded recently and carryforward holds it (see Activation-aware carryforward).
- Is it still current? Graduated patterns whose dates fall behind the staleness threshold (default 7 days) surface in the next wrap's package as removal candidates. The agent decides whether to demote, refresh evidence, or carry forward. This is a check on age, not on truth. A changed fact is handled separately, when the update names the episode it replaces (see Updated facts: supersession).
- Is the citation evidence real? The library catches fabricated episode IDs (no matching episode → demote), suspicious reuse of the same episode across many patterns in one session (per-ID frequency ≥3 → flag), and bare graduations with no
[evidence:]tag at all. The explanation-grounding check (≥2-word lexical overlap with episode content) raises the cost of fabricated evidence chains but is not a semantic-coherence check — see Honest scope below for what this catches and what it doesn't.
The result: memory as a living system, not a filing cabinet. Episodes accumulate fast, get compressed at session boundaries — and that compression is where patterns emerge and get validated. Co-cited episodes form lateral Hebbian associations (recorded and decayed at every wrap; recall does not read them, see What the links do, measured). The continuity file stays bounded and always-loaded, getting denser rather than longer.
The Immune System
The agent memory ecosystem is converging on consolidation as the right approach — even Anthropic's Claude Code now runs a periodic consolidation pass over accumulated session data. This validates the direction: raw accumulation doesn't scale, and compression at session boundaries is where intelligence emerges.
But consolidation alone doesn't solve the problem. A system that consolidates faithfully and a system that consolidates sycophantically produce the same kind of output — compressed, structured, always-loaded. The difference is whether anything checks the quality of what got consolidated. That's the immune system.
Structural immune-system primitives at the citation layer
The library implements a set of structural defenses around how patterns earn graduation. They are narrow and specific — naming them honestly is part of the architecture.
Citation-validated graduation. Patterns start at 1x. To graduate to Proven tier — 2x and every level above it, with no ceiling — they must cite specific episode IDs as evidence. The server verifies those IDs exist in the current wrap's frozen episode snapshot — the cross-session episode set is intentionally out of scope. No matching episode IDs, no promotion.
Explanation-grounding check. For each cited episode, the explanation in [evidence: ID "explanation"] must share ≥2 meaningful words (>2 chars, non-stopword) with the cited episode's content. This catches citations whose explanations are fabricated wholesale (no overlap → demote). It is lexical, not semantic — see Honest scope below.
Shortened here. Read the whole README on GitHub.
Signals
- GitHub stars
- 11
- Forks
- 2
- Last commit
- Oct 2026
- Weekly downloads
- 3k
Advanced
- Delivery
- anneal-memory MCP server → your Ahel connector (mcp.ahel.ai) → your AI.
- Item type
- mcp-server
- Key
io-github-phillipclapham-anneal-memory- Source
- github.com/phillipclapham/anneal-memory
github.com/phillipclapham/anneal-memory
More in Docs & knowledge
MCP server · mnemoverse
More in Docs & knowledgeagent-native-slides
MCP server · builderio
More in Docs & knowledgedatasinking
MCP server · heubme2020
More in Docs & knowledgeTransloadit Media Processing
MCP server · transloadit
More in Docs & knowledgeknowl
MCP server · dat999zx
More in Docs & knowledgeemailmd
MCP server · anypost
More in Docs & knowledge