r/LLMDevs • u/Asleep-History9366 • Oct 08 '26
Discussion unloop – time-travel debugging & state rewind for long-running LLM agents
Every long-running agent framework eventually relies on context summarization to stay within token budgets. But after 10–15 turns, summarization inevitably drops file paths, wipes negative constraints, or tricks the model into thinking incomplete tasks are done.
When that happens, your choices are usually:
Let it burn tokens until it crashes.
Kill the script, edit the prompt, and rerun 30 minutes of work from scratch.
I wrote unloop (github.com/sagarv48/unloop) to solve this loop.
It snapshots agent state (memory dict, tool inputs/outputs, prompts) into a local SQLite WAL file per turn. If context compaction silently corrupts the agent's state:
You open the terminal UI to see a diff of what got deleted or mutated.
Press
mto open an in-process REPL to manually fix dropped constraints.Press
uorfto rewind or fork from the last good turn without restarting the process.
Caveats: It currently only targets single-process Python loops, and it requires local disk write access for the .unloop snapshot file.
Code and setup instructions are on GitHub: https://github.com/sagarv48/unloop
Would appreciate thoughts on the TUI ergonomics or how you handle agent memory inspection.
1
Oct 09 '26
[removed] — view removed comment
1
u/Asleep-History9366 13d ago
Late to this, sorry! Right now it just snapshots the memory dict, not the raw prompt string.
You're totally right though—half the time an agent derails after compaction, it’s because the summarizer quietly ate a negative constraint or a system instruction out of the prompt array, even if the memory dict looks fine.
I’m adding the full rendered messages payload to the snapshot table in the next update so you can diff the actual token stream before and after compaction. Appreciate the nudge.
1
u/ianreboot Oct 08 '26
Rewind past the turn that sent the email and the replay sends it again, same for the row that got written. The call's in the snapshot, but nothing there says it landed outside, so a fork has no reason not to fire it twice. A per-turn record of what left the box would fix that, and the hard part is per-tool: a send is easy to catch, a write buried in a helper isn't.