DEV Community

Cover image for I compared 12 AI coding agent memories. Most only remember what, not why
iCe Gaming
iCe Gaming

Posted on

I compared 12 AI coding agent memories. Most only remember what, not why

Your agent does not have a memory problem. It has a "why" problem.

Every tool in this post can make an agent remember something tomorrow. A markdown file remembers what you typed into it. A memory layer remembers facts it extracted from a chat. A session recorder remembers what tools ran. Very few of them remember the thing that actually costs you time: why a fix landed, and which three obvious fixes were already tried and failed.

I spent the last few weeks reading the docs and source of every agent memory option I could find, and sending about 400 cold emails to dev teams asking how they handle memory for Claude Code, Cursor and Codex. Most of them were not convinced they needed anything new. Some of them were right. This post is the guide I wish I had before I started: what each option really stores, who writes it, how it is retrieved, whether a team can share it, and where it breaks.

Disclosure up front: I build one of the tools in this comparison (palace-rs, and the Palace team server on top of it). I have tried to describe it with the same rules as everything else: only what the repo and docs confirm, drawbacks included. You can weigh my opinions accordingly.

The problem in one scene

Monday: Alice's agent hits a flaky test in the payment webhook. It tries a retry wrapper (makes it worse). Then a longer timeout (hides it). Then it finds the real cause: the test fixture shares a database connection across workers. It fixes the fixture. The commit says:

fix: isolate webhook fixture connection
Enter fullscreen mode Exit fullscreen mode

Thursday: Bob's agent sees a different flaky test in the same area. It reads CLAUDE.md. Nothing about webhooks. It reads the git log and finds Alice's commit, but the commit does not say "retries and timeouts are traps here". So Bob's agent tries a retry wrapper. Then a longer timeout. Forty minutes later it lands on the same fixture fix.

Nothing in that story is exotic. It is three separate failures stacked on top of each other:

  1. Agents forget. Every session starts with an empty context window.
  2. Agents repeat dead ends. The successful fix is recorded somewhere (the commit). The failed attempts are recorded nowhere.
  3. Teammates' agents do not share. Even if Alice's agent remembered, that memory lives on Alice's laptop.

Keep those three in mind. Every option below solves some of them and ignores the rest.

A taxonomy of agent memory

Landscape of agent memory: seven families, from static instruction files to shared team memory

"Memory" is used for at least seven different things. Mixing them up is the main reason these comparisons go nowhere.

  1. Instruction files (static context). CLAUDE.md, AGENTS.md, Cursor rules, .github/copilot-instructions.md. Text a human (or an agent, when asked) writes, loaded into every session.
  2. Structured repo docs. Memory banks, ADRs, commit messages, spec files like Allium. Still files in git, but with a schema or a ritual around them.
  3. Built-in assistant memory. Claude Code auto memory, Codex memories, Copilot Memory. The vendor's tool writes notes for itself.
  4. Session recorders. claude-mem. Watch what the agent does, compress it into observations, inject them next time.
  5. Personal memory layers. Mem0, Supermemory, palace-rs, the official MCP knowledge-graph server, Basic Memory. An API, MCP server or local engine that stores facts or records for one user's agents.
  6. Graph and agent-managed memory. Zep/Graphiti (temporal knowledge graphs), Cognee (graph plus vectors), Letta (the agent edits its own memory blocks), LangMem (a library for building any of the above), and palace-rs again (a temporal knowledge graph, a room graph, and memory the working agent manages through MCP tools).

palace-rs does not fit in one box: it is a personal memory layer, a temporal graph and agent-managed memory in one local engine. It is still single-machine; the team version of the same model is Palace Server, in family 7.

  1. Shared team memory. One store that several developers' agents read and write, with permissions: Palace Server, Copilot's repo-level facts, and DIY team setups. Very few products actually live here.

The big comparison

The table covers 19 live options (plus Cursor Memories, which no longer exists). The grid after it scores the 12 most common head to head. The table is long because the differences are in the details. "Who writes it" and "can it invalidate" are the two columns that matter most for coding agents, and they are the ones marketing pages skip.

Option What it stores Who writes it Retrieval Team / shared Where it runs Licence Setup cost Can it mark something as wrong?
CLAUDE.md / AGENTS.md / Cursor rules / Copilot instructions Rules and conventions as prose You (or the agent when asked) Loaded whole, every session (Cursor rules can be scoped by glob or "apply intelligently") Yes, via git Local files n/a Minutes Only by editing the file
Cline memory bank Six markdown files: brief, product context, active context, system patterns, tech context, progress The agent, on "update memory bank" Agent reads all files at task start Yes, via git Local files n/a (a prompt pattern) Minutes Only by rewriting the file
ADRs + commit messages The decision and the final fix Humans and agents grep, git log, blame Yes, via git Local n/a Habit, not setup Superseding ADR; commits are permanent
Allium (.allium spec files) Intended behaviour: entities, rules with when / requires / ensures The agent, via /elicit, /distill, /tend, /weed skills Read as a spec; CLI validates; generates tests Yes, via git Local MIT Low to medium (new language) Edit the spec; /weed reconciles spec and code
Claude Code auto memory user, feedback, project and reference notes Claude, automatically MEMORY.md index (first 200 lines or 25 KB) loaded at start, topic files on demand No (per repo, per machine) Local, ~/.claude/projects/<project>/memory/ Proprietary tool Zero (on by default locally) Edit or delete via /memory
Codex memories Summaries and durable entries from prior chats Codex, in the background Injected into future sessions, not guaranteed No (per machine) Local, ~/.codex/memories/ Proprietary tool Flip a flag (off by default) Delete the store; docs say do not hand-edit
Copilot Memory Repo facts with code citations, user preferences Copilot agents Recent memories in prompt; citations checked against the current branch before use Yes, repo facts shared with repo users GitHub cloud Proprietary Toggle (launched as public preview) Yes: agent stores a corrected memory when citations contradict it; unused entries expire after 28 days
Cursor Memories (removed in Cursor 2.1; export to rules) n/a n/a n/a n/a n/a n/a n/a
claude-mem (103k stars) Typed observations (bugfix, feature, decision, discovery...) and session summaries A separate observer model watching the session Session-start injection plus search -> timeline -> get_observations MCP tools; SQLite FTS5, optional Chroma Optional TeamBrain shared workspace Local worker; hosted options Apache-2.0 npx install; Node, Bun, uv Delete via API/viewer; no supersede or validity model found
Mem0 (OSS + platform) LLM-extracted facts ("Project decision: use Postgres") An LLM extraction pass on what you send Semantic + keyword + entity (+ temporal on platform) Scoped by user_id / agent_id / run_id; your app decides Self-host or cloud Apache-2.0 Medium (LLM + vector store) Explicit update/delete; extraction is additive by default
Supermemory Documents and extracted memories, profiles Its extraction pipeline Hybrid search via API Namespaces Cloud, or a local binary (MCP is hosted-only) SDKs MIT; local server binary closed source Low Via API
MCP knowledge-graph memory server Entities, relations, atomic observations in a JSONL file The agent via tools Read graph / search nodes No (one file) Local MIT Minutes Delete observations or entities
Basic Memory Markdown notes with observations and wikilinks You and the agent, same files Semantic + full-text search over notes Cloud Teams offering Local files; optional cloud AGPL-3.0 Low (Python) Edit the note
Zep / Graphiti Temporal knowledge graph: entities, facts with validity windows, episodes LLM extraction from episodes Hybrid semantic + keyword + graph traversal Graphiti: you build tenancy; Zep cloud: yes Graphiti self-host; Zep is cloud (Community Edition discontinued April 2025) Apache-2.0 (Graphiti) High (graph DB + LLM + embedder + your service) Yes, bi-temporal edge invalidation, history kept
Cognee Knowledge graph + vector index over text, code, chats Its pipeline (remember / improve) Routed graph/vector recall; code graph queries Dataset permissions; API mode shares one graph Local (SQLite, LanceDB, Kuzu) or Postgres/Neo4j Apache-2.0 Medium forget; temporal mode keeps superseded facts
Letta Core memory blocks (always in context) + archival memory The agent edits its own blocks Blocks in prompt; archival via search tools Shared blocks across agents possible Self-host (Postgres + pgvector) or cloud Apache-2.0 Medium to high The agent rewrites its blocks
LangMem Semantic, episodic, procedural memories in your LangGraph store Agent tools + background consolidation Your store's search Whatever your store allows Your infra MIT Medium (you build it) Consolidation updates entries
DIY RAG (pgvector, Chroma) Whatever you chunk Whatever you write Vector (+ keyword if you add it) If you build it Your infra Varies Medium to high, forever If you build it
palace-rs Verbatim drawers (code, notes, diaries) in wings and rooms, per-agent diaries, a temporal KG of facts with valid_from / valid_to, a room graph with tunnels across wings, standing rules and preferences loaded at every session start (global, plus the project's own wing) The working agent, through MCP tools (diary, KG add / invalidate, remember / forget, add / delete drawer), plus mining your repo Hooks inject at session start, on prompt, during tool use; BM25 + cosine hybrid with provenance; KG queries with as_of; graph traversal and tunnels Shared across agents on one machine; not a team server Local: one binary, one SQLite file, local ONNX embeddings MIT Low (one binary, palace install) Yes: palace_kg_invalidate closes a fact's validity window; palace_conflicts flags contradictions
Palace Server (team) Same model as palace-rs, central Each developer's agents Same MCP tools over the network Yes: shared drawers, KG and diaries; roles; row-level isolation; audit log of writes Self-hosted only: Docker Compose or binary + Postgres/pgvector Commercial (built on the MIT core) Medium (a server and a database) Same invalidation, for the whole team

What each option actually remembers: rules, final fix, dead ends, why, invalidation, shared

Instruction files: necessary, and not memory

CLAUDE.md, AGENTS.md, .cursor/rules/*.mdc and .github/copilot-instructions.md are the right home for rules. Build commands. "Use pnpm, not npm." "Never touch the generated client." Codex concatenates AGENTS.md files from the repo root down to the current directory and stops at 32 KiB by default. Claude Code loads CLAUDE.md files at the start of every conversation and can read AGENTS.md in their place. Cursor rules can be always-on, glob-scoped, agent-selected or manual.

What works:

  • Versioned with the code, reviewed in PRs, shared by the whole team for free.
  • Zero infrastructure. Nothing to break.
  • Deterministic. You know exactly what the agent sees.

What does not:

  • Every line costs context in every session. So people keep them short, which means history is the first thing cut.
  • They store conclusions, not journeys. "Use the isolated fixture" is a rule. "Retries and timeouts hide this bug" is history, and history does not belong in a rule file that loads on every prompt.
  • Nobody writes them at 6pm after a two-hour debugging session. The moment with the most valuable knowledge is the moment with the least patience.

Even the vendors draw this line. OpenAI's Codex docs say to keep required team guidance in AGENTS.md and treat memories as "a helpful recall layer". Anthropic's docs describe CLAUDE.md as instructions you write and auto memory as notes Claude writes itself. Instruction files are configuration. They are not memory, and they were never meant to be.

Memory banks, ADRs, commits and spec files

This is where I disagree with a lot of people, so I will argue it properly.

Cline's memory bank is a prompt pattern: six markdown files (projectbrief.md, productContext.md, activeContext.md, systemPatterns.md, techContext.md, progress.md). The agent reads all of them at task start and rewrites them when you say "update memory bank". It is a real improvement over nothing, and for a solo developer on one project it can be enough.

ADRs and commit messages are the oldest memory system we have, and the best one for decisions. One team I emailed keeps the why of every change in commit messages and swears by it. They are right that the why belongs in git.

Allium (from JUXT, MIT, .allium files) is a behavioural spec language for agentic engineering: entities plus rules in the form when / requires / ensures, with skills like /elicit (forward from intent), /distill (backward from code), /weed (reconcile spec and code) and /propagate (generate tests). Its own site pitches it as something that "persists between sessions" and surfaces contradictions that markdown lets two requirements hide. It is not YAML, despite looking a bit like it.

My argument against treating any of these as agent memory:

  • They read back what was saved, nothing more. A file cannot notice that the question you are asking now is related to something filed under a different name three months ago. Retrieval is "load all of it" or "hope grep matches".
  • They hold the final state. A memory bank's progress.md says what works. A commit says what landed. An Allium spec says what the system should do. None of them has a place for "we tried X and Y first and here is why they failed", and that is exactly what Bob's agent needed on Thursday.
  • They decay silently. Nothing marks activeContext.md as stale when the code moves on. A wrong line in a rule file is loaded with full authority every session until a human notices.
  • They grow until they are cut. The more you put in, the more context each session burns, so the useful history gets pruned first.

Allium deserves a separate note, because it is solving a different problem well. Intent drift inside a long session is real, and a formal spec that generates tests is a sharper tool than a prose PRD. But a behaviour spec is not a memory of what happened. It will tell the next agent that webhooks must be idempotent. It will not tell it that a retry wrapper already made the flaky test worse. If you adopt it, adopt it as a spec, not as your memory layer.

Where file-based approaches genuinely win: solo developers, small repos, short-lived projects, and anything that must be reviewable line by line in a PR. If that is you, stop reading here and write a good AGENTS.md.

Built-in assistant memory

Claude Code auto memory is on by default in local sessions. Claude writes four kinds of notes for itself (user, feedback, project, reference) under ~/.claude/projects/<project>/memory/, with a MEMORY.md index whose first 200 lines or 25 KB load at every session start. The docs are explicit that it skips anything derivable from the code, "such as architecture, file paths, or debugging fixes". That is a sensible design for preferences, and it also means debugging history is out of scope by design. It is per machine; your teammate's Claude does not see it.

Codex memories are off by default, live under ~/.codex/memories/, are generated in the background once a chat has gone idle, and are described by OpenAI as useful recall that is not guaranteed to load. Again: per machine.

Copilot Memory is the most interesting design of the three. Repository facts are stored with citations to the code that supports them, and before using a memory the agent checks those citations against the current branch. If the code contradicts the memory, the agent is encouraged to store a corrected version. Unused memories are deleted after 28 days. Repo facts are shared with everyone who has Copilot Memory on that repo. The catches: it is GitHub-hosted, it works with Copilot's own agents (cloud agent, code review, CLI), and it launched as a public preview, so check its current status.

Cursor Memories no longer exist. Cursor removed the feature in 2.1 (November 2025) and told users to export memories into rules. One user in that forum thread summed it up: memories were "almost no different than .mdc files".

claude-mem: the most popular, and a recorder rather than a memory

claude-mem had 103,026 stars on GitHub when I checked today, which makes it by far the most starred project in this post. It deserves a careful look.

How it works, from its README, docs and source:

  • Lifecycle hooks (SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop, SessionEnd) send tool execution data to a local worker.
  • A separate observer model reads that activity and writes typed observations. Its own system prompt says it is "a specialized observer tool", that "you are NOT the one doing the work", and that the watched session "does not know it is being observed".
  • Observations have types (bugfix, feature, refactor, change, discovery, decision, plus security types) and concepts (why-it-exists, problem-solution, gotcha, trade-off and others), with a narrative field for "what was done, how it works, why it matters".
  • Storage is SQLite with FTS5 and optional Chroma. Retrieval is session-start injection plus three MCP tools: search -> timeline -> get_observations, a progressive-disclosure pattern that saves tokens.
  • There is an optional TeamBrain shared workspace and hosted providers; the default installer flow offers a hosted observer trial.

What it does well:

  • Zero effort. Install and it starts recording. That alone explains the stars.
  • Progressive disclosure is a genuinely good retrieval pattern: a cheap index first, full details only for the IDs that matter.
  • It does try to capture decisions and gotchas, not just file edits.

Why I do not count it as real memory for coding teams:

  • The narrator is not the actor. The observer sees tool calls and outputs. It does not see the reasoning that made the agent abandon the retry wrapper. It can record "added retry wrapper, then reverted it". It has to guess at "because it masked a shared connection". A summary written from outside the head is still a summary of activity.
  • Recording is not deciding. Nothing in the pipeline asks "was this the conclusion, or just something that happened?" Everything observed becomes an observation, so the next agent gets a timeline, not a verdict.
  • No notion of "this is no longer true". I could find delete endpoints for observations and summaries, but no supersede, validity window or contradiction check. When a decision is reversed, the old observation and the new one sit side by side and the reader has to work out which wins.
  • It is mostly one person's history. The default scope is your sessions on your machine (and by default your current harness). TeamBrain is opt-in and sharing is per person.

If you want a searchable black-box recorder of your own Claude Code sessions, claude-mem is good at that. Just be clear that a recorder answers "what happened" and you still need something that answers "what did we learn".

Personal memory layers: Mem0, Supermemory, MCP memory servers, Basic Memory

Mem0 (Apache-2.0, about 68k stars) is the best known memory layer. You send it conversation turns; an LLM extracts durable facts, deduplicates them, embeds them and stores them. Its own docs show the transform: "Let's use Postgres for this project" becomes Project decision: use Postgres. You can pass infer=False to store text verbatim. Retrieval fuses semantic, keyword and entity signals. Memories are scoped by user_id, agent_id and run_id. The OSS default LLM and embedder are OpenAI models, though both are configurable. OpenMemory, its local MCP server, is being sunset in favour of the Mem0 self-hosted server.

Mem0 is excellent for what it was built for: assistants that need to remember facts about a person across chats. For coding agents the extraction step is the problem. "Project decision: use Postgres" is exactly the sentence that loses the why. Its docs also note that automatic extraction is additive, so contradictions are handled with explicit update or delete calls that your app has to make.

Supermemory (MIT SDKs, about 31k stars) offers a hosted API and, more recently, a local single binary with embedded storage and local embeddings. Two details matter: its docs say the downloadable server binary is built from a separate non-public codebase, and its MCP server is available on the hosted platform only.

The official MCP knowledge-graph memory server (@modelcontextprotocol/server-memory) stores entities, relations and atomic observations in a local JSONL file. It describes itself as "a basic implementation". It is a perfect way to learn how MCP memory works, and a weak production choice: no semantic search, no time, one file.

Basic Memory (AGPL-3.0) keeps knowledge as markdown notes that you and the agent both edit, with observations, wikilinks and semantic search. It is the best of the "markdown, but searchable" options. The AGPL licence and the shift of its team features to a cloud offering are worth noting if you plan to embed or share it.

Graphs and agent-managed memory: Zep, Graphiti, Cognee, Letta, LangMem, palace-rs

Zep / Graphiti brings the most rigorous idea in this space: a bi-temporal knowledge graph. Every fact edge carries when it was true and when the system learned it. When a new fact contradicts an old one, an LLM detects the overlap and the old edge is invalidated, with history kept. Graphiti (Apache-2.0, about 32k stars) is the open framework. Zep is the commercial cloud. Zep Community Edition was discontinued in April 2025. Graphiti's own README is honest about the cost: "You supply the graph database, LLM, and embedder, and you build the service around it: ingestion, tenancy, access control, and operations." It even says "Neither is an agent memory product". If you need temporal reasoning over business data, this is the reference design. If you want your coding agent to stop repeating dead ends this week, it is a lot of building.

Cognee (Apache-2.0, about 33k stars) builds a knowledge graph plus vector index from text, code and conversations, runs locally on SQLite, LanceDB and Kuzu by default, and exposes remember, recall and forget over MCP. It adds a code graph for questions like "what breaks if I change this signature", and a temporal mode that keeps superseded facts. Strong if you want a graph of your codebase; the memory of sessions is a smaller part of what it does.

Letta (formerly MemGPT, Apache-2.0) is agent-managed memory: core memory blocks that are always in the prompt and that the agent edits itself, plus archival memory searched with tools. Self-hosting means a server with Postgres and pgvector. The idea that the agent curates its own memory is right. The catch for coding is that Letta works best when you run your agent inside Letta (including its own Letta Code harness); bolting it onto Claude Code or Cursor gives you less of the benefit.

LangMem (MIT) is a LangGraph library for semantic, episodic and procedural memory with background consolidation. It is a toolkit, not a product. Good if you are already on LangGraph and building your own agent.

palace-rs belongs in this section too, not only with the personal layers. Its repo confirms three things that overlap with the tools above:

  • A temporal knowledge graph. Facts are subject -> predicate -> object triples with valid_from and valid_to. Agents add them with palace_kg_add, close them with palace_kg_invalidate, read them with palace_kg_query (which takes an as_of date for point-in-time questions) and palace_kg_timeline, and palace_conflicts flags facts that look stale or contradictory. Invalidation keeps history, so the timeline shows both the old and the new fact. That is the same core idea as Graphiti's validity windows. The difference: in palace-rs the agent that knows the fact changed records the change explicitly, rather than an LLM pass detecting the contradiction, and it all lives in one local SQLite file instead of a graph database plus an LLM and embedder you wire up yourself. The trade-off is that Graphiti is bi-temporal (it also tracks when the system learned a fact) and does contradiction detection for you; palace-rs relies on the agent, with palace_conflicts as a check.
  • A room graph. Memory is organised into wings (projects or topics) and rooms, and palace_traverse, palace_find_tunnels, palace_create_tunnel, palace_follow_tunnels and palace_graph_stats walk and connect rooms across wings. A "webhooks" room in one project can be linked to the same topic in another, so the next agent can follow it. Cognee's code graph goes deeper on code structure; palace-rs's graph is about connecting memory, not parsing your codebase.
  • Agent-managed memory. The working agent curates its own store through MCP tools: palace_diary_write, palace_kg_add / palace_kg_invalidate, palace_remember and palace_forget, palace_add_drawer / palace_delete_drawer, and palace_check_duplicate before filing. palace_recall_check runs project-memory probes to see whether expected memories are actually found. Hooks inject context at session start, on each prompt and during tool use, and the stop hook asks for a diary entry and decisions if a session did real work and saved nothing. That is Letta's idea (the agent edits its own memory), but delivered as MCP tools and hooks inside the coding agent you already use (Claude Code, Codex, Cursor and others) rather than a separate agent runtime and server. The trade-off: Letta's core blocks are always in context by design, while palace-rs depends on hooks and on agents following the protocol.

So for a coding agent on one machine, palace-rs gives you a temporal graph and agent-managed memory without standing up a graph database, a Postgres server or a new agent runtime. What it does not give you is cross-machine sharing (that is Palace Server), LLM-driven contradiction detection, or Cognee's code-structure graph.

DIY RAG with pgvector or Chroma

Every team with a Postgres instance has thought "we could just embed our docs and chats". You can. One team I talked to did it properly, and it is the most impressive setup in this post (see below). The honest cost: you now own chunking, embedding, ranking, deduplication, staleness, permissions and the hooks that make agents use it. Vector search alone is also bad at exact names and commands, so you end up rebuilding hybrid search. DIY is the right call when memory is your product or your platform team's job. It is the wrong call when you wanted to stop re-explaining the webhook fixture.

palace-rs and Palace Server

Disclosure again: I build these. Here is what the repo and docs confirm, and where they fall short.

palace-rs (MIT, Rust) is local-first memory for one developer's agents. One binary, one SQLite file, local all-MiniLM-L6-v2 embeddings on ONNX Runtime, no API keys. palace install wires it into Claude Code, Codex, Cursor, Gemini CLI, VS Code, OpenCode, Cline, Zed, Goose, Windsurf and Claude Desktop.

What it stores: verbatim "drawers" (chunks of your repo, notes and transcripts, not LLM summaries) organised into wings (projects or topics) and rooms, with tunnels linking rooms across wings; per-agent diaries; standing rules and preferences in general/preferences, injected verbatim at every session start in every project, alongside the current project's own knowledge; and a temporal knowledge graph of facts with valid_from and valid_to (covered in the graphs section above).

Who writes it: the working agent. Hooks inject memory at session start, when you send a prompt, and while the agent greps and reads files. The installed rule tells agents to write a diary entry and record durable facts after substantive work, and a stop hook asks once if a session did real work and saved nothing. Because the agent that did the work writes the entry, "tried retries, tried timeouts, real cause was the shared fixture" can be written by the one party that actually knows it.

Correction: when a fact changes, the agent calls palace_kg_invalidate and adds the new fact, so the timeline keeps both. palace_conflicts surfaces facts that look stale or contradictory, and palace_forget removes drawers. In practice the human is the final judge: you tell the agent what is wrong, and it invalidates and refiles. Agents on the same machine share one palace, so a Codex session can pick up a Claude Code session's diary.

Drawbacks: it only shares across agents on one machine; there is no human approval gate in the code, so a wrong diary entry is stored until someone or something corrects it; quality depends on agents following the protocol; the embedding model is a one-time ~90 MB download; macOS Intel is not supported; and the published LongMemEval numbers (R@5 0.981) measure retrieval recall, not end-to-end answer quality.

Palace Server is the commercial team edition, self-hosted only. Every developer's local palace points at it with palace remote on, so the same MCP tools read and write shared drawers, knowledge-graph facts and diaries. It runs as a Docker Compose starter kit (server plus Postgres with pgvector) or a static binary with your own Postgres, computes embeddings locally, and its Docker image ships the embedding model so it can run with no outbound traffic. It adds roles, per-organisation row-level isolation in Postgres, SSO via OIDC and an audit log of memory writes.

Drawbacks: it is one more server and one more database to run, exactly the objection I heard most (below), and it is not open source.

What we heard from about 400 dev teams

I emailed roughly 400 teams that use coding agents, asking how they handle memory. The honest headline: most were not convinced they needed a memory product. The replies were more useful than the silence, though. Anonymised, here is what came back.

  • "It is already in the repo." Several teams keep decisions and context versioned in git: AGENTS.md, CLAUDE.md, plain markdown. They see no need for a separate server, and for their size they may be right.
  • "One more server to maintain." This was the most common objection by far. Teams are tired of infrastructure that exists to make other infrastructure smarter.
  • "Our agents run on our customers' machines." One team ships agents that execute in customer environments. A Docker and Postgres dependency is a non-starter for them. Claude Code's built-in memory plus CLAUDE.md covers their needs. That is the correct answer for that shape of product.
  • "We built it ourselves." The best setup I saw: versioned markdown decisions and lessons in git with an always-loaded index plus vector search, an agent-to-agent MCP mailbox with acknowledgements, a shared work board with advisory locks so two agents do not grab the same task, the why of every change in commit messages, and one Docker image per developer. It is serious engineering and it works. It is also a platform someone has to maintain.
  • "That is a team problem, and I am one person." Solo developers mostly said memory across teammates is not their problem yet.
  • Commits record the fix, not the traps. The webhook scene above came out of these conversations. fix: isolate webhook fixture connection is a perfectly good commit message, and it still lets the next agent walk straight into the retry wrapper and the longer timeout.

And two lessons from comment threads on my earlier posts, which changed how I think about this:

  • Save the conclusion, not the trace. A commenter pointed out that dumping every failed attempt into memory makes the next agent read a "panic spiral". The useful entry is two lines: what was tried, why it failed, what the cause was.
  • Who writes the conclusion matters. If an agent summarises itself, a wrong conclusion can get saved, which is worse than nothing. You need a way for the human to say "that is wrong" and for the next agent to mark it invalid rather than stack a second version next to it.

Two agents, same bug, three days apart: what each memory option would have told Bob's agent

What works and what does not

What works:

  • Rules in files, history in memory. Every vendor doc and every good team I saw separates the two.
  • The actor writes the lesson. Entries written by the agent that did the work, at the end of the work, beat entries reconstructed by someone watching.
  • Conclusions with their dead ends. "Cause: shared fixture connection. Tried: retry wrapper (worse), longer timeout (hides it)." That one entry saves forty minutes.
  • Facts that can expire. Copilot's citation checks, Graphiti's validity windows, palace-rs's valid_to. Memory without a way to say "no longer true" rots.
  • Automatic recall. If the agent has to remember to search memory, it will forget. Hooks that inject relevant context beat tools that wait to be called.
  • Provenance. Every recalled item should say where it came from and when, so the agent (and you) can judge it.

What does not:

  • LLM extraction for engineering decisions. Turning a debugging session into "Project decision: use Postgres" throws away the reason.
  • Recording everything. Timelines of tool calls are searchable, not instructive.
  • Bigger instruction files. Every line you add is paid for in every session, forever.
  • Cloud memory for teams that cannot send code context out. For many of the teams I emailed, this ruled out half the market before features came up.
  • Building a platform when you needed a habit. If your team is three people on one repo, a disciplined AGENTS.md plus good commit messages beats a graph database.

Decision guide

Decision flowchart: solo or team, can data leave, customer machines, do you need the why and dead ends

Answer these in order.

1. Do your agents run on your customers' machines?
Use the assistant's built-in memory (Claude Code auto memory, Codex memories) plus a tight CLAUDE.md or AGENTS.md shipped with your product. Do not add a server or database dependency to someone else's machine.

2. Are you solo, or is this one person's agents?

  • Small repo, short project, mostly rules: AGENTS.md / CLAUDE.md plus good commit messages. Add a Cline-style memory bank if you like the ritual.
  • You want a zero-effort searchable log of your own Claude Code sessions: claude-mem.
  • You want local memory that keeps the why, the dead ends and corrections, shared by all your agents on your machine: palace-rs.

3. You are a team. Can memory leave your network?

  • Yes, and you are on GitHub with Copilot agents: Copilot Memory, for its citation checks.
  • Yes, and you are building a product that remembers users: Mem0 or Zep cloud.
  • No: keep going.

4. Do your agents need to share the why and the dead ends across developers, with invalidation, on your own infrastructure?

  • Yes, and you would rather run a server than build one: Palace Server. Budget for one server and one Postgres.
  • Yes, and you have a platform team that wants to own it: Graphiti or Cognee as the engine, or the DIY markdown + vector + MCP mailbox setup described above.
  • No, you mostly need shared conventions: versioned rule files are enough. Really.

5. Are you building your own agent rather than using Claude Code, Cursor or Codex?
Letta (agent-managed memory) or LangMem (on LangGraph). Both shine when memory is part of the agent's own loop.

Anti-patterns

  • The 2,000-line CLAUDE.md. If your instruction file reads like a wiki, it is costing you context and it is still not memory.
  • Treating a spec as history. Allium specs, ADRs and memory banks describe the destination. They do not remember the road.
  • The panic spiral. Saving every failed attempt verbatim. Save the conclusion and the named dead ends.
  • Self-graded memory with no correction path. An agent that writes its own conclusions with nobody able to invalidate them will eventually teach the next agent something false, confidently.
  • Two memories at once. Built-in auto memory plus a memory server plus a memory bank, all written by the same agent, means three partial truths. Pick one place for history.
  • Memory nobody reads. A tool the agent must remember to call is a tool it will not call. Check that recall is automatic.
  • Mistaking stars for fit. The most popular option in this post is a session recorder. That is fine if you want a recorder.

Checklist

Before you pick anything, answer these on one page:

  • [ ] Where do rules live, and is that file under ~200 lines?
  • [ ] When an agent fixes something hard, where do the dead ends get written, and by whom?
  • [ ] Can a wrong memory be marked invalid, not just deleted or duplicated?
  • [ ] Does recall happen automatically at session start and on the prompt?
  • [ ] Does every recalled item show its source and date?
  • [ ] Can a teammate's agent see it? Does it need to?
  • [ ] Can this data leave your network? Your customers' network?
  • [ ] Who maintains it in six months?
  • [ ] What happens when it is down? (It should fail open.)

If you only do one thing after reading this: next time an agent finishes a nasty bug, make it write two lines somewhere the next agent will see: the cause, and the things that looked right but were not. Whatever tool you use, that is the part that is missing today.

What does your team do with the dead ends? I am genuinely curious, especially if you have a setup that works without any of the tools above.

Top comments (2)

Collapse
 
maxbuildsdev profile image
Max Kaya •

The dead-ends point is the sharpest thing here — git log only survives if the commit message happens to narrate the failed attempts, which it almost never does. We hit this with a flaky test that three different agents "fixed" with sleeps before someone wrote down that the fixture leaked a shared connection. Two lines in a scratch file beat any of the tools. One thing the checklist nudges at but doesn't resolve: once those why-notes exist, who decides when one is stale? A fix from 6 months ago that no longer applies can be worse than no note at all.

Collapse
 
icegaming profile image
iCe Gaming •

In practice the agent does, but how it decides varies a lot by tool. Most memory layers have no notion of stale at all: a note lives until someone deletes it. The ones that handle it treat staleness as a contradiction, not an age. The agent that hits the flaky test, sees the fixture was fixed and the note no longer matches, closes the old note (valid until that date, linked to the commit that ended it) and records the new state. It isn't deleted, because "this used to flake because X" is still useful history. It just stops being presented as current truth.

One thing that makes this work: a note should name what it depends on (a file, a fixture, a version), so a change there tells the agent to re-check it. Expiring notes by age alone throws away the ones that are still true.