State
By the Syncfusion DevTutorials team · Last updated
The loop's memory outside the conversation. Watch a loop with no state file do the same ticket twice, then give it a state.md file that it reads first and writes last.
The Loop's Memory
State file = a short file in the repo that lists what the loop has finished. In this lesson, you will give a loop a memory, so it never does the same ticket twice.
A loop goes around many times. After each turn, the agent's chat is thrown away.
So how does the next turn know what the last one finished?
It doesn't. Not unless the answer is in a file.
For example, without a memory, a loop may:
- fix ticket #3, then fix it again two turns later
- change tickets that were closed last week
- spend tokens on work that is already done
Simple lesson: the chat forgets. A file in the repo remembers.
A Real-World Example
Think about nurses who work in shifts.
The night nurse goes home at 7 in the morning. Before she leaves, she writes in the patient's chart: "Gave medicine at 3 a.m."
The day nurse reads the chart first, before she does anything. At the end of her shift, she writes in it last.
Without the chart, the patient might get the medicine twice.
A loop works the same way:
- Each nurse = one loop turn. Each turn starts with no memory.
- The chart = the state file. It stays in one place between turns.
- Read first, write last = the rule that stops work being done twice.
No state file: the loop forgets
Click the button and look for orange rows marked repeated work.
- Ticket #3: fixed, then fixed again two turns later.
- Tickets #10 and #17: finished last week, changed anyway.
- The scorecard: more turns and more tokens than the work needed.
Simple lesson: a loop with no memory does some work twice.
What You Will Learn
In this lesson, you will learn:
- Why an agent forgets between loop turns.
- What a state file is, and where it lives.
- The read first, write last rule.
- Why writing too early makes the memory lie.
- What a good state line looks like.
- When to use a tracker board instead of a file.
Old work in the lab
- In the lab, the state file already knows about tickets finished before the loop started, such as #10 and #17.
- In a real project, those lines would already be ticked in your
state.md, or closed in your tracker.
Why the Agent Forgets
Each Turn Starts Fresh
Many loops start each run as a fresh agent session. Scheduled runs usually do. Even one long session gets summarised, and details fall out.
In this lab, every turn starts fresh.
The agent's context window is everything it can see right now (the Harness Engineering course explains it). When the turn ends, that is gone.
The next turn starts with only:
- the rules file
- the loop's instructions
- the files it chooses to read
So "I already fixed #3" is not in its memory. It has to be in a file.
Watch It Happen
Step through a run with no state file:
- Frame 1: three fixes are checked. Their chats are now gone.
- Frame 2: the next turn starts empty and picks #3 again.
- Frame 3: it also changes #10 and #17, which were closed last week.
- Frame 4: the same loop with one more line,
state: state.md. Nothing is done twice.
The agent was not careless. It simply could not know.
Simple lesson: anything a turn must know has to be in a file it reads.
The State File
What It Looks Like
The loop reads the state file at the start of a turn and writes to it at the end.
Each turn reads state.md first and writes one line to it last. The chat is wiped. The file is kept.
Here is a simple state.md:
# state.md
- [x] #1 fixed and checked
- [x] #2 fixed and checked
- [x] #10 already done
- [ ] #3 next
Each line is one ticket. A tick [x] means done. The loop skips every ticked ticket.
In the loop file, it is one line:
state: state.md
Read First, Write Last
Every turn follows the same order:
- Read
state.md. - Pick the first ticket that is not ticked.
- Fix it.
- Check it.
- Write one line, only if the check passed.
Watch the file grow, turn by turn:
- Frame 2: the check fails. Nothing is written.
- Frame 3: the second try passes. Now the line is written.
- Frame 4: #10 is already in the file, so the turn skips it.
- Frame 5: the run is over. The file stays in the repo for the next run.
The same loop with state.md
Click the button. Then open the Backlog tab to see the full state.md at the bottom.
Memory saves money too.
- Without state, the run needed 8 turns.
- With state, it needed 7, and 2 of those were cheap skips.
Simple lesson: read the file before you pick. Write to it after the check passes.
The Danger of Writing Too Early
When the Memory Lies
The most common state bug is writing "done" before the check.
The agent says a ticket is done. The loop writes the tick. Then the check fails. But the tick is already in the file.
- Frame 1: the left file ticks broken #2. The right file does not.
- Frame 2: the next turn trusts the file. On the left, broken #2 is never looked at again.
In this lab, the loop always writes last. The left side shows what the file would say if it wrote first.
Important: a wrong line is worse than no line.
- No line means the work may be done twice.
- A wrong line means broken work is never fixed.
Simple lesson: write the tick only after the check passes, or the memory starts to lie.
Good State Lines
Lines a Program Can Read
The next turn is a program reading a file. It needs the same shape on every line.
Good lines:
- [x] #3 fixed and checkedhas one ticket, one status and one tick.- [x] #6 escalated to the inboxsays the loop is done with it, and why.- [x] #10 already donesaves the next turn from checking again.
Weak lines:
Fixed some stuff todaydoes not say which ticket.#3 is probably donehas no tick. "Probably" is not a status.- A 200-line log is too long to read every turn.
A File or a Tracker Board?
Tracker board = an app where a team keeps tickets, such as GitHub Issues, Linear or Jira.
Markdown file (state.md) | Tracker board | |
|---|---|---|
| Lives in | The repo | A separate app |
| The agent reaches it with | A normal file read | A connector |
| Good for | One loop, one project | A team, many loops |
| Risk | Two loops writing at once | The connector is down or slow |
Start with a file. Move to a tracker when people outside the loop need to add or see work. You will connect a tracker in the Connectors lesson.
Simple lesson: one ticket, one tick, one status per line. Start with a file.
Your Loop's Memory
Lab Exercise: Give the Loop a Memory
This loop does repeated work. Fix it.
Give the loop a memory
Click the button to open the loop file in the lab.
- Add one line at the top level, with no spaces before it:
state: state.md. - Press Check my loop.
The check runs 3 versions of the work. Each one must finish with 0 repeated items.
Simple lesson: one line in the loop file gives every turn a memory.
TL;DR
- Context window = what the agent can see right now. It is wiped after each turn.
- State file = a short file in the repo, such as
state.md, that lists what is done. Read first, write last = every turn:
- read the state file
- pick the first unticked ticket
- fix it and check it
- write one line, only if the check passed
- Writing too early = ticking before the check. Broken work is then never fixed.
- Good state line = a tick, a ticket number and a status:
- [x] #3 fixed and checked. - Tracker board = a team app for tickets. Use it when people outside the loop share the work.
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| No state file | "The agent will remember what it did." | Each turn starts fresh. Memory must be in a file. | Finished tickets are done again. |
| Writing too early | "Mark it done, then check it." | Write the line only after the check passes. | Broken work is marked done and never fixed. |
| Free-form notes | "Fixed some stuff today." | One ticket and one status per line. | The next turn cannot read it. |
| A huge log | "Write everything down." | Keep only status lines. Logs go elsewhere. | Every turn wastes tokens reading it. |
Check Your Understanding
Exercises
Press Check when you are ready. Use Show Hint if you get stuck.
What to Remember
- The agent forgets everything between turns. The repo does not.
- A state file is the loop's memory. In the loop file it is one line:
state: state.md. - Read the state file first. Write one line last, only after the check passes.
- Writing too early makes the memory lie, and broken work is never fixed.
- Keep each line short: a tick, a ticket number and a status.
- Start with a file. Move to a tracker board when a team shares the work.
Further Reading
- Effective harnesses for long-running agents, by Anthropic: why state lives on disk between sessions.
- Cursor CLI agent loops, on DevGenius: the
state.mdpattern in practice. - Loop Engineering, by Addy Osmani: state as the memory beside the other building blocks.
Next: Maker vs Checker. You will watch a loop grade its own work, then give it a checker that runs the tests.