Research

How AI agent memory actually works: the four problems every system has to solve

The word "memory" covers three different things: the context window, retrieval over a corpus, and durable facts that persist across sessions. They fail differently, and most products build one and call it memory. Here is the full picture, and the four problems any system has to solve.

10 min read

The most common complaint about AI agents is that they forget. It is also the least precise. "It forgot" covers a chatbot that lost the thread halfway through a long session, an assistant that could not find a detail in a document you uploaded last week, and a tool you have told three times how you want dates formatted that keeps using the wrong one. Those are three different failures in three different systems, and fixing one does nothing for the other two.

This confusion is not just semantic. It is why two products that both advertise memory can behave nothing alike, and why buyers evaluating them end up comparing marketing copy instead of mechanisms. This piece separates the three things that get called memory, explains which failure belongs to which, and then works through the four design problems any real memory system has to solve.

Three things people call memory

MechanismWhat it holdsLifespanFails as
Context windowThe working set for this turn: conversation so far, files read, tool outputOne turnDrift, then overflow
RetrievalPassages pulled from a document corpus at question timePer questionWrong passages, or none
Durable memoryFacts about you and your work that persistIndefiniteNever learned, or never recalled

The context window is not storage at all. It is finite working space, and everything the model can actually use on a given turn has to fit inside it. Retrieval, usually discussed as RAG, searches a corpus you supplied and returns passages that become evidence for an answer. Durable memory holds what stays true about you across sessions: your role, your conventions, the things you should not have to repeat.

The reason to keep these separate is traceability. A claim sourced from a document is checkable against that document. A preference applied from memory is not a claim at all, and should not be cited as though it were. Blending everything into one undifferentiated context makes it impossible to tell which is which, which means it is impossible to check the answer. We keep these as three distinct sources for exactly that reason.

Why "it forgot" is usually a context problem

Most forgetting reported by users is the first row of that table, and it has nothing to do with whether the product has a memory feature.

As a context window fills, the model loses reliable access to the instructions you gave at the start. It leans on stale tool output, drifts toward side goals, and starts answering a question adjacent to the one you asked. The critical detail is that this degradation begins well before the hard token limit rather than at it. There is no error, no warning, and no visible transition. The agent looks fine and is running on a context that no longer holds the thread.

Tool-heavy runs hit this hardest. A single raw page snapshot or operator screenshot can cost more context than dozens of turns of actual reasoning, and it is almost never needed a few steps later. An agent that reads forty files and runs a dozen checks accumulates enormous tool output, most of it dead weight within minutes. This is one of the failure modes behind the industry's roughly 90 percent rate of agent projects that never reach production, covered in why most AI agents fail in production.

The fix is not a bigger window. It is active management of the one you have: pruning heavy artifacts unconditionally, clearing stale tool bodies before spending a model call on summarization, and summarizing only when the cheap steps were not enough. Cheapest and least destructive first, expensive and lossy last.

That is the context half. The rest of this piece is about durable memory, which is where the four problems live.

Problem one: deciding what to store

Every memory system faces the same first question, and the answers cluster at two bad extremes.

Store only what the user explicitly asks you to store, and the system is reliable but nearly empty, because it requires the user to notice a preference, decide it is worth persisting, and take an action. Most people never do. Store everything the user says, and retrieval degrades under the volume, because the useful facts are now buried among a thousand incidental ones.

The signal worth designing around sits in between: corrections. When you tell an agent it got something wrong and state what right looks like, you have handed over the single highest-value training moment available. You identified a specific wrong behavior, you specified the correct one, and you did it in context. Nothing a settings page collects comes close.

The distinction is between a tool that remembers what you typed into a preferences form and one that remembers being told it was wrong. Correcting the agent once should be sufficient to teach it, and you should not also have to go write the lesson down somewhere. That is why our third memory layer captures corrections as events and proposes durable memories from them, without you operating anything.

Problem two: deciding where it lives

The second problem is scope, and most products get it wrong by having exactly one bucket.

Some facts belong to a project. The conventions for this case, the output format this client expects, the paths that matter in this repository, the things never to touch without asking. These are worthless in a different project and actively harmful if applied there.

Other facts belong to you. Your role, how you like results presented, the domain you work in. These should follow you into every project and across every surface you use, whether that is a browser tab, a desktop app, or a terminal.

A single bucket forces a bad trade. Scope everything to the project and you re-teach the tool who you are every time you start something new. Scope everything to the account and project-specific rules leak into work where they do not apply.

There is also a question of custody that vendors rarely raise. Project memory should be plain files on disk that you own, can open in any editor, can diff, and can check into version control alongside the code. Ours lives in .perch/PERCH.md for the project manual and .perch/memory/*.md for individual facts, one per file. Nothing about it is hidden, and nothing requires our UI to read. Account-level memory necessarily lives in a service, because following you across surfaces is the entire point, but the project layer has no such excuse.

Problem three: finding it again

Storage is the easy half. A memory system's real quality is its recall, and recall is a search problem with a specific trap.

Semantic search over embeddings finds cards that mean the same thing as the current turn even when the wording is completely different. This is what makes memory feel intelligent. It is also unreliable in one predictable way: embeddings blur exact terms. Account numbers, function names, client identifiers, version strings, the precise tokens that matter most in professional work, are exactly what semantic similarity smooths over.

Sparse keyword search has the inverse profile. It nails the identifier and misses the paraphrase.

Running both and fusing the results is the standard answer, and the fusion method matters. We merge the two ranked lists with reciprocal rank fusion, so a card that both methods rank moderately well beats a card that only one of them is enthusiastic about. That is the correct bias: agreement across independent methods is stronger evidence than intensity from one. The fused score is then adjusted by the card's own confidence and by how recently it was written.

The other half of recall quality is what happens when part of the pipeline is unavailable. If embeddings cannot be reached, the system should degrade in order rather than fail: hybrid, then semantic alone, then sparse alone, then plain recency. You get worse recall, never a broken turn. A memory system that returns an error when its vector store is down is a memory system that will take your agent down with it.

Problem four: fitting it in the window

This is the problem most discussions of agent memory skip entirely, and it is the one that determines whether any of the previous three mattered.

Memory is only useful if it reaches the model. The context window is finite. Retrieval will routinely surface more relevant material than can possibly fit, alongside the files, the tools, the conversation, and the skills that also need room. Something has to decide what makes it in.

We handle this with ordered lanes under a token budget. Each turn, content is rendered into named lanes covering project memory, permanent memory, thread evidence, tool evidence, files, tools, selected skills, and selected model, and admitted in order until the budget is spent. A reserve is held back for the model's own output, so a long answer is never truncated by its own context.

Two properties are what make this worth building rather than just capping the input:

  • Admission is explicit. When something does not make it into the turn, that is a recorded decision with a reason attached, not a silent drop. Silent drops are how you get an agent that behaves inconsistently for reasons nobody can reconstruct.
  • Every section carries a reason. Each admitted piece of context has a short explanation of why it is there, and skipped sections record why they were not.

Note that this is a different job from compaction. Lanes decide what gets into the window at the start of a turn. Compaction decides what comes out when a long run pushes against the limit. You need both, and they operate at opposite ends of the same constraint.

The part that makes it checkable

Because every admitted section carries its lane, label, and reason, the whole context can be rendered as something you read. Each durable memory card becomes a row carrying its type and scope, a freshness label, a stale flag when it has aged past the point of being trusted without checking, a confidence score, a truncation flag when it had to be shortened to fit, and the reasons it was retrieved.

This is the answer to the question every agent tool eventually provokes, which is "why did it do that." You do not reason about it from the outside. You look at what the model was given.

We hold models to the same standard, scoring them against known-correct answers rather than vibes, as described in how we evaluate models for verifiable work. A memory system deserves the same treatment. If you cannot inspect what it did, you cannot evaluate it, and you are being asked for trust the product has not earned.

How to evaluate a memory system

If you are comparing tools, these six questions separate real systems from a feature checkbox faster than any demo:

  1. Where does it physically live, and can you read it without the vendor's interface?
  2. Is it scoped to a project or to your account, and can you have both?
  3. How does it decide what to retrieve, and what happens when retrieval fails?
  4. What happens when retrieved memory does not fit the budget, and are you told?
  5. Can you see what actually reached the model on a given turn?
  6. How do you correct something that is wrong, and does correcting it once suffice?

Most products answer the first three and go quiet on the last three. That silence is informative, because questions four through six are where a memory system either becomes inspectable infrastructure or stays a black box that occasionally impresses you.

The full architecture behind our answers is documented in memory, context, and retrieval, with the surrounding agent machinery in the harness. It runs across the web app, the desktop app, and the CLI, so what Perch learns in one place is available in the others.

If the work you are trying to do requires knowing why the agent did what it did, that is the problem we build around. Talk to us.

Frequently asked questions

What is AI agent memory?
AI agent memory refers to at least three unrelated mechanisms. The context window is the working set for a single turn, holding the conversation, the files read, and the tool output so far. Retrieval finds relevant passages in a corpus of documents at question time. Durable memory stores facts about the user that persist across sessions and projects. Products often build one of these and call it memory, which is why two tools that both advertise memory can behave nothing alike.
What is the difference between agent memory and RAG?
RAG retrieves passages from a document corpus to answer a specific question, and the retrieved text is evidence for that answer. Durable memory stores facts about you and how you work, and it shapes the answer rather than serving as evidence for it. The distinction matters because they should be cited differently: a claim from a document is checkable against that document, while a preference applied from memory is not a claim at all. Systems that blend both into one undifferentiated context make it impossible to tell which is which.
Why do AI agents forget things mid-task?
Usually because the context window filled up, not because a memory system failed. As the window fills, a model loses reliable access to its original instructions and starts leaning on stale tool output. Quality degrades well before the hard token limit rather than at it, so an agent can look fine while running on a context that no longer holds the thread. Long tool-heavy runs are the worst case, because a single page snapshot or screenshot can cost more than dozens of turns of reasoning.
What is the difference between a context window and memory?
The context window is finite working space for one turn, and everything the model can use has to fit inside it. Memory is durable storage that outlives the turn. Memory is only useful if it reaches the window, so every memory system needs an admission step that decides what fits under a token budget. A system with excellent storage and no admission strategy will still behave as though it forgot.
How does an agent decide what to remember?
There are two approaches, and good systems use both. Explicit capture stores what you directly tell it to remember, which is reliable but requires you to notice and act. Inferred capture derives memories from your behavior, most usefully from corrections, since a correction is the highest-signal moment available: you have identified a specific wrong behavior and stated the right one. The failure modes sit at both ends, storing nothing useful without prompting, or storing so much that retrieval degrades.
How should you evaluate an AI tool's memory system?
Ask six questions. Where does it physically live and can you read it without the vendor's UI. Is it scoped to a project or to your account, and can you have both. How does it decide what to retrieve, and what happens when retrieval fails. What happens when retrieved memory does not fit the context budget, and are you told. Can you see what actually reached the model on a given turn. And how do you correct something that is wrong. A system that cannot answer the last two is asking for trust it has not earned.

Explore Perch