Skip to content
Harness Engineering2026-09-217 min read

What an AI Agent Remembers After a Restart

After a restart, an agent remembers what your application wrote to storage and nothing else. Run a 50-line Python example that loses its conversation, keeps a corrected preference, and shows where stored memory stops being evidence.

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 an order was placed, a message was sent or a payment went through.

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 agent. Maybe you deployed a fix, maybe the machine rebooted overnight. The next morning the agent asks your customer a question she answered 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

Most first agents keep the conversation in a list and pass the whole list to the model on each turn. It works well in a demo because the demo never restarts. The first restart empties the list, and the agent greets a returning customer 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 here 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("Lucy: ask the supplier for afternoon delivery")
    conversation.append("Lucy: actually, make that morning delivery")
    remember(db, "lucy", "delivery_window", "afternoon", "operator message 1")
    remember(db, "lucy", "delivery_window", "morning", "operator message 2")

print("conversation turns in this process:", len(conversation))
print("current preferences:", current(db, "lucy"))
print("versions on file:", db.execute("SELECT COUNT(*) FROM preferences").fetchone()[0])
db.close()
Run it as yesterday's process

python restart_memory.py first-run records two turns of conversation in a list and stores Lucy's preference twice: first "afternoon", then her correction to "morning".

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: [('delivery_window', 'morning', 'operator message 2')]
versions on file: 2

$ python restart_memory.py
conversation turns in this process: 0
current preferences: [('delivery_window', 'morning', 'operator message 2')]
versions on file: 2

I ran this with Python 3.14.3 on September 21, 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 Lucy's preference had been those two lines of chat, it would now be asking her again.

The preference survived, and so did its correction. The second process reads "morning", the value Lucy changed her mind to, along with a note of where it came from. It does not read "afternoon", 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 for a given session and name. Both writes in remember sit inside one transaction, so a crash between them cannot leave Lucy with two current delivery windows or with none. If you update and insert in two separate commits, that gap exists, and a restart is exactly when you will find it.

Storage is not yet context. Nothing in this script sends the preference to a model. On a real turn your code has to select the rows that matter for this session and put them in the request. A fact that is stored but never selected is, from the model's side, forgotten.

A summary saved at shutdown is not a substitute

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

Check your understanding

Quick check — An agent stores a customer 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. "Lucy prefers morning delivery" tells you what she said. It does not tell you that a delivery was booked. Whether an order went through is a question for the supplier's receipt, not for the agent's memory. Draft accepted is not purchase made works through that boundary.
  • 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. In this example only an operator'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 Lucy said.

Build the full version

The free book builds this mechanism properly for Lucy's shop agent. Chapter 5, "Remember across conversations", adds retrieval within one customer's session, a size budget for what goes into the request, the source of each remembered fact, 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. It uses a database helper supplied with the book, because Chapter 4, where you build that store yourself, is still a planned brief. The book states this at the top of the chapter.

When you want to practice, Unit A of the Chapter 5 exercises has you build the retrieval step and keep your evidence for Unit B, where you break it and repair 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: Remember across conversations

Build retrieval, a context budget and real forgetting on top of the table you just ran. Free to read, no account.

Ready to put an agent to work?

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.