DEV Community

Cover image for My AI agent forgets decisions made in previous conversations. How to give it long term memory?
Edward Izgorodin
Edward Izgorodin

Posted on Originally published at mnemoverse.com

My AI agent forgets decisions made in previous conversations. How to give it long term memory?

On Tuesday you and your agent spent twenty minutes deciding not to keep sessions in Redis: the team would rather run one less service, and Postgres already handles the load. On Friday, in a new conversation, the same agent suggests moving sessions to Redis. It is not being stubborn. The conversation where the decision was made is over, and nothing outside it says the question was settled.

The short answer: a decision is not a fact the agent will rediscover from the code, so it has to be written down as its own record, with its reason, at the moment it is made. Then the agent reads the decisions that bear on a task before it proposes anything, and when a decision is reversed, the new one is written as the replacement of the old one rather than on top of it.

Disclosure: I work on Mnemoverse, the memory layer in the example near the end.

Why decisions are the first thing to go

Facts about the code can be found again: they are in the repository, and the agent reads them there when it looks. Preferences come back because you repeat them. Decisions do neither. The code shows what was done, not what was considered and rejected, and a decision you believe is settled is the last thing you think to repeat.

A decision also carries more than a fact. It has a reason, a scope, a date and, sooner or later, a successor. A summary of the conversation keeps the conclusion at best and often drops the reason, and without the reason the agent cannot tell whether the decision still applies to the case in front of it.

What a decision record needs

Five parts, each one short:

  • The decision, as a sentence that stands alone: "Sessions stay in Postgres; no Redis for sessions."
  • The reason: "One less service to run; Postgres handles current load."
  • The scope: this service, this repository, the whole team.
  • The date, so a later reader knows how old it is.
  • What it replaces, if anything.

The reason is the part that does the work. An agent that reads "one less service to run" can tell that a proposal to add Redis as a cache meets the same objection, although the decision names only sessions, and that a change to how long sessions last does not.

If your team keeps architecture decision records in the repository, that is the same shape, including a status for a replaced decision, and an agent can read them there if it is told where they are. What they do not hold is the decision made in a conversation that never became a file, which is most of the ones an agent helps you make.

When to write it and when to read it

Write it when it is agreed, not at the end of the session. Put that in the agent's standing instruction: "When we settle a design choice, save it as a decision record with its reason." Sessions that end abruptly lose everything that was going to be written at the end.

Read before proposing. Add a second line to the same instruction: before proposing a change in an area, search the decision records for that area. That is a search with a query, and it finds the decision more reliably when the record uses the words someone will later search with, which is one more reason to keep the decision sentence plain.

When a decision is reversed

Decisions change, and the change is where most memories go wrong. If the new decision is simply added, the agent now finds two contradicting records and has to guess. If the old one is deleted, the reason it was made is gone, and so is the answer to "didn't we decide the opposite?".

The better shape is a replacement: the new record says what it replaces, and the old one is kept and marked as replaced. Anyone who asks later can tell the current decision from the replaced one, and can still read why the earlier one was made.

With the Python SDK

This uses mnemoverse 0.3.1. The agent's own logic is left out.

from mnemoverse import MnemoClient

client = MnemoClient()  # reads MNEMOVERSE_API_KEY

# Tuesday: the decision, with its reason, written when it is agreed
first = client.write(
    "Decision (2026-09-29, service: api): sessions stay in Postgres, no Redis for sessions. "
    "Reason: one less service to run; Postgres handles current load.",
    concepts=["decision", "sessions", "redis", "postgres"],
    domain="project:api",
)
if not first.stored:
    raise SystemExit(f"Not stored: {first.reason}")
print(first.atom_id)

# Friday: before proposing anything about sessions
for item in client.read("decisions about session storage", domain="project:api").items:
    print(item.content)

# Later: the decision is reversed, and the new record replaces the old one
second = client.write(
    "Decision (2026-10-20, service: api): sessions move to Redis. "
    "Reason: login traffic grew beyond what Postgres handles; replaces the 2026-09-29 decision.",
    concepts=["decision", "sessions", "redis", "postgres"],
    domain="project:api",
    supersedes=[str(first.atom_id)],
)
print(second.superseded)   # the ids this write marked as replaced
Enter fullscreen mode Exit fullscreen mode

Passing supersedes marks the older record as replaced in the same write. Our API reference describes what happens to it: "A target is not deleted; it gains a superseded_by pointer to the new atom and stays fetchable by ID". Whether ordinary reads still return replaced records is a setting: the filter that hides them is off by default, and an organisation switches it on in the console, under "Hide replaced memories". With it off, a read can return both records, so write the reversal so it reads on its own, as above: its date and its "replaces" line are what tell the agent which one is current.

A write can be refused when it is too similar to something already stored in the same domain, and a refused write has no id, which is why the code checks stored before it passes the id to supersedes.

Check it with a control

  1. In one conversation, agree a decision with the agent and have it saved as a record with its reason.
  2. Start a new conversation and ask the agent to propose a change in that area. It should find the decision and name its reason, which exists only in the record, and then either respect it or argue with that reason.
  3. Control: ask about an area where nothing was decided. The agent should say it found no decision, rather than inventing one. If it cites one anyway, find where it came from before you trust the first answer.

The library page covers agent memory more broadly: what it is, the main approaches, and how to choose a memory layer. What was the last decision your agent had to be told twice?

The Python SDK is open source (MIT) and on PyPI as mnemoverse: github.com/mnemoverse/mnemoverse-sdk-python. The MCP server package on npm is open source too: github.com/mnemoverse/mcp-memory-server.

Top comments (1)

Collapse
 
glenallen profile image
Glen Allen •

The supersession model is particularly useful because long-term memory has a validity problem, not just a retrieval problem. At IT Path Solutions, we’ve found that an old decision can be retrieved perfectly and still be the wrong context for the current task if the underlying assumptions have changed. That makes validity signals just as important as semantic relevance: scope, age, superseded status, and the evidence behind the original decision can all affect whether it should influence a new proposal. I’d also consider making revalidation an explicit state rather than treating every stored decision as either “active” or “forgotten.” That gives the agent a safer middle ground when a decision is relevant but its original assumptions may no longer hold.