cd /news/artificial-intelligence/mem0-vs-zep-vs-langchain-memory-vs-l… · home topics artificial-intelligence article
[ARTICLE · art-112311] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

Mem0 vs Zep vs LangChain Memory vs Letta: Which One Actually Remembers?

A developer's comparison of AI memory tools Mem0, Zep, LangChain Memory, and Letta reveals that real memory requires conflict resolution, not just retrieval. Mem0 uses a two-stage LLM call to add, update, or delete facts, while Zep's Graphiti engine uses bi-temporal graphs to track changes over time. LangChain's memory classes are building blocks that leave conflict resolution to the developer.

read5 min views1 publishedAug 26, 2026

Most "AI memory" demos are a vector store with a marketing label. You embed every message, cosine-search the top-k on the next turn, and call it memory. It works until turn 40, when the agent confidently tells a user their favorite color is blue because that's what came back highest-ranked — even though they corrected it three messages later.

Real memory isn't retrieval. It's deciding what's still true. That distinction is why four very different architectures — Mem0, Zep, LangChain's memory classes, and Letta (formerly MemGPT) — all claim the same territory but solve almost none of the same problems. Here's what each one actually does under the hood, where it breaks, and which one you should reach for.

ConversationBufferMemory

, ConversationSummaryMemory

, ConversationKGMemory

, VectorStoreRetrieverMemory

— these are building blocks, not a memory service. You own the extraction logic, the storage schema, and every decision about what gets kept or discarded. ConversationSummaryMemory

re-summarizes the whole history on every turn, which means cost and latency grow with conversation length even though the output size doesn't. ConversationKGMemory

extracts triples but has no mechanism to invalidate a triple once a new fact contradicts it — old and new coexist in the graph, and retrieval has no way to prefer one.

This is fine if you want full control and are building something bespoke on top of LangGraph's checkpointing. It's the wrong choice if you want memory to just work, because "just work" is precisely the part LangChain leaves as an exercise for you.

Use it when: you're already deep in LangGraph, you have specific extraction logic you don't want a black box making decisions about, and you're willing to build conflict resolution yourself.

Mem0's core loop is a two-stage LLM call. First, an extraction pass pulls candidate facts out of a message ("user prefers dark mode," "user is allergic to shellfish"). Second — and this is the part most memory layers skip — a second LLM call compares each candidate against the existing memories for that user and decides: ADD (net new), UPDATE (same entity, changed value), DELETE (contradicted), or NOOP (already known). That decision is what stops the shellfish-allergy memory from sitting next to a stale "user eats shrimp regularly" memory forever.

from mem0 import Memory
m = Memory()
m.add("I used to like coffee but I've switched to tea", user_id="u1")

Memories are stored as embeddings in a pluggable vector store (Qdrant, Chroma, pgvector, Weaviate) with metadata, and Mem0 added a graph layer (Neo4j-backed) for relationship queries — "who does the user report to" style facts that a flat vector store handles badly. Addition is async by default, so it doesn't block your response path, which matters if you're calling add()

after every turn in a latency-sensitive chat app.

The honest tradeoff: the conflict-resolution LLM call is an extra hop with extra cost and extra latency on the write path, and if your extraction prompt is too aggressive you'll get memory bloat — hundreds of low-value "facts" that dilute retrieval quality. Mem0 gives you knobs (custom extraction prompts, memory-type separation) but you still have to tune them.

Use it when: you have a multi-session, multi-user product (support bot, personal assistant, CRM copilot) where facts genuinely change over time and you need automatic reconciliation instead of a growing pile of contradictions.

Zep's differentiator is Graphiti, its temporal-graph engine. Instead of choosing between "keep the old fact" or "overwrite it," Zep timestamps edges with both event time and ingestion time (a bi-temporal model) and marks superseded facts as invalid rather than deleting them. Ask Zep "where did the user work in 2023" and it can answer correctly even after the user has since changed jobs, because the graph retains history instead of collapsing to a single current value.

This is genuinely different from Mem0's ADD/UPDATE/DELETE model — Zep never deletes, it invalidates, which means you get an audit trail for free. That's valuable for compliance-sensitive domains but it's overkill if you only ever care about the current state of a fact and don't need to reason about when it changed.

Use it when: you need point-in-time correctness — support timelines, longitudinal user profiles, anything where "what did we believe was true at time X" is a real query, not just "what's true now."

Letta flips the architecture entirely. Instead of an external pipeline deciding what to remember, the LLM agent itself gets memory-editing functions (core_memory_append

, core_memory_replace

, archival_memory_insert

) as tools it can call mid-conversation. Context is split into an OS-style hierarchy: core memory (small, always in the prompt, directly editable), and archival/recall memory (external, paged in via search when relevant). The agent decides, at inference time, what's worth writing down and what's worth paging back in.

The upside is nuance — the agent can decide "this is important enough for core memory" versus "this is archival trivia" based on actual conversational context, not a fixed extraction heuristic. The downside is cost and predictability: every memory operation is now an extra tool call inside the agent's own reasoning loop, which adds latency and makes memory writes non-deterministic across runs. Debugging "why didn't it remember X" means inspecting the agent's tool-call trace, not a pipeline log.

Use it when: you're building a long-running autonomous agent (not a request/response chatbot) where memory management is itself part of the task the agent should reason about — not a side effect you want abstracted away.

Need Reach for
Full control, already on LangGraph LangChain memory primitives
Multi-user product, facts change, want automatic reconciliation Mem0
Need to know what was true when, audit trail
Zep
Autonomous long-running agent, memory as part of the task Letta

The question to ask before picking any of these isn't "which has the best retrieval." Retrieval is the easy 20%. It's "who decides when a memory is wrong, and how do they find out." A vector store with no conflict resolution will happily retrieve a stale fact with high cosine similarity and hand it to your agent with total confidence. That's not memory — that's a very expensive way to remember things incorrectly.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @mem0 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/mem0-vs-zep-vs-langc…] indexed:0 read:5min 2026-08-26 ·