Skip to content

[Bug][Agent-generated] Background circuit breaker falsely cancels explore/librarian during legitimate search bursts #2652

@specialfortificationgoods-cpu

Description

This issue was drafted with help from an AI coding agent after reproducing the behavior locally and inspecting the relevant source paths. I reviewed the contents before posting. Marking it as agent-generated for clarity.

Prerequisites

  • I am writing this issue in English.
  • I searched existing issues and did not find an obvious duplicate.
  • I am using the latest version available in my local setup.
  • I checked the docs / investigated source and still hit the issue.

Bug Description

Background subagents such as explore and librarian are being cancelled by the repetitive-tool circuit breaker during legitimate research/search bursts.

The detector appears to treat repeated use of the same tool name as an infinite loop even when the inputs differ materially, which is common for glob, grep, bash, and similar exploration tools.

Steps to Reproduce

  1. Run a task that asks explore to search broadly across a codebase, or asks librarian to inspect an external repo/docs with many search/tool turns.
  2. Let the subagent perform a burst of repeated search calls with different queries/paths.
  3. Observe background-task cancellation.

Two concrete reproductions from my session:

[BACKGROUND TASK CANCELLED]
ID: bg_4ac25da9
Description: Find explorer kill logic
Error: Subagent repeatedly called glob 16/16 times in the recent tool-call window (80% threshold). This usually indicates an infinite loop. The task was automatically cancelled to prevent excessive token usage.
[BACKGROUND TASK CANCELLED]
ID: bg_390c502a
Description: Inspect upstream plugin changes
Error: Subagent repeatedly called bash 16/16 times in the recent tool-call window (80% threshold). This usually indicates an infinite loop. The task was automatically cancelled to prevent excessive token usage.

Expected Behavior

Search-heavy agents should be allowed to use the same tool many times in a row when the inputs differ and progress is still being made.

A real loop detector should still catch repeated identical or near-identical tool calls, but it should not kill healthy exploration solely because the tool name repeats.

Actual Behavior

The background circuit breaker cancels the subagent mid-task, which prevents explore / librarian from finishing legitimate investigations.

Doctor Output

 oMoMoMoMo Doctor 

 ⚠ 1 issue found:

1. Comment checker unavailable
   Comment checker binary is not installed.
   Fix: Install @code-yeongyu/comment-checker
   Affects: comment-checker hook

Error Logs

Subagent repeatedly called glob 16/16 times in the recent tool-call window (80% threshold). This usually indicates an infinite loop. The task was automatically cancelled to prevent excessive token usage.

Subagent repeatedly called bash 16/16 times in the recent tool-call window (80% threshold). This usually indicates an infinite loop. The task was automatically cancelled to prevent excessive token usage.

Configuration

Current stopgap mitigation on my side is config-only, not a code patch:

{
  "background_task": {
    "staleTimeoutMs": 1800000,
    "messageStalenessTimeoutMs": 1800000,
    "syncPollTimeoutMs": 1800000,
    "circuitBreaker": {
      "maxToolCalls": 400,
      "windowSize": 60,
      "repetitionThresholdPercent": 100
    }
  },
  "agents": {
    "explore": {
      "prompt_append": "Codebase exploration may require many search turns in a row. Avoid repeating the same tool call with the same inputs unless you explicitly state why the retry is necessary. After each search burst, synthesize what changed and switch approach if results stop improving."
    },
    "librarian": {
      "prompt_append": "External research may require many search turns in a row. Avoid repeating the same tool call with the same inputs unless you explicitly state why the retry is necessary. After each search burst, synthesize what changed and switch approach if results stop improving."
    }
  }
}

This reduces the false positives enough to keep working, but it is only a temporary workaround.

Additional Context

Relevant source paths in current dev:

  • src/features/background-agent/manager.ts
  • src/features/background-agent/loop-detector.ts
  • src/features/background-agent/manager-circuit-breaker.test.ts
  • src/cli/run/types.ts

From reading those files, the current repetitive-tool detection appears to count repeated tool names in a sliding window, while tool events already expose input state. That makes grep(query=A), grep(query=B), and grep(query=C) look like the same repeated action.

A likely fix would be to detect repeated (tool name + normalized input) signatures instead of tool name alone, while still keeping the absolute maxToolCalls breaker as the final backstop.

Operating System

macOS

OpenCode Version

1.2.27

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions