Skip to content

fix(agent): explain turns stopped by iteration limits - #92563

Open
fangliquanflq wants to merge 1 commit into
NousResearch:mainfrom
fangliquanflq:fix/agent-max-iterations-finalization
Open

fix(agent): explain turns stopped by iteration limits#92563
fangliquanflq wants to merge 1 commit into
NousResearch:mainfrom
fangliquanflq:fix/agent-max-iterations-finalization

Conversation

@fangliquanflq

Copy link
Copy Markdown
Contributor

What does this PR do?

Turns that reach agent.max_iterations after an earlier empty completion now run the existing summary fallback instead of ending with a blank response. TUI and Desktop clients also receive recoverable error semantics for this incomplete turn instead of a misleading status=complete frame.

Symptom

A tool-heavy turn can end at api_calls=N/N with reason=unknown, last_msg_role=tool, and response_len=0. The TUI renders a blank completed reply, so the user must guess that they should send continue.

Impact

Users can lose the visible conclusion of long-running work and receive no explanation that the configured iteration limit stopped the turn.

Bug Cause

Trigger: agent/turn_finalizer.py:finalize_turn when the API-call cap is reached with a refunded shared budget and a stale blank final_response.

Causal chain:

  1. A no-tool empty completion stores final_response="" before recovery continues.
  2. Later tool turns reach max_iterations while iteration-budget refunds keep remaining > 0, so the loop falls through with turn_exit_reason="unknown".
  3. The finalizer accepted only final_response is None for the max-iteration summary fallback, so the stale blank suppressed both limit classification and summary generation. The TUI then ignored completed=False and emitted status=complete.

Why it is wrong: An empty string is not a usable final answer and must not bypass the same exhaustion handling as None.

Working sibling / contrast: The existing None path already classifies the exit as max_iterations_reached(...), requests a toolless summary, and marks the result incomplete.

Ruled out: The shared iteration budget itself was not exhausted in the reported trace (182/240 remained), which excludes the separate iteration_budget.consume() failure branch as the source of the warning.

Fix

Treat blank string responses as unanswered at the max-iteration finalizer boundary, preserving the existing bounded summary and completion-explainer flow. In the TUI gateway, classify incomplete max_iterations_reached(...) results as recoverable errors while retaining the generated summary text.

Related Issue

Closes #92552

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Changes Made

  • agent/turn_finalizer.py - allow blank responses to enter the existing max-iteration summary fallback.
  • tui_gateway/server.py - emit recoverable error semantics for incomplete iteration-limit turns.
  • tests/agent/test_turn_finalizer_iteration_limit_exit.py - reproduce the refunded-budget blank-response state.
  • tests/tui_gateway/test_failed_turn_retention.py - verify the terminal frame and retained recovery snapshot.

How to Test

  1. Run the focused agent finalizer and conversation-loop tests.
  2. Run the focused TUI gateway failure-retention test.
  3. Confirm all 44 tests pass:
scripts/run_tests.sh tests/agent/test_turn_finalizer_iteration_limit_exit.py tests/run_agent/test_turn_completion_explainer.py tests/run_agent/test_dict_tool_call_args.py tests/tui_gateway/test_failed_turn_retention.py -q

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run the repository test entry point on the relevant tests and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: Windows 11

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) - N/A
  • I've updated cli-config.yaml.example if I added/changed config keys - N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows - N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide
  • I've updated tool descriptions/schemas if I changed tool behavior - N/A

Screenshots / Logs

The regression tests encode the captured api_calls=240/240, refunded-budget, blank-response state and the TUI terminal-frame behavior.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Turn exhausting agent.max_iterations stops silently (exit_reason=unknown) - no summary fallback, no explainer, status=complete

2 participants