Skip to content

fix(server): subagents stop burning tokens on pull request watch wakes - #16217

Closed
t3dotgg wants to merge 4 commits into
mainfrom
t3code/audit-delegate-token-waste
Closed

t3dotgg wants to merge 4 commits into
mainfrom
t3code/audit-delegate-token-waste

Conversation

@t3dotgg

@t3dotgg t3dotgg commented Oct 5, 2026

Copy link
Copy Markdown
Member

Delegated subagents were burning huge numbers of tokens on pull request watch wakes nobody reads. Across the fleet since Oct 1, finished subagents ran about 4,000 extra times. On cup2 alone that was 3,635 extra runs and about 1.48B input tokens, against about 398M for the subagents' real work. One review subagent ran 151 times.

Two things combined:

  1. Before fix(server): subagents no longer inherit parent pull-request links #14918, a subagent copied its parent's pull request links, including active watches. Every check, comment, and conflict on the parent's pull request then woke each finished subagent. Its result had already gone to the parent, so these runs reached no one. Some ran babysit-pr, and one edited code in parallel with its parent. fix(server): subagents no longer inherit parent pull-request links #14918 stops new copies, but watches that subagents already hold stay active.
  2. With dozens of watches, the shared GitHub GraphQL quota ran out. Rate-limited reads counted toward the 15-minute give-up, so every watch ended with a wake that says "call watch_pull_request to watch it again". The agent re-watched into the same limit and woke again 15 minutes later. On cup2 this sent 2,388 "stopped watching" wakes to subagents in two days.

Fix:

  • Subagent threads cannot start a pull request watch. watch_pull_request returns a typed refusal whose text reaches the agent, telling it to put the pull request in its result so the parent can watch it. The orchestrator refuses the command too.
  • The watch reactor ends watches that subagents already hold on its next sweep. It does not wake the subagent and does not read the host.
  • A host rate limit no longer counts toward the 15-minute give-up. The watch waits until the limit resets.

Tests cover a rate-limited watch (stays on, no wake after 30 passes) and a subagent with an inherited watch (new watch refused, inherited one ended without a host read or wake). Both fail without the fix. The Stop test now gives its subagent an inherited watch instead of starting one, because subagents can no longer start one.

Not changed: review subagents still call link_pull_request for the pull request they review, because the runtime instructions tell every agent to link pull requests it works on. Links do not wake anyone, so this costs a few tool calls per subagent.

Reviewed with sol-loop: 2 rounds with GPT-6.1 Sol on high.

Created with Claude Opus 5.5 in Claude Code.

t3dotgg and others added 3 commits October 5, 2026 15:08
…watch wakes

Subagents cannot watch pull requests; watches they inherited end without a wake.
A host rate limit no longer counts toward giving up on a watch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Oct 5, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 5, 2026
Comment thread apps/server/src/orchestration-v2/PullRequestWatchReactor.ts
@macroscopeapp

macroscopeapp Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 74f80f8

Macroscope's review found this PR approvable — This is a focused server bug fix that prevents subagents from creating or honoring pull-request watches that cannot deliver useful results, while preserving parent-thread watches and pausing cleanly through host rate limits. The production changes are narrowly scoped and covered by targeted tests, with no sensitive, schema, deployment, or static-analysis impact.

You can add or adjust custom eligibility rules. Learn more.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Codex Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Codex Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Codex Live turn WebSocket decoded 20.9 KiB 20.9 KiB 0 B (0.0%) 29.3 KiB ✅
Codex Live turn messages 2 2 0 (0.0%) 8 ✅
Claude Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Claude Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Claude Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Claude Live turn WebSocket decoded 21.2 KiB 21.2 KiB 0 B (0.0%) 29.3 KiB ✅
Claude Live turn messages 1 1 0 (0.0%) 8 ✅

Baseline: 54b6b66 · PR result: 74f80f8 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 5, 2026
…lone

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 5, 2026 22:16

Dismissing prior approval to re-evaluate 74f80f8

@t3dotgg

t3dotgg commented Oct 5, 2026

Copy link
Copy Markdown
Member Author

Note

🤖 Claude Opus 5.5 responding on behalf of Theo

Closing as superseded by #16208, which shipped every behavior here: subagents cannot watch, watches they inherited end without a wake, and a rate limit never ends a watch. #16208 also shares one read per pull request across watchers and slows the cadence.

After #16208 landed, I checked whether its subagent refusal text reaches the agent. It does: for a declared tool failure, Effect's MCP server sends error.message as the tool result text (effect/dist/ai/McpServer.js, declaredFailureResult). Nothing is left to fix in this branch.

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

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants