fix(agent): prevent auto retry loop from slow LLM backend prefilling large contexts (#69424) - #69521
Closed
webtecnica wants to merge 1 commit into
Closed
fix(agent): prevent auto retry loop from slow LLM backend prefilling large contexts (#69424)#69521webtecnica wants to merge 1 commit into
webtecnica wants to merge 1 commit into
Conversation
…large contexts (NousResearch#69424) Three-pronged fix for the stale-stream detector killing connections before a slow local/cloud model finishes prompt prefill: 1. Apply context-size scaling to local endpoints too The local-endpoint stale-timeout branch (default 900s) skipped the context-token scaling that the cloud path applied, so a 900s flat ceiling could still fire before a 122B model finishes prefilling 140K+ tokens. Move scaling out of the branch so both local and cloud paths get proportional timeouts: - >200K tokens → 1800s (30 min) - >100K tokens → 1200s (20 min) - >50K tokens → 600s (10 min) 2. Add stale-streak backoff After 2+ consecutive stale kills, apply a progressive multiplier (1× → 2.5× → 4× … up to 10×) to the stale timeout so each retry waits longer, eventually outlasting the prefill and breaking the infinite retry loop. Resets on successful response. 3. Raise the non-streaming stale timeout tiers consistently The non-streaming path () and Bedrock path () now share the same increased floors for consistency. Closes NousResearch#69424.
1 task
Contributor
|
Thanks for the detailed investigation and the user confirmation on #69424. This is an automated hermes-sweeper review: current
|
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a slow local LLM backend (e.g., 122B Qwen model on AMD Ryzen AI Max+ 395) processes a large context (~140K tokens), prompt prefill can take well over 180 seconds. The stale-stream detector kills the connection at the timeout threshold, and the conversation loop's retry mechanism immediately restarts the same large-context request from scratch — creating an infinite retry loop where prompt processing never completes.
Reported in #69424.
Root Cause
Three interacting issues in the stale-stream timeout computation:
Local endpoints skipped context-size scaling. The local-endpoint branch (is_local_endpoint() → default 900s) jumped straight to the local stale timeout without applying the context-token-based scaling that the cloud path used. A 900s ceiling would still fire before a 122B model finishes prefilling 140K+ tokens on modest hardware.
No backoff between retries. After a stale-stream kill, the conversation loop retries immediately with the identical timeout. If the prefill genuinely takes longer than the timeout, every retry hits the same wall → infinite loop. The existing circuit breaker (_stale_streak ≥ 5) eventually gives up, but that's 5 full timeout waits rather than progressive scaling.
Cloud path tiers were too conservative. The >100K tier capped at 300s and the >50K tier at 240s — too short for very large models processing dense contexts.
Fix (3 changes)
1. Context-size scaling for ALL paths (local + cloud)
Move the scaling out of the else branch so both local and cloud endpoints get proportional timeouts:
Applied to _stream_with_stale_detection (main streaming), _derive_stream_stale_timeout (Bedrock streaming), and _compute_non_stream_stale_timeout (non-streaming).
2. Stale-streak backoff
After 2+ consecutive stale-stream kills on the same agent (tracked by _stale_streak), multiply the stale timeout by a progressive factor:
This breaks the infinite retry loop: each retry waits longer, eventually outlasting the prefill. The multiplier resets on the next successful response (handled by the existing _reset_stale_streak on any successful API call).
3. Updated test assertions
test_non_stream_stale_timeout.py assertions updated to match the new conservative floor values (600s and 1200s instead of 150s and 240s).
Testing