Add loop/thrash guard to the zarvis agent loop#324
Merged
Conversation
A benchmark trial thrashed ~185 tool calls (re-editing the same file, commands repeatedly timing out) into a 90-minute external timeout SIGKILL. Add a model/provider-agnostic guard to the per-turn step loop: - Non-progress nudge (always on): after NONPRODUCTIVE_STREAK_LIMIT (4) consecutive tool rounds with no successful result, inject a one-shot harness observation telling the model to step back, verify state (run the project's build/tests), change approach, or stop — instead of repeating a failing action. - Graceful caps (opt-in, 0 = unlimited, default off → no behavior change): AGENTD_ZARVIS_MAX_STEPS caps model calls per turn; AGENTD_ZARVIS_MAX_TURN_SECS caps wall-clock per turn, so a session can stop itself cleanly (partial work preserved) before an external timeout kills it mid-edit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a model/provider-agnostic guard to the zarvis per-turn step loop:
OBSERVATIONtelling the model to step back, verify state (run build/tests), change approach, or stop — rather than repeat a failing action.0= unlimited, default off).AGENTD_ZARVIS_MAX_STEPS(model calls/turn) andAGENTD_ZARVIS_MAX_TURN_SECS(wall-clock/turn) let a session stop itself cleanly — partial work stays in the tree, session parks awaiting input — before an external timeout SIGKILLs it mid-edit.Why
In DeepSWE benchmarking, one trial introduced a recursion/hang, then thrashed ~185 tool calls (12% failing, many
exit_code 124), re-editing the same file 17× without recovering, until it hit the harness's 90-minAgentTimeoutError. This is a general failure mode (any model/repo): the loop had no notion of "not making progress" or "out of budget." The nudge gives the model a chance to self-correct; the caps bound the worst case.Design notes / limitations
ok=truein the round." It catches failing/timeout thrash (the observed case) but not "successful but pointless" looping — a deliberate, conservative scope.Test plan
cargo build+cargo test -p agentd-adapter-zarvis→ 138 passed, 0 failed.AGENTD_ZARVIS_MAX_TURN_SECS=3600): all 5 trials completed with 0 exceptions / 0 timeouts (the prior run had a 90-min timeout). No regressions; guard was inert when not needed (0 nudges/caps fired this run).🤖 Generated with Claude Code