Skip to content

fix(delegate-task): add subagent turn limit and model routing transparency#2575

Merged
code-yeongyu merged 1 commit intocode-yeongyu:devfrom
apple-ouyang:fix/issue-2571-subagent-safeguards
Mar 25, 2026
Merged

fix(delegate-task): add subagent turn limit and model routing transparency#2575
code-yeongyu merged 1 commit intocode-yeongyu:devfrom
apple-ouyang:fix/issue-2571-subagent-safeguards

Conversation

@apple-ouyang
Copy link
Copy Markdown
Contributor

@apple-ouyang apple-ouyang commented Mar 15, 2026

Summary

Fixes #2571 — a subagent infinite tool-call loop burned $350+ in one afternoon due to two missing safeguards.

Changes

Bug 1: Subagent infinite loop — no circuit breaker

File: src/tools/delegate-task/sync-session-poller.ts

Added a maxAssistantTurns parameter (default: 300) to pollSyncSession. Each time a new assistant message is detected, a counter increments. When the limit is reached, the session is aborted and a clear error message is returned to the parent.

Task aborted: subagent exceeded 300 assistant turns without completing.
This usually indicates an infinite tool-call loop. Session ID: ...

The default of 300 is well above any normal task's requirements while still preventing runaway loops. The parameter is optional and backward-compatible.

Bug 2: Silent model routing — no user visibility

File: src/tools/delegate-task/sync-task.ts

When a task completes, the return string now includes the actual model used. If the subagent was routed to a different model than the parent session (via category resolution), a ⚠️ warning is shown:

⚠️  Model routing: parent used openai/gpt-5.4, this subagent used google/gemini-3.1-pro-preview (via category: visual-engineering)

Root Cause (from issue)

A Sisyphus-Junior subagent was silently routed to google/gemini-3.1-pro-preview via the visual-engineering category, despite the parent session using GPT-5.4. The subagent then entered an infinite tool-calls loop (809 turns, 3.5 hours) with no safeguard to stop it. Gemini 3.1 Pro has zero prompt caching, so each of the 809 turns sent 880K input tokens at full price ($1.76/turn displayed, ~$3.52/turn actual due to >200K context tier).

Testing

bun test src/tools/delegate-task/
# 199 pass, 0 fail

All existing delegate-task tests pass. No breaking changes — maxAssistantTurns is an optional parameter with a safe default.

Related


Summary by cubic

Adds a turn-limit circuit breaker for subagents and makes model routing visible in task results to prevent infinite loops and surprise model costs. Addresses #2571.

  • Bug Fixes

    • Added maxAssistantTurns (default 300) to subagent polling; aborts the session and returns a clear error when the limit is hit.
    • Task output now includes the actual model used; shows a warning if it differs from the parent session’s model, with the routing category.
  • Migration

    • Backward compatible. No changes required; maxAssistantTurns is optional and defaults to 300.

Written for commit f2b26e5. Summary will update on new commits.

…rency

原因:
- subagent 无最大步数限制,陷入 tool-call 死循环时可无限运行,造成巨额 API 费用
- category 路由将 subagent 静默切换到与父 session 不同的模型,用户完全无感知

改动:
- sync-session-poller: 新增 maxAssistantTurns 参数(默认 300),每检测到新 assistant 消息
  计数一次,超限后调用 abortSyncSession 并返回明确错误信息
- sync-task: task 完成时在返回字符串中显示实际使用的模型;若与父 session 模型不同,
  加 ⚠️ 警告提示用户发生了静默路由

影响:
- 现有行为不变,maxAssistantTurns 为可选参数,默认值 300 远高于正常任务所需轮次
- 修复 code-yeongyu#2571:用户一个下午因 Sisyphus-Junior 死循环 + 静默路由到 Gemini 3.1 Pro
  烧掉 $350+,且 OpenCode 显示费用仅为实际的一半
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Auto-approved: Critical cost-protection circuit breaker and model transparency. Defensive design with high defaults ensures no impact on normal operations.

@code-yeongyu code-yeongyu added the triage:bug Confirmed bug with repro steps label Mar 24, 2026
@code-yeongyu code-yeongyu merged commit 5898d36 into code-yeongyu:dev Mar 25, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage:bug Confirmed bug with repro steps

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Subagent burned $350 in 3.5 hours with ZERO safeguard — silent model routing + no loop limit + cost display showing HALF the real bill

2 participants