Essay
The process has to survive the session
Justin Ahinon
I went through a few months of my coding agent sessions recently, and I kept laughing at how bad some of my prompts look without the rest of the project around them.
This is a real one:
let's plan bd ngr-dy4.5
Then, a few minutes later:
Implement the plan.
On another project:
remember kb/design
That's it. There is no feature description or acceptance criteria, and nothing explains what kb/design contains or why the agent should care.
And, somehow, it usually works.
Early in a project I explain everything: what the product does, how I want it to feel, which stack it uses, what I'm afraid of breaking. A few weeks later I'm saying "implement the plan" and expecting the agent to know what I mean.
I don't think I got better at prompting. The project got better at explaining itself.
I was treating every session like the first session
Every coding agent session starts a little cold. Even when the agent can read the whole repository, it doesn't inherit the exact understanding the last session had when it stopped.
It can inspect the files and Git history. It can search old tickets. It can recover a surprising amount from the shape of the code. But it doesn't know why I rejected the first design, which production failure changed our migration process, or whether that odd-looking constraint is intentional or just something nobody has cleaned up yet.
I used to fill that gap by explaining things again. Or, more often than I'd like to admit, by assuming the agent would figure them out.
That works while a project is small and everything is still in my head. It stops working when I have several projects, several sessions inside each one, and agents working on different parts at the same time.
Also, I forget too. A lot of my recent sessions start with some version of "I don't remember exactly, but at some point..." Then I ask the agent to search the tickets and commit history for whatever half-memory I'm trying to recover.
So I've started trying to make the project remember instead. Not by keeping transcripts or writing one enormous README that explains every file. I write down the things that should change what the next agent does.
I recently wrote about stopping asking a model to remember books it had never seen. Different problem, same instinct. If memory is the unreliable part, stop making the whole thing depend on memory.
The migration that taught me the difference
I learned the difference between "we documented it" and "we fixed the process" through two database migrations on NextGoodRole.
The first time, Atlas generated a migration with an unrelated rebuild of an existing profile table. The agent caught it during review and removed it. I asked why it happened, then asked the question I've apparently started asking after every weird failure: should we document this so it doesn't happen again?
We added atlas:check to the project guidance.
I thought that counted as fixing the process. Sort of.
A few days later, a production D1 migration failed with a foreign-key error. The migration tried to rebuild a table while another table referenced it. It included this:
PRAGMA foreign_keys = off;
That looks reasonable in ordinary SQLite. D1 applies migrations inside a transaction, where that pragma can't take effect. The table drop still violated the foreign key. We needed to defer the checks for the transaction instead.
We fixed the pending migrations and added the D1-specific rule to the operations runbook.
This time I didn't want the runbook to be the end of it.
We made atlas:check reject the unsafe pragma. We added regression tests with populated parent and child rows, because an empty database would never reproduce the production failure. Then we made every migration command run the check before Wrangler applies anything.
The runbook explains why the migration is dangerous. The command catches it even if the next agent never reads the runbook.
That's the part I was missing. Writing down a lesson is useful. Making the normal path enforce the lesson is much better. It's the same boring-layer lesson I came away with when I let an LLM write SQL against my production database: the prompt explains what should happen, but the validator is what I trust.
I was already doing this with design
I'd already learned a softer version of this with design, without really thinking of it as documentation.
When I find a visual direction I like, I put it in kb/design-guidelines.md and sometimes kb/extraordinary-design.md. The files have the palette and typography, but the part that does the most work is the physical metaphor behind the interface. WhatIsThatBook feels like a dusty independent bookshop. Buttons can be bookmarks or stamps. The navigation is a shelf of book spines.
Months later, I can point a new session at the design folder and ask it to build a page. I don't have to reconstruct the conversation where I said no to three beige SaaS designs before we found the bookshop. The new page starts from the decision we already made instead of the model's defaults.
The same thing now happens with operational work. I start debugging sessions by pointing the agent to my Cloudflare logs or PostHog runbook. The runbook has the commands, the project lookup steps, and the bits that shouldn't end up in a tool result. I don't spend the first ten messages teaching the investigation process anymore.
Those runbooks live in a public KB I keep on GitHub. It started as a few notes for myself. Now it's where I put engineering rules and runbooks that apply across projects. A Cloudflare logging lesson from WhatIsThatBook should still be available when I'm debugging Sets six months later. It doesn't belong copied into both repositories.
Tickets carry a different kind of memory. A good one has the problem, the context we found while researching it, the dependencies, and what done means. I can come back two weeks later and ask, "what is this ticket about?" The answer is sitting beside the work instead of buried in a chat I will never find.
I ended up writing more about the ticket as the handoff between agent sessions, because that pattern showed up all over the sessions I reviewed.
Even the closure matters. "Close the ticket with reason" might be the sentence I've typed most often this year. I want the next session to know what was verified and why we decided the work was done, not just see a green closed label.
I've started thinking of all of this as prompt compression. "Remember kb/design" works because hundreds of words of decisions already live somewhere the agent knows to read.
More documentation made things worse too
The obvious answer would be to write everything down. I tried something close to that too. Agents are extremely good at producing Markdown, so the documentation pile grows fast.
At one point NextGoodRole's web/README.md was 247 lines. It had started as a quick start and somehow become an operations manual, deployment runbook, architecture record, migration guide, and reliability checklist. Some of it repeated the local knowledge base. Some of it repeated my shared engineering docs.
And it was already wrong.
The README said a digest Worker ran every minute. The Wrangler configuration said every fifteen minutes. It said DEMO_MODE had a default in Wrangler, but the binding was not declared there.
An agent doing the responsible thing and reading the documentation would have received the wrong context.
We cut the README to 24 lines and made it an entry point. The operations material moved into one runbook. Product invariants stayed in the contracts, and technical decisions stayed in ADRs. Exact schedules and bindings went back to the only place that can really own them: the configuration.
The cleanup gave me a rule I like: every fact needs one owner.
I use AGENTS.md to tell the agent how to work in the repository and where to look next, not to repeat the whole knowledge base. Product decisions and the reasons behind weird constraints go in the KB. A ticket only needs the context for its piece of work. If something can be enforced by a test or a command, I put it there. And I stopped copying exact schedules and runtime values out of the configuration just to make a Markdown file feel complete.
When the same fact appears in three places, one of them will eventually lie.
The question I ask after a session now
I noticed another repeated prompt while going through my sessions:
is there any lesson that you learned from reviewing that work that we could document so that later on we make things the right way in the future?
The grammar is doing some work there, but the question is good.
I ask it while the surprise is still fresh. Maybe an agent found a migration problem. Maybe a review caught a role ID being used where the route needs a match ID. Or a date can be set but not cleared. Or a test passes alone and fails in the full suite.
Fixing the immediate problem is the first job. Then I ask:
Could the next agent make this mistake again?
If the answer is yes, I figure out where the lesson belongs. It might be one sentence in AGENTS.md, a runbook section, or a note in the ticket if the lesson only matters to that feature.
Then I try to go one step further. If a check can reject the mistake, make the check part of the command. If a test can reproduce it, add the test. If the order matters, give the next agent one command that does things in the right order.
I don't want perfect documentation. I don't think that exists. An agent can generate a beautifully organized pile of stale prose faster than any team I've worked with.
I want to open a project three months from now, type "implement the plan," and have that be a mostly reasonable thing to say. That only works if the project can tell the next session what we were doing, why we were doing it, and which mistakes we've already paid for.
The agent won't remember the last session. I probably won't either.
The process has to survive both of us.