[GH-ISSUE #175] performAgentChain has no iteration cap — infinite loop on repeating tool calls #68

Closed
opened 2026-06-06 22:08:56 -04:00 by yindo · 0 comments
Owner

Originally created by @Vladimir44343 on GitHub (Mar 5, 2026).
Original GitHub issue: https://github.com/vxcontrol/pentagi/issues/175

Bug Description

The main performAgentChain loop in backend/pkg/providers/performer.go is an unbounded for {} loop with no maximum iteration counter. When a model repeatedly calls the same tool (e.g., due to model limitations), the repeating detector fires and returns "tool call 'X' is repeating, please try another tool" as a successful response (nil error). This means wantToStop is never set to true, and the loop continues indefinitely.

Reproduction

  1. Use a smaller/local model (e.g., Qwen3-Coder-Next-FP8 via vLLM) as the LLM provider
  2. Start a pentest flow that triggers terminal commands
  3. When the model encounters an error from a terminal command, it may retry the same command
  4. After 3 identical calls, the repeating detector fires
  5. The model receives "tool call 'X' is repeating, please try another tool" but ignores it and calls the same tool again
  6. This creates an infinite loop — we observed 4,800+ repeating warnings in a single session

Root Cause

In performer.go, execToolCall returns (response, nil) when repeating is detected:

if detector.detect(toolCall) {
    response := fmt.Sprintf("tool call '%s' is repeating, please try another tool", funcName)
    return response, nil  // <-- nil error means loop continues
}

The performAgentChain loop has no iteration cap:

for {  // no max iterations
    result, err := fp.callWithRetries(ctx, chain, ...)
    // ...
    if wantToStop { return nil }
    // loop continues forever
}

Suggested Fix

Add a hard iteration cap to performAgentChain:

const maxAgentChainIterations = 100

for iteration := 0; ; iteration++ {
    if iteration >= maxAgentChainIterations {
        return fmt.Errorf("agent chain exceeded maximum iterations (%d)", maxAgentChainIterations)
    }
    // ... existing loop body
}

Additionally, consider adding escalation to the repeating detector — after N consecutive repeating detections (e.g., 5), return an actual error instead of a message:

if detector.repeatCount >= maxRepeatingBeforeAbort {
    return "", fmt.Errorf("tool '%s' repeated %d times, aborting chain", funcName, detector.repeatCount)
}

Environment

  • PentAGI v1.2.0 (Docker image built 2026-02-25)
  • LLM: Qwen3-Coder-Next-FP8 via vLLM 0.15.1 (custom provider)
  • 2x NVIDIA GB10 (DGX Spark)
Originally created by @Vladimir44343 on GitHub (Mar 5, 2026). Original GitHub issue: https://github.com/vxcontrol/pentagi/issues/175 ## Bug Description The main `performAgentChain` loop in `backend/pkg/providers/performer.go` is an unbounded `for {}` loop with no maximum iteration counter. When a model repeatedly calls the same tool (e.g., due to model limitations), the repeating detector fires and returns `"tool call 'X' is repeating, please try another tool"` as a **successful response** (`nil` error). This means `wantToStop` is never set to `true`, and the loop continues indefinitely. ## Reproduction 1. Use a smaller/local model (e.g., Qwen3-Coder-Next-FP8 via vLLM) as the LLM provider 2. Start a pentest flow that triggers terminal commands 3. When the model encounters an error from a terminal command, it may retry the same command 4. After 3 identical calls, the repeating detector fires 5. The model receives `"tool call 'X' is repeating, please try another tool"` but ignores it and calls the same tool again 6. This creates an infinite loop — we observed **4,800+ repeating warnings** in a single session ## Root Cause In `performer.go`, `execToolCall` returns `(response, nil)` when repeating is detected: ```go if detector.detect(toolCall) { response := fmt.Sprintf("tool call '%s' is repeating, please try another tool", funcName) return response, nil // <-- nil error means loop continues } ``` The `performAgentChain` loop has no iteration cap: ```go for { // no max iterations result, err := fp.callWithRetries(ctx, chain, ...) // ... if wantToStop { return nil } // loop continues forever } ``` ## Suggested Fix Add a hard iteration cap to `performAgentChain`: ```go const maxAgentChainIterations = 100 for iteration := 0; ; iteration++ { if iteration >= maxAgentChainIterations { return fmt.Errorf("agent chain exceeded maximum iterations (%d)", maxAgentChainIterations) } // ... existing loop body } ``` Additionally, consider adding escalation to the repeating detector — after N consecutive repeating detections (e.g., 5), return an actual error instead of a message: ```go if detector.repeatCount >= maxRepeatingBeforeAbort { return "", fmt.Errorf("tool '%s' repeated %d times, aborting chain", funcName, detector.repeatCount) } ``` ## Environment - PentAGI v1.2.0 (Docker image built 2026-02-25) - LLM: Qwen3-Coder-Next-FP8 via vLLM 0.15.1 (custom provider) - 2x NVIDIA GB10 (DGX Spark)
yindo closed this issue 2026-06-06 22:08:56 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vxcontrol/pentagi#68