Repository navigation
fix(conversation): detect context-window condensation loops as stuck - #6215
Open
xxwtiancai wants to merge 1 commit into
Open
xxwtiancai wants to merge 1 commit into
xxwtiancai wants to merge 1 commit into
Conversation
A context-window-rejected agent call emits a CondensationRequest and the condenser answers with a Condensation, but nothing ever stopped that cycle: _is_stuck_context_window_error was an unconditional stub, so a conversation whose prompt never fits kept burning one rejected agent call plus one summarizer call per iteration until max_iteration_per_run. Implement the detection: the run is stuck when every event in the trailing window after the last user message belongs to such rejected-call/condensation cycles, with at least one CondensationRequest (which proactive token/event-pressure condensation does not emit) and no action, observation, or agent message between them. The existing 10-event scenario gate and the STUCK run-loop exit bound the detection; a user message still resets the window. Fixes OpenHands#6104
xxwtiancai
marked this pull request as ready for review
October 25, 2026 08:29
1 of 5 tasks
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.
HUMAN:
Problem: Re-prompting after failed context condensation loops indefinitely until hitting MaxIterationsReached.
Fix: Added trailing-event detection to mark runs STUCK on repeated condensation failures while ignoring proactive compaction.
Verification: Verified via scripted repro: the run now safely halts at the 5th rejection instead of spinning for 15 turns.
AGENT:
Why
When every agent LLM call is rejected with a context-window error while the condenser keeps succeeding, the conversation loops forever: each rejected call emits a
CondensationRequest, the condenser emits aCondensation, and the next call is rejected again.StuckDetector._is_stuck_context_window_errorwas an unconditional stub (return False), so the cycle only stopped atmax_iteration_per_run(default 500), wasting one rejected agent call plus one summarizer call per iteration in exactly the long conversations that are most expensive to restart. Fixes #6104.Summary
openhands/sdk/conversation/stuck_detector.py: the run is stuck when every event in the trailing window after the last user message belongs to rejected-call/condensation cycles (CondensationRequest/Condensation), with no action, observation, or agent message between them. At least oneCondensationRequestmust be present, so proactive condensation (token/event pressure, which emits onlyCondensation) never matches.len(events) >= 10gate inis_stuck(), and the existingSTUCKrun-loop exit — no new plumbing, no new configuration field, no changes to scenarios 1–4 or the nudge.TODO: blocked by agent-sdk#282stub.Issue Number
Fixes #6104
How to Test
New coverage (all verified to fail without the product change and pass with it):
tests/cross/test_stuck_detector.py: trailing run of 6 cycles → stuck; 4 cycles (8 events) below the 10-event gate → not stuck; 12 proactiveCondensationevents with noCondensationRequest→ not stuck; cycles interrupted by anActionEvent→ not stuck; user message after the cycles resets the window → not stuck.tests/sdk/conversation/local/test_stuck_detector_context_window.py: the issue's scripted repro (agent LLM always raisesLLMContextWindowExceedErrorviaTestLLM, summarizer always succeeds) endsSTUCKwith noConversationErrorEventand agent calls strictly belowmax_iteration_per_run; withstuck_detection=Falsethe same loop still endsERROR/MaxIterationsReached.The reproduction is the mocked scripted run the issue and its triage specify (no real LLM involved); the condenser, git-less run loop, and stuck plumbing are the real code paths.
Video/Screenshots
Reproduction notes instead of media (non-visual bug):
errorafter 15 rejected agent calls + 15 summarizer calls withMaxIterationsReached(matches the issue's reported log).stuckafter 5 rejected calls (agent_llm.call_count == 5 < 30) with noConversationErrorEvent.Type