October 27, 20264 min read

How AI Agents Remember Context Between Runs

We run automation across client accounts for the unglamorous half of outbound: watching inboxes, classifying what comes back, scoring deliverability signals and assembling the reporting. Most of it is driven by a language model.

A language model remembers nothing on its own. Every call starts clean, reads its prompt, answers and forgets, which is perfectly fine when a person is asking it a question.

It stops being fine when the thing calling the model is a job that wakes up every few minutes, reads the same mailboxes it read last time, and has to know what it already decided.

One of our reply watchers polls 19 mailboxes across 47 campaigns for a single client. Nothing about that job works unless the state lives outside the model.

This post covers what has to be remembered between runs, the split between run state and knowledge the agent builds up itself, and the part that turned out to need safety rails.

The first job is not reading the same thing twice

The simplest kind of memory is a list of what you have already seen, and it is the one you need before anything clever.

That watcher keeps a store of message identifiers per mailbox, currently 7,947 of them. On every run it reads the inbox, discards everything already in that store, and only sends what is genuinely new to the model.

Without it, each run would re-classify the entire mailbox, re-alert on replies that were handled days ago, and cost a model call for every message every time.

This is cheap, boring state, and it is the difference between a job you can run every few minutes and one you cannot run at all.

Run state and learned knowledge are different problems

Run state is bookkeeping: what has been processed, where the last run stopped, which campaigns were checked. It answers "have I done this already" and it is easy to rebuild if you lose it.

Learned knowledge is what the agent has worked out that nobody wrote down in advance. It has to survive long after the run that produced it, and losing it means starting the learning over.

Most agent setups only build the first kind. They are safe to restart and they never get better, because every lesson evaporates when the process exits.

The denylist is the part the agent writes itself

Across a fleet sending to 2,600 or more prospects a day, most of what lands in those mailboxes is not a prospect at all. It is warmup traffic and ordinary spam.

So the classifier learns. When the model reads a message and concludes the sender is warmup or spam rather than a human replying to a campaign, that sender's domain is written to a shared file. It holds 1,932 domains now.

Both the watcher and the step that pushes real replies into the CRM read the same file, so the two cannot drift apart and reach different conclusions about the same sender.

That is agent memory in the strict sense. Nobody compiled that list up front, the agent built it from what it saw, and it is worth more every month it runs.

This kind of plumbing is what we mean by automation engineering work rather than a one-off automation.

Memory that writes itself needs rails

A store the agent can write to is also a store the agent can poison, and the failure is silent.

A wrong entry throws no error. It quietly buries a real reply that nobody ever sees.

So the write path has two hard rules. It never learns a freemail domain, because a genuine prospect can answer from a personal address.

And no caller may skip a message on a denylist hit when the sender is a known lead in that campaign.

Those rails exist because the cost of the two mistakes is not symmetrical. Letting through a spam message wastes a few seconds of someone's attention, while suppressing a real reply loses a deal and tells you nothing.

Any agent that writes its own memory needs the equivalent, written before the agent is trusted to run unattended rather than after the first thing goes missing.

Retrieval is the half that decides whether it helps

Storing is the easy part. The harder question is what comes back into the prompt for a given decision, out of everything the agent has ever recorded.

Pull too much and the model drowns in irrelevant history. Pull too little and it repeats a mistake it already made once.

Running campaigns across five regions for one account, the same contact can appear in different sequences and angles, so the memory layer has to know which slice of history applies to the decision in front of it.

We lean toward narrow recall: fetch only what the current decision depends on. That matches what we keep seeing in campaign work, where tighter targeting with less noise beats trying to use everything available.

The Questions We Get Asked

Do AI agents need a database to have memory?

In some form, yes, though it does not have to be a database. Ours is a pair of JSON files read and written on every run.

What matters is that it lives outside the model and survives the process exiting.

Is a bigger context window the same thing as memory?

No. A larger window holds more at once, but it still empties when the session ends, and models do not weigh every token in a long prompt equally.

Memory is about what persists after the window closes, not how much fits inside it.

How is agent memory different from RAG?

RAG retrieves from a set of documents somebody else assembled, and the agent does not write back to it.

Agent memory is written by the agent itself as it works. Our denylist started empty and the classifier filled it, which is exactly what RAG over a fixed document set cannot do.