Lesson 02 · Loop Engineering
The cheapest part of a loop, and the one that holds the rest together.
You start here because you can build it today, with no scheduler and no sub-agents. Osmani calls state the sixth thing, and then calls it the spine:
The state file is the spine of the whole thing, it remembers what got tried, what passed, what is still open, so tomorrow morning the run picks up where today stopped. Addy Osmani, Loop Engineering
An agent has no memory between runs. Run one fixes a flaky test. Run two, tomorrow, starts cold and fixes the same flaky test again — or worse, undoes it. Nothing in the conversation survives. So the memory has to live somewhere the conversation cannot reach: a file in the repo.
Osmani develops the argument at length in long-running agents. It is the same trick every long-running agent depends on.
Create one file, LOOP.md, at the root of a repo you actually work on.
Three sections, nothing more:
# Loop state
Last run: 2026-08-19
## Open
- [ ] flaky test in test/auth/session.test.ts — times out on CI only
## Done
- [x] 2026-08-18 — bumped node to 22 in CI (PR #412)
## Do not retry
- reordering the migration files. Broke staging on 2026-08-11.
The third section is the one people leave out and then regret. A loop with no record of failure will confidently retry the thing that broke staging, every single morning, forever.
Why can a loop's memory not simply live in the conversation?
Which section stops a loop repeating an expensive mistake?
Write the three sections of your LOOP.md from memory, and one line you would put under each.
Primary source: Long-running agents by Addy Osmani — the post he points to for why memory belongs on disk. Then re-read the What one loop looks like section of Loop Engineering.
LOOP.md from your real open issues.