Skip to main content

Module loop_guard

Module loop_guard 

Source
Expand description

Cross-batch tool-call loop guard.

The runner already deduplicates within a single LLM batch (is_dup in runner.rs). This module covers the orthogonal case: a model emitting the same (tool, arguments) pair across many sequential batches with no progress between them — the symptom that produced the 22-identical-Bash(cargo check) screenshot.

Trigger conditions (all required, to avoid the false positives that killed commit 9339cf1’s removed detect_call_loop):

  • (name, arguments) exactly matches a prior call’s pair — normalised once via \0 separator. No fuzzy / token-streak detection (that was the bit that wrongly caught batches like ssh ls/cat/sshpass).
  • Every prior matching call had identical output and identical success — polling a flaky endpoint where the body changes is real progress, not a loop.
  • No state-changing tool succeeded with a new key in between — when an edit_file to a previously-untouched file lands, the world has changed and any prior repeats no longer count. (A state-changing call to a key that is already in the window does NOT clear it: that means edit_file itself is being spammed with identical args, which is a loop we want to catch.)

The trigger threshold is intentionally low (third attempt blocks) so the model gets two “maybe this time” chances on transient flakes but doesn’t burn a full turn budget repeating itself. The agent clears the window at every user-message boundary, so the per-turn-only semantics are guaranteed by the caller.

Structs§

LoopGuardState

Enums§

LoopGuardDecision
What the runner should do with the call it’s about to dispatch.