Skip to content
Harness Engineering2026-09-217 min readRev. 2026-09-30

What an AI Agent Remembers After a Restart

After a restart, an agent remembers what your application stored and nothing else. Run a short Python example on Colab that loses its conversation and keeps a corrected preference.

Key takeaways

  • A model keeps nothing between requests. After a restart the agent knows what your application stored and reloads, and nothing else.
  • Conversation held in a Python list disappears with the process. A row committed to SQLite is still there when the next process opens the file.
  • Correct a stored fact in one transaction: retire the old value and insert the new one together, so a crash cannot leave two current values or none.
  • Stored memory is a record of what someone said. It is never evidence that a job ran, a result was produced or a message was sent.

Rod Rivera

Author

What an AI Agent Remembers After a Restart

Rod's note: read with a pencil; the margins are for you.

You restart the process that runs your research agent. Maybe you deployed a fix, maybe the node was preempted overnight. The next morning the agent formats Maya's sweep report the way she told it not to yesterday. What did it actually keep?

The short answer: an agent remembers what your application wrote to storage and reads back on the next turn. The model itself keeps nothing. Every request to a model starts from the text you send with it. Anything that feels like memory is something your code saved and chose to include again.

That makes the useful question a concrete one. For each thing the agent seemed to know, where did it live?

Three places "memory" can live

Where it livesExampleAfter a restart
The modelNothing of yours. The weights do not change when you chatUnchanged, and never held your data
The processA Python list of conversation turns, a cached tool result, a variable holding "the current task"Gone
StorageA row in a database, a file on diskStill there, if it was committed before the process stopped
What the next process can and cannot read. Maya's message; Process memory: a Python list; Storage: a committed SQLite row; Restart; List is empty; Row is still there; Your code selects it and sends it to the model
What the next process can and cannot read

Most first agents keep the conversation in a list and pass the whole list to the model on each turn. It works in a demo because the demo never restarts. The first preemption empties the list, and the agent greets a returning researcher as a stranger.

A small example you can run

This script needs only Python's standard library. It has no model call, no API key and no network access, because the point is what survives, not what the model says. Save it as restart_memory.py.

python
import sqlite3
import sys
import time

SCHEMA = """
CREATE TABLE IF NOT EXISTS preferences (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    session TEXT NOT NULL,
    name TEXT NOT NULL,
    value TEXT NOT NULL,
    source TEXT NOT NULL,
    created REAL NOT NULL,
    active INTEGER NOT NULL DEFAULT 1
);
CREATE UNIQUE INDEX IF NOT EXISTS one_current_value
ON preferences(session, name) WHERE active = 1;
"""


def remember(db, session, name, value, source):
    # Retire the old value and add the new one together, or not at all.
    with db:
        db.execute(
            "UPDATE preferences SET active = 0 WHERE session = ? AND name = ? AND active = 1",
            (session, name),
        )
        db.execute(
            "INSERT INTO preferences (session, name, value, source, created) VALUES (?, ?, ?, ?, ?)",
            (session, name, value, source, time.time()),
        )


def current(db, session):
    rows = db.execute(
        "SELECT name, value, source FROM preferences WHERE session = ? AND active = 1 ORDER BY name",
        (session,),
    )
    return rows.fetchall()


db = sqlite3.connect("agent.db")
db.executescript(SCHEMA)
conversation = []  # lives in this process only

if sys.argv[1:] == ["first-run"]:
    conversation.append("Maya: report last night's sweep as plain text")
    conversation.append("Maya: actually, use a table with 95% intervals")
    remember(db, "maya", "report_format", "plain text", "researcher message 1")
    remember(db, "maya", "report_format", "table with 95% intervals", "researcher message 2")

print("conversation turns in this process:", len(conversation))
print("current preferences:", current(db, "maya"))
print("versions on file:", db.execute("SELECT COUNT(*) FROM preferences").fetchone()[0])
db.close()
Running it on Colab

Put %%writefile restart_memory.py as the first line of a cell above the code and run it to save the file. Then run each process from its own cell with a leading !, as in !python restart_memory.py first-run. Each !python starts a fresh Python process, which is exactly the restart you want to see.

Run it as yesterday's process

python restart_memory.py first-run records two turns of conversation in a list and stores Maya's preference twice: first "plain text", then her correction to a table with intervals.

Run it again as the restarted process

python restart_memory.py starts a new process with nothing in memory and opens the same agent.db file.

Compare the two outputs

Look at three numbers: the conversation turns, the current preference and the versions on file.

text
$ python restart_memory.py first-run
conversation turns in this process: 2
current preferences: [('report_format', 'table with 95% intervals', 'researcher message 2')]
versions on file: 2

$ python restart_memory.py
conversation turns in this process: 0
current preferences: [('report_format', 'table with 95% intervals', 'researcher message 2')]
versions on file: 2

I ran this with Python 3.12.13, the Python line Colab uses, on September 30, 2026. Delete agent.db to start again.

What the two runs show

The conversation did not survive. The second process starts with zero turns. If the agent's only record of Maya's preference had been those two lines of chat, it would now format the report the old way, or ask her again.

The preference survived, and so did its correction. The second process reads the table format, the value Maya changed her mind to, with a note of where it came from. It does not read "plain text," even though that row is still in the file.

The old value is history, not a second opinion. The unique index allows any number of retired versions but only one active value per session and name. Both writes in remember sit inside one transaction, so a crash between them cannot leave Maya with two current formats or with none. Update and insert in two separate commits and that gap exists, and a preemption is exactly when you find it.

Storage is not yet context. Nothing in this script sends the preference to a model. On a real turn your code selects the rows that matter for this session and puts them in the request. A fact that is stored but never selected is, from the model's side, forgotten. Choosing which rows to send is a retrieval problem, and Chapter 5 measures it.

A summary saved at shutdown is not a substitute

Writing a chat summary to disk when the process exits works only when the process exits politely. Preemption, a kill signal or a crash skips that step. Store each fact when you learn it.

Check your understanding

Quick check — An agent stores a preference with two separate commits: first it marks the old value inactive, then it inserts the new one. The process is killed between the two commits. What does the restarted process find?

Where this stops

  • A stored statement is not evidence of an action: "Maya prefers tables with intervals" tells you what she said. It does not tell you that last night's report was sent, or that the sweep it describes finished. Whether a job ran is a question for the scheduler's record, not the agent's memory. An accepted agent draft still needs an action boundary works through that line.
  • Only committed data survives: A process killed halfway through a transaction loses that transaction. That is the behavior you want, and it means the write has to finish before the agent tells anyone it has remembered something.
  • This is not deletion: Setting active = 0 stops a value from being current. The row, your backups and any request already sent to a model provider still hold it. Removing personal data for real is a separate job.
  • One file on one machine: The example does not cover several processes writing at once, a database on a network drive or a lost disk.
  • Let people, not the model, write facts at first: Here only a researcher's message becomes a preference. If a model can save its own guesses as facts, the next process will read a guess back as something Maya said.

Why this matters in a lab

Research agents run on preemptible machines, inside jobs that restart, across sessions that span days. "What survives a restart" is the first question in any agent design review, and the answer has to be specific: which facts are in which table, written in which transaction, and selected by which rule. An interviewer who asks how your agent keeps state is checking for exactly that: that you separate model, process and storage, that you know correction is one transaction, and that you do not treat memory as proof that something happened.

Once facts outlive a process, they can also go stale. Giving every memory an owner and an expiry rule covers who decides what is still true.

Build the full version

The free book builds this mechanism properly. Chapter 5, "Memory and retrieval", first derives BM25 and the ranking metrics and measures retrieval on a real model, then builds preferences with provenance, correction in one transaction, a bounded context, and a way to forget a preference so that an older summary cannot bring it back. The chapter is a manuscript draft with runnable code.

When you want to practice, Unit A of the Chapter 5 exercises has you build durable memory, and Unit B has you measure a retriever before trusting it. Reading and the exercises need no account.

If your question is a different one, such as whether an action really completed or how an agent picks up after a crash, the book's question map points to the chapter that answers it.

Read Chapter 5: memory and retrieval

Measure retrieval, then build correctable preferences, a context budget and real forgetting on top of the table you just ran. Free to read, no account.

Learn the mechanism. Test the claim.

Join the Prof Rod newsletter for one educational lesson a week, with worked examples attached. It is free to register for and separate from the Zero Employee community.