Where ljos fits among agent memory tools

Mem0, Zep, Letta, and most agent memory let a model decide what to keep. A CLAUDE.md file is the exception, and you write it by hand. ljos keeps only what you tell it to keep. That one choice explains most of the table below, including where ljos is behind.

Which to pick

Mem0, Graphiti and Letta suit memory that builds itself from conversations, with a model doing the extraction. A CLAUDE.md or AGENTS.md file is enough when one page of standing notes covers it. A plain retrieval index over your documents answers questions about those documents. ljos fits when each memory should be a sentence someone chose to write, kept in local files and searched back per prompt, next to a rule check on shell commands and a ticket tracker.

Side by side

How each tool writes, stores and returns memory, from each project's own documentation in October 2026.
ljosMem0Graphiti (Zep)LettaPlain retrieval indexCLAUDE.md file
Who writes a memoryYou, by saying Remember: or Prefer:. A lesson an agent drafts waits until you accept it.A model extracts facts from each conversation you pass to add().A model extracts entities, relations and their validity dates from each episode.The agent edits its own memory files with tools; background subagents can consolidate from conversations.Whatever you index.You, or the agent when asked.
The unitOne claim, two sentences at most, with its kind, age and review date.An extracted fact, with vectors and linked entities.A temporal graph of entities and facts, traced to source episodes.Markdown files in a git repository.Chunks and their embeddings.One Markdown file.
How it comes backSearched per prompt: BM25+, plus a local encoder when installed, fused.Semantic, keyword and entity search, fused.Semantic, keyword and graph search.Some files sit in every prompt; the agent reads the rest on demand.Top-k by similarity.The whole file, every session.
Model needed to writeNo.Yes; gpt-5-mini by default.Yes; OpenAI by default.The agent's own model.An embedding model.No.
Where it livesLocal files and a loopback daemon.Your vector store, or the hosted platform.A graph database (Neo4j, FalkorDB, Neptune), or Zep's cloud.A Letta server, Letta Cloud, or your git remote.Your index.Your repository.
Shell command checkYes: fixed rules plus yours, before each command.Not part of a memory layer. Use the runner's own permissions.
Work trackerYes: vissue, plain Org files in git.Not included.
LicenceMIT (claimdag: Apache-2.0 OR MIT)Apache-2.0Apache-2.0Apache-2.0DependsNone needed

Where ljos is behind

  • Retrieval accuracy. On LongMemEval_S session retrieval the fused arm reaches recall@5 0.949. A public neighbour reports 95.2% R@5 on the same protocol, so the two are level. The lexical arm scores 0.568 on MemoryAgentBench accurate retrieval, below the published BM25 row of 0.605 (that row used GPT-4o-mini as the reader; ours used a local 7 B model). The measured rows and where the data is.
  • Changing facts. Graphiti keeps a validity window on every fact. ljos closes an earlier lesson only when a new one opens with the same words, and scores 0.395 on MemoryAgentBench conflict resolution at 262K tokens. The measured row and where the data is.
  • Question answering. Those scores come from a local 7 B reader. Its answer accuracy on LongMemEval_S is 0.549 against a 0.634 ceiling for perfect sessions. Projects that use a hosted reader and judge report higher answer accuracy (one on the compare page reports 96.20%); the protocols differ, and we have not run a hosted model.
  • It forgets what nobody said. Answers can only use what was written, and nothing is extracted from the conversation. If you never say Remember:, the next session starts without it. That is the point, and it is also a cost.

What we think is new

The parts all have neighbours: hybrid retrieval, review schedules, ticket trackers, command filters. What we have not found elsewhere is the combination with provenance kept on every write: memory written only by declaration, no model in the write path, lessons an agent drafts held until you accept them, and artefacts recorded as hashed deeds the tracker cites.

Tools that build memory from transcripts can be poisoned by text that reaches the transcript, such as a web page or a tool result. Writing only on declaration should resist that. We have not yet measured it; that test is the next piece of work, and the results will go on the compare page when they exist.

Sources: each project's README and documentation (Mem0, Graphiti, Letta), read on 10 October 2026. Corrections are welcome as issues.