Your Agent Is Still a while (true) Loop. Here's the Event Log That Replaced Mine.
Your Agent Is Still a while (true) Loop. Here's the Event Log That Replaced Mine. An agent crashes mid-run and there's no answer to "what state was it in." Not because the debugging is hard. Because the state was a dic
Your Agent Is Still a while (true) Loop. Here's the Event Log That Replaced Mine.
An agent crashes mid-run and there's no answer to "what state was it in." Not because the debugging is hard. Because the state was a dict in RAM, and the dict died with the process.
That's not a bug in the code. It's a bug in the shape of the code.
The loop we all write
Almost every agent runtime on GitHub looks like this:
state = {}
while not done:
thought = llm(state)
result = tool(thought)
state = merge(state, result)
It works in demos. It falls apart the moment anything real happens:
- a tool call times out and you retry. Did the first one land? The dict can't tell you.
- the user hits interrupt. What finished before the stop? Guess.
- two sub-agents run in parallel and both write to
state. Last write wins, and you never know what lost.
The loop is fine. The problem is your state is a snapshot, not a history. A snapshot answers "what is the value right now." A history answers "what happened, in what order, and what did each step see."
This isn't a new idea. Workflow engines solved it decades ago. Temporal, durable functions, every queue system ever built: they journal actions instead of storing snapshots. Then we all started building agents and reached straight for the mutable dict, because the loop is what the tutorials show.
The fix is to stop storing state and start storing events:
events.append({"type": "tool_called", "tool": "ci_fetch", "args": {...}})
events.append({"type": "tool_result", "call_id": 7, "ok": True})
State becomes a function of the log. Any process can reconstruct it by replaying.
Walk the failure modes and the dict loses every round.
Crash mid-run: the dict is gone, the log replays and resumes. Retried tool call: the dict can't tell you the first one landed, so you get a double side effect that nobody notices until a customer asks why they got the same email twice. With keyed events, the retry is an exact-duplicate check. User interrupt: the dict leaves you a half-finished mystery, the log tells you exactly where to resume from. Two agents writing in parallel: last write wins and the loser evaporates, while a log keeps both orderings side by side, visible, comparable, auditable after the fact.
The retry case is the one that earns trust. A retried call that succeeded server-side is invisible in a dict. With a keyed event, it's a one-line duplicate check.
This failure class is well documented in real release tooling. A green pipeline that lied. A gate that silently no-op'd. An audit log that turned out to be fiction until someone checked it against reality. Every one of those was a snapshot lying about history. Every one would have been a non-event with an append-only record and one replay.
What it costs
Storage. Long runs append thousands of events and the log keeps them all. Cap old runs, compress finished ones, but it's a real line on disk usage.
Projection latency. Rebuilding state from events every step is slower than reading a dict. At microseconds most setups stop caring. For a hot loop, cache the projection and invalidate on append.
Over-engineering, sometimes. If your agent does A then B then C and never retries, keep the dict. I still do. The log earns its keep the day runs get long, retryable, or concurrent. For most of us that's where our agents already are.
tip: You don't need a framework. A JSONL file per run and a
reduce()function is a valid event store. Start there.
The agent's state can survive crashes and bad decisions about parallelism. The loop is still there. It just doesn't hold anything anymore.
What's holding your agent's state right now, and would it survive a hard kill mid-run?
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.