Skip to content

fix(agents): collapse repeated waits queued inside one model turn - #979

Merged
0xallam merged 2 commits into
mainfrom
devin/1785961358-dedupe-waits
Aug 5, 2026
Merged

fix(agents): collapse repeated waits queued inside one model turn#979
0xallam merged 2 commits into
mainfrom
devin/1785961358-dedupe-waits

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

Stacked on #978#977#976, so review those first.

wait_for_agents blocks and resumes on its own, but nothing says so, so a model treats it as a poll and writes the whole loop out ahead of time — wait → view_agent_graph → wait → ... — in one response. Every queued wait then parks for its full timeout in turn, so an orchestrator can sit on hundreds of consecutive no-op waits (at the 300s ceiling, hours) while its children run unsupervised. The per-response cap (#977) bounds how many get queued; this bounds what they cost.

Only the first wait of a model turn parks. ReportUsageHooks.on_llm_start stamps the turn onto the run context, and the tool records the turn it waited in:

if turn is not None and inner.get(_WAITED_TURN_KEY) == turn:
    return {"wait_outcome": "already_waited", "note": "You already waited in this turn. ..."}
inner[_WAITED_TURN_KEY] = turn

Keying on the model turn is what makes this safe: waits the model queued blindly inside one response collapse, while a wait it issues after seeing the previous result — a new turn — parks normally. No timing heuristics, no "identical arguments" matching. The collapsed response tells the model why, so it can react instead of re-queueing.

Prompt side, in the shared INTER-AGENT MESSAGES block (so every variant gets it — root and subagent, autonomous and interactive) plus the tool's own summary:

wait_for_agents blocks and resumes you automatically, so it is never a poll you repeat: issue exactly ONE wait, then stop and react to what it returns.

Verified by assembling the real prompt across root/subagent × autonomous/interactive × quick/standard/deep × whitebox — all 24 variants carry the line, and it is in the tool description the SDK sends.

Repro

tests/test_wait_dedupe.py drives the real tool against a real AgentCoordinator (timeout shrunk to 2s; the shape is identical at 300s):

# today: three queued waits each park for the full timeout
assert outcomes == ["timeout", "timeout", "timeout"]
assert elapsed >= 3 * TIMEOUT

# with the guard: the first parks, the rest return at once
assert outcomes == ["timeout", "already_waited", "already_waited"]
assert elapsed < 2 * TIMEOUT

Plus: a wait in the next turn still parks, a message arriving during the first wait is still reported, and on_llm_start bumps the turn marker.

Link to Devin session: https://app.devin.ai/sessions/dad023e379e942f287bcf6822463b7a4
Requested by: @0xallam

@0xallam 0xallam self-assigned this Aug 5, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR prevents multiple wait_for_agents calls queued in one model turn from each consuming the full timeout.

  • Adds a per-context model-turn marker through ReportUsageHooks.
  • Returns already_waited for subsequent waits in the same turn.
  • Updates shared prompt and tool guidance to discourage pre-queued polling loops.
  • Adds coverage for repeated waits, later-turn waits, arriving messages, and turn-marker increments.

Confidence Score: 5/5

The PR appears safe to merge, with the wait deduplication aligned to the model-turn lifecycle and no actionable regressions identified.

Supported execution paths share the hook-mutated context with agent tools, repeated waits collapse only within one model turn, and later turns continue to perform real waits.

Important Files Changed

Filename Overview
strix/core/hooks.py Adds a monotonically increasing model-turn marker to the shared run context at LLM start.
strix/tools/agents_graph/tools.py Deduplicates repeated same-turn waits while preserving normal waits in subsequent turns.
strix/agents/prompts/system_prompt.jinja Clarifies globally that wait_for_agents blocks and must not be queued as a polling loop.
tests/test_wait_dedupe.py Covers deduplication timing, next-turn behavior, message arrival, and hook marker increments.

Reviews (1): Last reviewed commit: "fix(agents): state that one wait is enou..." | Re-trigger Greptile

@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1785961358-dedupe-waits branch from 0a74eb0 to d25644e Compare August 5, 2026 20:35
@0xallam
0xallam force-pushed the devin/1785961358-dedupe-waits branch from d25644e to 905b7bb Compare August 5, 2026 21:06
@0xallam
0xallam force-pushed the devin/1785961358-dedupe-waits branch from 905b7bb to cae37fc Compare August 5, 2026 21:07
Base automatically changed from devin/1785961125-stream-idle-watchdog to main August 5, 2026 21:07
@0xallam
0xallam force-pushed the devin/1785961358-dedupe-waits branch from cae37fc to 99baead Compare August 5, 2026 21:07
@0xallam
0xallam merged commit 0abe82d into main Aug 5, 2026
1 check passed
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.

1 participant