Skip to content

fix: prevent infinite loop in performAgentChain on repeating tool calls#178

Merged
asdek merged 2 commits intovxcontrol:feature/next_releasefrom
mason5052:fix/agent-chain-iteration-cap
Mar 11, 2026
Merged

fix: prevent infinite loop in performAgentChain on repeating tool calls#178
asdek merged 2 commits intovxcontrol:feature/next_releasefrom
mason5052:fix/agent-chain-iteration-cap

Conversation

@mason5052
Copy link
Contributor

@mason5052 mason5052 commented Mar 6, 2026

Description of the Change

Problem

The performAgentChain loop in performer.go is an unbounded for {} with no iteration cap. When a model repeatedly calls the same tool, the repeatingDetector fires and returns a message (nil error), so the loop never breaks. This can result in 4,800+ iterations in a single session, consuming resources indefinitely.

Closes #175

Solution

Add two safety mechanisms:

  1. Iteration cap (maxAgentChainIterations = 100): Hard limit on the main loop. Normal pentest flows use far fewer iterations; 100 is generous while preventing runaway loops.

  2. Repeating escalation (maxSoftDetectionsBeforeAbort = 4): After 4 consecutive soft detection warnings (7 total identical calls), escalate from a soft message to an actual error that terminates the chain. The existing soft response is preserved for the first 4 detections, giving the LLM a chance to course-correct.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Areas Affected

  • Core Services (Backend API)

Testing and Verification

Test Configuration

  • PentAGI Version: master
  • Go Version: 1.24

Test Steps

  1. Verified both constants follow existing naming patterns (maxRetriesToCallSimpleChain, etc.)
  2. Confirmed for iteration := 0; ; iteration++ preserves all existing loop semantics
  3. Verified len(detector.funcCalls) is accessible (same package) and correctly tracks consecutive identical calls (resets on different calls per helpers.go:detect())
  4. Confirmed escalation threshold math: RepeatingToolCallThreshold(3) + maxSoftDetectionsBeforeAbort(4) = 7, so error fires on the 7th consecutive identical call
  5. Timeline: calls 1-2 build up, call 3 triggers first detection, calls 3-6 get soft warnings (4 soft detections), call 7 aborts

Security Considerations

No security impact. This is a resource exhaustion prevention fix.

Checklist

  • My code follows the project's coding standards
  • All new and existing tests pass
  • I have run go fmt and go vet
  • Security implications considered
  • Changes are backward compatible

Copilot AI review requested due to automatic review settings March 6, 2026 00:39
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prevents runaway performAgentChain executions in backend/pkg/providers/performer.go by adding hard stops for excessive looping and repeated tool-call patterns, addressing resource exhaustion described in #175.

Changes:

  • Add a maximum iteration cap to the main performAgentChain loop.
  • Escalate repeating tool-call detections from a soft warning to a terminating error after a configured threshold.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

The performAgentChain loop has no iteration cap, allowing infinite loops
when a model repeatedly calls the same tool. The repeating detector
returns a message (not an error), so the loop never breaks.

Add two safety mechanisms:
- Hard cap of 100 iterations on the main agent chain loop
- Escalation to error after 5 consecutive repeating detections
  (8 total identical calls: 3 before first detection + 5 detections)

The soft "please try another tool" response is preserved for the first
4 detections, giving the LLM a chance to course-correct before aborting.

Closes vxcontrol#175

Signed-off-by: mason5052 <ehehwnwjs5052@gmail.com>
- Rename maxRepeatingDetectionsBeforeErr to maxSoftDetectionsBeforeAbort
  for clarity (name now matches behavior: 4 soft warnings before abort)
- Adjust threshold value from 5 to 4 and remove -1 from condition
  (same runtime behavior: abort on 7th consecutive identical call)
- Use errors.New() instead of fmt.Errorf("%s", msg) for non-formatted
  error strings (more idiomatic Go)

Signed-off-by: mason5052 <ehehwnwjs5052@gmail.com>
@mason5052 mason5052 force-pushed the fix/agent-chain-iteration-cap branch from 917b371 to 536ea86 Compare March 10, 2026 15:35
@mason5052
Copy link
Contributor Author

Hi @asdek -- just a heads up that all four PRs (#178, #179, #180, #181) have been rebased onto the latest master (post-#185 merge) and are now cleanly mergeable.

This PR addresses the infinite loop reported in #175. The companion test PR is #180 (merge this one first).

Similarly, #179 fixes the detached context cancellation from #176, with tests in #181.

Happy to adjust anything based on your feedback.

@asdek asdek changed the base branch from master to feature/next_release March 11, 2026 13:08
@asdek asdek merged commit a98d4bc into vxcontrol:feature/next_release Mar 11, 2026
@asdek
Copy link
Contributor

asdek commented Mar 11, 2026

hey @mason5052

thank you for the PR, it's very useful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

performAgentChain has no iteration cap — infinite loop on repeating tool calls

3 participants