The reflexion loop: AI that stops making the same mistake
Nothing sours a good AI setup faster than correcting the same thing in week four that you corrected in week one. The model does not remember, and it will not, unless you build the part that does. The reflexion loop is four moves: capture the friction, surface it at the start of the next session, graduate what keeps recurring into permanent rules, prune the rest. Here is the file layout, the entry format, and the two gotchas that quietly turn this into a system that does nothing.
The problem: a sharp colleague with amnesia
You tell the agent on Monday to stop padding emails with reassurance. Thursday, padded email. You explain the naming convention for your files. Next week, wrong names. Nothing is malfunctioning: chat sessions are stateless, so unless a correction is written somewhere the next session reads, it did not happen.
What makes this worth fixing is what you are throwing away. Your corrections are the highest-signal information that exists about how you want to work. A new employee's first month of feedback is exactly what turns them from generically competent into useful to you. With an agent, all of it evaporates by default, and you pay for it again every week in small irritations that never compound into improvement.
The principle underneath the whole loop is one line: every repeated correction is a missing rule. The system exists to notice the repeat and write the rule.
The loop, in four moves
- Capture. At the end of a working session, write zero to three lessons about how the work went. Not what was built. Your project notes already hold what was built.
- Surface. The recent lessons get loaded at the start of the next session, either by a session-start hook or by a line in your standing instructions telling the agent to read the file first.
- Graduate. A lesson that keeps recurring gets rewritten as a permanent rule in the standing instructions, where it is binding rather than advisory.
- Prune. Recent lessons roll off. A file that only grows is a file nobody reads, and an unread file is not a loop.
Capture is the only move that needs you. The other three are mechanical enough to hand to the agent.
What counts as worth capturing? Four triggers cover nearly all of it: you corrected the agent or repeated an instruction; it missed a chance to be proactive when it had the information to act; a tool or approach had a gotcha worth remembering; or you learned something durable about how you want to work. If none of those happened, write nothing. Zero lessons is a valid outcome and a manufactured one is worse than none, because it dilutes the file you are asking your future sessions to read.
Where the files live
Two files, two different jobs, and keeping them separate is what stops either from rotting.
The lessons file. One Markdown file with two headings: ## Recent and ## Graduated. New entries go under Recent, newest first, capped at around ten. This file is advisory and current.
The standing instructions. The file your agent reads before every session, CLAUDE.md or AGENTS.md depending on your tool. Rules here are binding and permanent. This file has a budget you should treat as real, because everything in it is loaded on every session, whether it is relevant or not.
The split is the point. Without it, every small friction becomes a permanent rule and your standing instructions swell into something the model skims instead of follows. Ours grew to about 28KB before we cut it in half, moving the long step-by-step procedures out into skills that load only when they apply, and leaving the standing file as rules only. A rule the model skims is not a rule.
The entry format, and why recurrence matters
Short, dated, and structured enough to scan:
### 2026-07-27 · Check the deploy before saying it shipped [claude]
**What happened:** Reported the site as live off a successful build.
The deploy had failed at the CDN step; found out the next morning.
**Rule:** Never call a deploy done without loading the live URL.
**Recurrence:** 2
Four parts. The date, so you can see age at a glance. What happened, in one or two sentences, concrete enough to recognize. The rule, written as an instruction rather than a story. And a recurrence count.
That last field carries more weight than it looks. Before you write a new entry, scan Recent for one that already says the same thing. If it is there, bump the count instead of writing a near-copy. Four entries phrased four ways read as clutter. One entry with a recurrence of four reads as a demand, and it is the number that decides what graduates.
Two things to keep out. Lessons about what got built (that belongs in your project notes) and lessons that are really complaints. “The API was slow” is not actionable. “Check whether the API is rate-limited before assuming the code is wrong” is.
Graduation: from lesson to law
A lesson graduates when it earns a permanent slot. Two triggers:
- Recurrence of three or more. It has proven it is not a one-off.
- A single instance that cost real money or a real afternoon. Some lessons do not need a second occurrence to justify a rule.
Graduating means rewriting the lesson as an imperative in your standing instructions, then moving the original entry to the ## Graduated heading so Recent stays short. Rewrite it, do not paste it: standing instructions are commands, not anecdotes. “Never call a deploy done without loading the live URL” belongs there. The story of the night it went wrong does not.
Treat graduation as a trade rather than a promotion. Every line you add is loaded on every future session, competing for attention with everything else in there. When you graduate a lesson, look for something in the file that is no longer true and cut it in the same pass. A standing instructions file that only grows ends up describing a version of your work from six months ago.
Pull, not push (learned the hard way)
We originally ran capture as a forced step. A hook fired at the end of every session and made the agent write a retrospective before it could finish.
It worked, and we removed it. The reason is worth knowing before you build the same thing: the interruption landed at the worst possible moment, when the work had just clicked and the next thing was already in mind. Being stopped to reflect on how the last hour went is fine occasionally and corrosive daily. The retrospective became something to get past rather than something to do.
Now the routine save runs automatically, the notes and the task board stay current without being asked, and the retrospective runs only on request. Lessons get scraped when it is worth scraping. Fewer entries, better ones, and the habit survived instead of getting switched off.
The general version of that lesson, which is a lesson about the lesson system: a self-improvement loop that interrupts is a self-improvement loop that gets disabled. Make capture cheap enough that running it is not a decision, and pull-based enough that it never lands mid-thought.
What breaks
The entries are written where nothing reads them
This is the gotcha that costs the most and shows the least. If a session-start hook extracts everything below a specific heading, then an entry written above that heading is invisible to every future session forever. It happened to us. The file looked healthy and the loop had been open for weeks. Once, after wiring this up, check what your session actually receives against what your file actually contains. They are not the same thing until you have verified they are.
The file only grows
Fifty lessons is an archive, not a working file. Cap Recent at around ten and enforce it every time you add. The cap is the feature.
Everything graduates
The opposite failure. Promote every irritation and your standing instructions become a wall of text the model reads past. Graduate on evidence, and cut something when you add something.
Lessons about the build instead of the work
“Shipped the pricing page” is a project note. It has nothing to teach the next session about how to behave. If an entry would not change a future decision, it does not belong here.
Nobody ever reads it back
Once a month, read the Recent list yourself. Half of what is in there will be stale, and the two that are not will usually explain something you have been quietly annoyed about for weeks.
Your turn: start the file today
- Create
Lessons.mdwith two headings:## Recentand## Graduated. - Seed it from memory. Write the three things you have already corrected more than once. You know what they are, and they should be there on day one.
- Add one line to your standing instructions: read the recent lessons at the start of every session.
- Verify the read. Start a fresh session and ask the agent to repeat the lessons it loaded. If it cannot, your loop is open and this is the moment to find out.
- Install the skill below so the capture, dedupe, and graduation rules are the agent's job rather than something you have to remember.
- Run a graduation pass in a month. Anything at recurrence three becomes a permanent rule, and something stale comes out to make room.
The payoff is not dramatic and it compounds. Month two feels slightly less repetitive than month one. By month four the agent is annoying about different things than it used to be, which is exactly what improvement looks like from the inside.
Sources
- Wasser AI · the lessons file and graduation process running in our own AI operating system, including the forced-retrospective hook we removed and why
- Wasser AI · Reflexion Loop skill · the installable version of this workflow
- Wasser AI · Session Close skill · the end-of-session save the capture step attaches to
- Wasser AI · Your second brain with Claude Code and Obsidian · the vault these files live in
Want a system that gets less annoying over time?
We build the capture, the standing rules, and the review cadence into your setup so it improves without you maintaining it. Two-minute intake.
Get a quote ↗