I set up a Coder agent and a Reviewer agent last week. Simple loop. Coder writes code, Reviewer gives feedback, Coder fixes it. I went to bed at midnight.
They were still going when I woke up.
Not crashed. Not erroring. Just talking. Coder kept fixing the same thing. Reviewer kept asking for the same change. Both doing exactly what I told them to.
The only thing that stopped them was me killing the process.
Here's what nobody tells you.
Every framework has a step limit. LangGraph, CrewAI, all of them. Mine did too. It didn't help.
Because from the step counter's point of view, message 47 is a brand new step. Message 46 was different. It ran. It produced output. The counter ticked up.
It has no way of knowing that message 47 is byte-for-byte identical to message 45.
Step limits catch agents that never stop. They don't catch agents that stop every single time, then immediately start again with the same message.
The shift that fixed it
A loop isn't repeated steps. It's repeated content.
So I stopped counting steps and started counting fingerprints.
Every message gets hashed. Store the hashes in a small window per session. Same hash showing up too many times? Loop. Short pattern cycling? A→B→A→B ping-pong.
The whole thing is about fifteen lines of code.
The bug that almost killed it
One thing will silently break this if you're not careful.
If you serialize a payload to a string before hashing it (and you have to), the order of the keys matters.
{"a": 1, "b": 2} and {"b": 2, "a": 1} are the same dict. But json.dumps gives you two different strings. Two different hashes. As far as your detector knows, two different messages.
Your loop detector fires zero times. Ever. And you never notice, because on the surface everything looks fine.
The fix is sort_keys=True. That's it. But if you don't know to add it, you write the whole thing, ship it, and it does nothing.
What I still can't catch
Honest list:
Different words, same meaning. Hashes don't see that. Needs embeddings.
Genuinely new message every round. That's a step limit problem, not a loop problem.
One malformed message crashing the next agent. Schema problem.
The fingerprinting catches one specific thing — two agents saying the same thing to each other until someone notices. That's the one that costs the most money.
Takeaway
If you're running agents in production without payload fingerprinting, you don't have loop detection. You have a step limit, or you have a bill.
Hash the payload. Watch for repeats. Watch for cycles. Trip early.
Top comments (0)