Memory between sessions: what an agent should remember, and what it must not
Every session of this agent starts with no recollection of the previous one. That is not a limitation to work around; it is the design constraint that decides where each kind of knowledge lives. Get the split wrong and you either lose lessons every night or drown each morning in a wall of stale notes.
Three places, three kinds of knowledge
| Kind | Where | Example |
|---|---|---|
| State: what is true right now | project files, written by scripts | ledger balance, open requests, hypothesis status |
| Lessons: how to do things here | memory files, one fact each | "the platform bans four parallel crawlers, go sequential" |
| Secrets | an env file outside git | tokens, keys, account numbers |
The test for a memory file: will this still be true in a month, and can it be derived from the project files? If it expires, it is state. If it can be derived, it is noise. Only what survives both questions gets a file.
One fact, one file
The memory folder is flat. Each file is a few hundred bytes with a small header:
---
name: feedback_market-before-machinery
description: Day-zero lesson - the agent built a ledger and a report before talking to any customer
metadata:
type: feedback
---
On day zero the whole morning went into infrastructure...
**Why:** the agent is drawn to code and text; money comes only from contact.
**How to apply:** the daily report has a mandatory "market" line; a step
towards a customer outranks a step towards code.
Four types, encoded in the filename prefix so a glance at the folder tells you what is in it:
user_- who the owner is and how they like to work;feedback_- corrections the owner gave, with the reason;project_- facts about the work that are not in the code or the git history;reference_- pointers to dashboards, tickets, external pages.
Every file ends with **Why:** and **How to apply:**. A lesson without the why gets misapplied; a lesson without the how gets ignored.
The index is what actually loads
Sessions do not read the whole folder. They read one index file, MEMORY.md, with one line per memory:
- [Market before machinery](feedback_market-before-machinery.md) - a step towards a customer outranks a step towards code
The line is a hook, not the content. The session decides from the hook whether to open the file. Keep the index under a screen; when it grows past that, merge duplicates and delete what turned out to be wrong. We do this monthly.
Three things that never go in
- Secrets. Memory is read into context every session and mirrored to backups. A token in a memory file is a token in ten places. Store the pointer ("PayPal link is in env/paypal.txt"), never the value.
- Statuses and events. "Sent the report on the 8th" is state; it belongs in the journal file the scripts write. Memory that records events rots within days and the agent starts acting on last week's truth.
- Anything already in the repository. Code structure, past fixes, git history. If the owner asks to "remember" one of these, ask what was non-obvious about it and save that instead.
The trap we walked into
Memory is keyed by the project's folder path. Move the folder, or open the same work from two different paths on two machines, and you get two memory stores that never meet. The owner learned this the expensive way before this experiment: 23 fragmented memory folders across four projects, merged by hand. The rule now: identical paths on every machine, one project folder per long-lived line of work, sub-projects as subfolders and never as siblings.
What a session does with all this
The session's first step is a checklist that reads the index, then the state files, then decides. Memory tells it how to act; state tells it what is going on; the checklist tells it in what order to look. None of the three tries to do the job of the other two.