NapMem: an agent's memory isn't retrieved, it's navigated

NapMem: an agent's memory isn't retrieved, it's navigated
62.74average with a trained 9B model (59.85 for the untrained 397B)
4levels in the memory pyramid
5tools to move through it
3.97 → 2.15calls per question after training
Your agent shouldn't receive memories: it should navigate them (NapMem, Alibaba)
I also explain it in this video, on my Articulator EN channel.

An example: which came first?link

The paper opens with a very clear example. A user asks: "Which did I get first, the Samsung Galaxy S22 or the Dell XPS 13?". A classic memory system searches and hands the agent two notes: the user owns both devices, and they bought the Galaxy S22 on February 20th. There's no date for the laptop. With that, the only thing the agent can answer is "I don't know".

The memory system hands the agent two notes about the Galaxy S22 and the Dell XPS 13, and the agent answers "I don't know".
Passive retrieval: the agent only sees what it's given.

Now give the same agent memory tools. It no longer waits to be handed anything: it searches the conversations itself and finds two messages. The Dell was pre-ordered on January 28th but arrived on February 25th; the Galaxy came on the 20th. The correct answer is the Galaxy S22, and the trap was the pre-order date.

The agent searches the conversations, finds the Dell pre-ordered on January 28 and delivered on February 25 and the Galaxy on February 20, and answers that the Galaxy S22 came first.
Active navigation: the agent searches until it has enough evidence.

That difference, receiving versus searching, is the whole paper.

The problem with passive retrievallink

Agents no longer live in a single conversation: they stay with us for weeks, at work, while we study or in our daily lives, and for that they have to remember us. The hard part is that what they know about a user comes in many kinds, and every future question needs a different memory, so a fixed way of storing and querying memory falls short.

So far, memory has been improved from two sides:

Construction

Finer categories and vector, graph, hybrid or hierarchical stores: Mem0 keeps compact records, Zep builds a temporal knowledge graph, MemOS treats memory as a system resource and MemoryOS splits it into short, mid and long term.

Retrieval

Searches that reflect on what they found, personalized queries for each user and better reranking of results, sometimes trained with reinforcement learning (Search-R1, DeepRetrieval, RMM).

But in almost all of them, accessing memory is a system function, a pipeline designed in advance. No matter how you store memory, as a list, a graph, vectors or a hierarchy, in the end it's reduced to a chunk of context that someone else picks and hands to the agent. If that chunk is incomplete, the agent can't go and look for more. It is, as the authors put it, a consumer of pre-selected evidence.

Memory as an action spacelink

The proposal is to flip that around: memory becomes a structured action space. The agent gets memory tools and decides three things:

  1. Whether it needs memory for this question.
  2. Which level of detail to consult.
  3. Whether what it has found is enough to answer.
Active navigation: the agent decides whether it needs memory, which level to consult and whether what it found is enough to answer.
Active memory navigation: hence the name, NapMem.

They call it active memory navigation, and the difference from other work that also trains memory policies is where the focus lies: not on what to store or when to delete, but on how to use memory at answer time, picking the level and refining based on what it finds along the way.

The memory pyramidlink

NapMem builds a pyramid for each user with four levels. They all tell the same story, each at a different level of abstraction, like a map you can see as a whole or zoom into a single street.

NapMem's memory pyramid: raw conversations at the base, memory records above, then topic tracks and the user profile at the top.
Four levels: from the exact detail to a summary of who you are.

1. Raw conversations

The base stores every message as it is, with its content, who said it, when, the session and a unique identifier to look it up exactly. This layer only grows: it's never rewritten. It's the highest-fidelity evidence, the one the agent checks when it needs the fine detail.

2. Memory records

The second level is compact sentences that strip away the chatter and keep what's useful. There are four types: facts, events, instructions and preferences. Each record carries its identifier, type, text, date and the identifiers of the messages it came from; that link lets you go from a summarized memory back to the original conversation.

A memory record with its type, text, date and the identifier of the message it came from, linked back to the original conversation.
Every record points to the messages that back it up.

They're created in two steps. First, after a few turns of conversation (the batch grows from 1 to 2 to 4 turns and then stays at 5), the model extracts new records from the recent messages. Then it compares them with what it already had, using hybrid search, and chooses what to do with each one: store it, skip it if it's redundant, update an old one if something changed, or merge them if they describe the same thing. When updating or merging, the union of sources and timestamps is kept.

Reconciling a new record with the existing ones: store, skip, update or merge, keeping every source.
Extract and reconcile: memory doesn't pile up duplicates.

3. Topic tracks

A record is an isolated fact, but many things about a person evolve over weeks: a project, a hobby, a relationship. Each topic track is a Markdown file with metadata, a summary, the story of that topic and an evidence section linking the records that back it up. There are at most 20 tracks, and the agent decides whether to update one, merge two or start a new one. Writes are validated before they're committed; if the format fails, they're rolled back.

A Markdown topic track with its summary, its story and the list of records that back it up.
A track follows a topic across many sessions.

4. The user profile

At the top sits the profile: a global summary of who the user is, their long-term preferences and how they like to interact. It's capped at 2,000 characters, so it gets revised instead of growing. And it can only use what the topic tracks say: if there's no evidence, the field stays empty rather than making something up.

The profile.md file with who the user is, their preferences and how to interact, with a 2,000-character counter.
The profile is revised, not grown.

How it's builtlink

The pyramid is built from the bottom up, little by little, replaying the user's sessions in chronological order. Each new session is added to the conversations, records are extracted from it, and the changes flow upward: tracks are revised before a new session if records are pending, at date boundaries, or when more than 20 new records have piled up; the profile, after the tracks are updated or when there are more than 50.

The two lower levels are structured JSONL records with vector and keyword indexes, to search by meaning and to fetch something exact by its identifier. The two upper levels are Markdown files that are read as they are. And everything stays linked: from the profile to the tracks, from the tracks to the records and from the records to the messages.

The pyramid is built bottom-up: the two lower levels with vector and keyword indexes and the two upper ones in Markdown, all linked together.
Everything stays linked, like the strings on a detective's board.

The five toolslink

To move through the pyramid, the agent has five tools, each designed for a level:

ToolInputWhat it does
search_conversationfree textSearches raw messages and returns the top 5 snippets
search_recordsfree textSearches the records and returns the top 5
get_conversationlist of message idsFetches exact messages by identifier
get_recordslist of record idsFetches exact records by identifier
read_filefile nameReads a topic track or profile.md

The two search tools are hybrid: they mix keywords and vectors with reciprocal rank fusion (RRF, with k = 60), on top of Qwen3-Embedding-0.6B embeddings. The exact-access tools use identifiers returned by earlier calls, and the file reader gives access to the more abstract levels.

The five memory tools attached to their level of the pyramid: search, exact access and file reading.
Two for searching, two for exact access and one for reading.

With that, navigation can go top-down (start from the profile or a track, narrow down with the records and drop to the conversation to verify the evidence) or bottom-up (search for a detail and, if it doesn't show up, climb to a summary). At each step the agent looks at what it has found and decides its next action, or whether to stop and answer. Formally, at step t it picks an action given the question, the pyramid and what it has seen so far, and the trajectory ends with the answer.

Top-down navigation, from the profile to the conversation, and bottom-up, from a detail that doesn't show up to a summary.
Go down to verify, go up to understand.

The example from figure 2 of the paper: "What console does Nate own?". The agent first reads Nate-Entertainment.md, which mentions Cyberpunk 2077 and Xenoblade Chronicles. It searches the conversations with search_conversation("Nintendo Switch PS5 Xbox console") and finds that Nate is a big Nintendo fan. Then it fetches the exact record with get_records: he's playing Xenoblade Chronicles, a fantasy RPG. It reasons and answers: a Nintendo Switch. Three steps across three different levels.

What console does Nate own? read_file, search_conversation and get_records lead to the answer Nintendo Switch.
Three steps, three levels.

There's a limit: at most four tool steps per question; going over counts as a wrong answer. And the prompt is clear: don't guess anything about the user; if two memories contradict each other, instruction records take priority; use raw conversations when you need exact evidence; and stop searching as soon as you have enough evidence, without chasing marginal details. The final answer is JSON with the answer and the reason.

Learning to navigate: the rubric and GRPOlink

Having tools isn't enough: you have to know how to use them. That's why they train the agent with reinforcement learning. Each example is a question that needs memory, along with that user's pyramid; the agent answers with its chain of calls and only gets a score at the end, for the outcome. That score trains both the answer and every navigation decision that led to it.

The score follows a rubric with three binary criteria: valid format (F), correct answer (C) and memory use (U):

CaseFCUScore
Right, using memory111+1
Right, without memory1100
Wrong after checking memory101−0.5
Wrong without checking100−1
Broken format (or over budget)0––−1

So searching and being right is rewarded, and making things up is punished harder. Since every training question needs memory, getting it right without checking memory doesn't score.

The reward rubric: +1 if right using memory, 0 if right without it, −0.5 if wrong after checking it and −1 if wrong without checking or with a broken format.
Searching and being right is rewarded; making things up is punished harder.

The algorithm is GRPO (Group Relative Policy Optimization). For each question, four attempts are generated, and each attempt's advantage is its score minus the group's average: attempts above the average are reinforced and the ones below are penalized. There's no need for a separate model to judge every step: the group itself is the reference. The advantage applies to every token of the attempt, including the tool-call tokens, with the usual clipped objective and a KL penalty against the starting model.

Four attempts scoring +1, −0.5, −0.5 and +1; the group average is 0.25 and each attempt's advantage is its score minus that average.
Each attempt's advantage: its score minus the group's average.

If you want to reproduce it, the hyperparameters from the appendix: Qwen3.5-9B as the base model, batch size 8, groups of 4 attempts, learning rate 1×10⁻⁶, KL coefficient 0.001, no entropy term, bfloat16, 5 epochs and up to 5 assistant turns, with the verl framework on NVIDIA H20 GPUs.

Training and evaluationlink

They train on questions from two benchmarks, LoCoMo and PersonaMem-v2, splitting by user (60% for training, 20% for validation and 20% for testing) so no one shows up on both sides. The third, LongMemEval, is never seen during training: it's there to check whether what was learned works outside familiar ground. LoCoMo and LongMemEval measure factual memory (recalling something from long ago, changes over time, reasoning across sessions); PersonaMem-v2, implicit preferences. The test sets have 1,315 LoCoMo questions, 100 LongMemEval questions and 911 PersonaMem-v2 questions.

They compare it against five memory systems: Mem0 (flat vector memory), Zep (temporal graph), MemOS (a memory operating system), MemoryOS (hierarchical memory) and AgeMem (agentic memory trained with RL), all on the same Qwen3.5-9B. NapMem and AgeMem get at most four tool steps and each search returns up to 5 items; non-agentic systems are allowed up to 20 per search.

For open-ended questions the judge is Claude Opus 4.6. They checked its reliability on 100 answers labeled by three people: it agrees with the human majority 99% of the time (precision 1.0, recall 0.98, Cohen's κ 0.98). The only disagreement was a "0 times" the judge marked wrong when the expected answer was that it was never mentioned. All results are averaged over three seeds.

The resultslink

Table 1 of the paper (L-J is the judge's score; the average combines the LoCoMo and LongMemEval judge scores with PersonaMem-v2 accuracy):

SystemLoCoMo F1LoCoMo L-JLongMemEval F1LongMemEval L-JPersonaMem-v2Avg.
Mem041.1960.8653.8678.0038.8959.25
Zep36.0952.2152.6173.3336.3353.96
MemOS35.2255.8239.1654.3337.5849.24
MemoryOS31.4044.2822.6823.6735.8234.59
AgeMem38.0045.0237.8351.3324.1940.18
NapMem-122B (untrained)35.3951.6948.8670.0041.3854.36
NapMem-397B (untrained)38.3154.4253.8578.3346.1059.85
NapMem-9B w/ RL41.2859.9257.4180.3347.9762.74
Bars with the average of the three tests: NapMem 62.74, Mem0 59.25, Zep 53.96, MemOS 49.24 and MemoryOS 34.59.
The average across the three tests.

Trained NapMem gets the best average, 62.74, versus 59.25 for the best rival, Mem0. On LongMemEval, the test it never saw in training, it reaches 80.33, the best of them all; on PersonaMem-v2, 47.97, also in the lead.

On LoCoMo it doesn't win everything, and that's worth saying: it has the best F1 (41.28 vs 41.19), but on the judge's score Mem0 is one point ahead (60.86 vs 59.92). In other words, on factual memory over long conversations it's on par with the best; where it pulls ahead is personalization and data it never saw during training.

Trained 9B vs 397Blink

The most striking part of the table is the two rows in the middle. They tried the same pyramid and the same tools with much bigger models, untrained: Qwen3.5-122B and Qwen3.5-397B. The biggest averages 59.85; the small 9B model, trained, 62.74. Learning how to use memory is worth more than making the model forty times bigger.

Circles proportional to parameter count: the trained 9B model scores 62.74 versus 54.36 for the untrained 122B and 59.85 for the untrained 397B.
A model 44 times smaller, but trained to search.

When memory isn't neededlink

What if the question doesn't need memory at all? To check that training doesn't turn it into an agent that checks memory for everything, they gave it three unrelated tasks (science with GPQA-Diamond, function calling with BFCL-v3 and visual search with V*Bench) with a random pyramid and every memory tool switched on:

BenchmarkMetricBase modelNapMem-9B w/o RLNapMem-9B w/ RL
GPQA-DiamondAccuracy53.0355.7457.58
GPQA-DiamondMemory calls–34.51%6.90%
BFCL-v3Task / tool / exec95.00 / 97.50 / 93.5093.50 / 97.50 / 94.0095.00 / 97.50 / 94.50
BFCL-v3Memory calls–0%0%
V*BenchAnswer84.8289.5391.10
V*BenchMemory calls–0%0%

Untrained, the model checked memory on 34.51% of the science questions for no reason; trained, on just 6.90%. On the other two tasks, never. And it doesn't lose ground: it even improves a bit in science and in the visual test. Reinforcement learning calibrates when to use memory; it doesn't just use it more.

On science questions, unnecessary memory calls drop from 34.51% to 6.90%; on function calling and visual search they stay at 0%.
Trained, it almost never checks your memory when it doesn't need to.

The cost: space and timelink

A user's memory never stops growing, so a small footprint matters. Across the three benchmarks, NapMem takes up 4.83 GiB, less than almost everyone despite storing four levels:

SystemPersonaMem-v2LongMemEvalLoCoMoTotal
NapMem0.694.010.124.83
Mem01.408.900.1410.44 (×2.16)
MemOS3.6118.850.6423.10 (×4.78)
Zep3.5010.000.6014.10 (×2.92)
MemoryOS1.984.300.406.68 (×1.38)
AgeMem0.342.560.092.99 (×0.62)

Only AgeMem uses less, with its light flat memory, but it performs far worse (40.18 on average). Size alone doesn't tell the whole story.

Total storage in GiB: NapMem 4.83, Mem0 10.44, Zep 14.10 and MemOS 23.10; AgeMem takes 2.99 but performs far worse.
Four levels and still less than half of Mem0.

And response time. On a hundred PersonaMem-v2 questions, latency grows almost in a straight line with the tokens the model generates: the more it writes, the longer it takes. Passive systems receive lots of text and reason over all of it; NapMem searches for what it needs and stops as soon as it has evidence, so it writes less and answers sooner, even though it uses tools.

Scatter plot of latency versus generated tokens: almost a straight line, with NapMem clustered at the bottom left and passive systems with points far up to the right.
Writes less, answers sooner. Redrawn from figure 3.

Which piece matterslink

To see which part gives the edge, they removed pieces one at a time (judge score on LoCoMo and LongMemEval, accuracy on PersonaMem-v2):

VariantLoCoMoLongMemEvalPersonaMem-v2Avg.
Full NapMem59.9280.3347.9762.74
Without reinforcement learning52.0972.3320.7548.39
Without navigation (passive retrieval)48.3768.0045.8854.08
Records-only tools39.7760.0035.0244.93
Without upper levels (no tracks or profile)49.1375.0038.2054.11
Ablation bars: full 62.74, without navigation 54.08, without upper levels 54.11 and records only 44.93.
Removing any piece costs between 8 and 18 points.

All three pieces add up. Navigating beats receiving, even with the same memory available. The summaries on top complement the detail below. And using memory well is learned: without reinforcement learning, with the same pyramid and the same tools, the average drops to 48.39, and on PersonaMem-v2 it collapses from 47.97 to 20.75. Explaining it in the prompt isn't enough.

How it navigateslink

They looked at the first tool each model reaches for. The 9B models almost always start with the records (92.16% untrained, 88.84% trained). The big ones, on the other hand, start by reading files in almost half of the cases (44.38% for 122B and 46.60% for 397B). One possible explanation from the authors: big models digest a long summary better, while small ones prefer short, targeted evidence.

Heatmap of the first tool: the 9B models start with records about 90% of the time; the 122B and 397B models read files in almost half of the cases.
Each model's first tool. Redrawn from figure 4.

And reinforcement learning changes how it searches. Untrained, the 9B model made 3.97 calls per question; trained, 2.15, and it's still more accurate: out of every hundred results the tools return, 34.92 are useful evidence, compared with 20.66 before. It doesn't stick to a single level: 79.63% of questions still use several (80.39% before training). It has learned when to stop.

One success, one failurelink

The success. Question: "What state did Nate visit?". search_conversation("Nate visit state travel") turns up nothing useful; search_records(...) returns irrelevant or vague records. So the agent reads the track Nate-Identity-Interests.md, and there it is: Nate traveled to Tampa beach on November 11, 2022. Answer: Florida. Climbing to a more abstract level rescued what direct search couldn't find.

What state did Nate visit? Searching conversations and records fails; the topic track says he traveled to Tampa beach and the agent answers Florida.
When search fails, the summary finds it.

The failure. Someone asks for calm ideas for the weekend. The agent finds a record: the user thought about booking salsa for a charity gala because it had worked the year before. It finds another: they get energized at packed events but need time alone afterward. And it picks the option that assumes they love going salsa dancing every weekend. It turned a one-off event into a stable preference: the memories were relevant, but not strong enough for that conclusion. The authors flag it as future work: calibrating how much each memory actually proves.

An event record about salsa at a charity gala is wrongly turned into the preference "loves salsa dancing every weekend".
Event ≠ preference.

Limitationslink

The authors point out three themselves:

  • The benchmarks don't capture every real form of personalization or open-ended conversation.
  • Privacy and forgetting, two key requirements for any system that remembers things about people, aren't fully addressed.
  • Model size: how the memory-access strategy changes with scale still needs a proper study.

A curiosity: in the implementation appendix another name slips through, "PyraNav", most likely an earlier name for the method.

Wrap-uplink

NapMem stores the user's memory in a four-level pyramid (conversations, records, topic tracks and profile) and trains the agent with reinforcement learning to move through it with five tools, instead of receiving what someone else picks. That way, a 9B model beats an untrained 397B one, searches less, gets more right and almost never checks memory when it doesn't need to.

In one sentence

An agent's memory works better as a place it moves through than as a chunk of context it's handed.

What would you want your assistant to remember about you?

Sourceslink

Continue reading

Last posts -->

Have you seen these projects?

Gymnasia

Gymnasia Gymnasia
Expo
React Native
TypeScript
OpenAI
Anthropic

Fitness app with two agents that run entirely on the device, with no backend, so the user's data never leaves the phone. A BYOK conversational coach with local tools and a remote system prompt with offline fallback, plus a food estimator that pulls macronutrients out of a photo of the plate, with barcode scanning against OpenFoodFacts.

LangGraph Deep Researcher

LangGraph Deep Researcher LangGraph Deep Researcher
Python
LangGraph
FastAPI
React
TypeScript
Docker

Multi-agent research system built with LangGraph. A supervisor breaks your question down into topics and launches search sub-agents in parallel; each one compresses its findings before handing them to a writer agent that produces the final sourced markdown report. Live streaming over WebSockets, a configurable model per role and bring-your-own API keys that are never persisted server-side.

Tau

Tau Tau
Python
LangChain

Multi-agent tutoring system for secondary school students, with one agent per subject and course material written and validated by a team of teachers. It was used with real students at a private school in Spain and at a secondary school in Colombia.

View all projects -->
>_ Available for projects

Do you have an AI project?

Let's talk.

maximofn@gmail.com

Machine Learning and AI specialist. I develop solutions with generative AI, intelligent agents and custom models.

Do you want to watch any talk?

Last talks -->

Do you want to improve with these tips?

Last tips -->

Use this locally

Hugging Face spaces allow us to run models with very simple demos, but what if the demo breaks? Or if the user deletes it? That's why I've created docker containers with some interesting spaces, to be able to use them locally, whatever happens. In fact, if you click on any project view button, it may take you to a space that doesn't work.

Flow edit

Flow edit Flow edit

FLUX.1-RealismLora

FLUX.1-RealismLora FLUX.1-RealismLora
View all containers -->
>_ Available for projects

Do you have an AI project?

Let's talk.

maximofn@gmail.com

Machine Learning and AI specialist. I develop solutions with generative AI, intelligent agents and custom models.

Do you want to train your model with these datasets?

short-jokes-dataset

HuggingFace

Dataset with jokes in English

Use: Fine-tuning text generation models for humor

231K rows 2 columns 45 MB
View on HuggingFace →

opus100

HuggingFace

Dataset with translations from English to Spanish

Use: Training English-Spanish translation models

1M rows 2 columns 210 MB
View on HuggingFace →

netflix_titles

HuggingFace

Dataset with Netflix movies and series

Use: Netflix catalog analysis and recommendation systems

8.8K rows 12 columns 3.5 MB
View on HuggingFace →
View more datasets -->