diff --git a/agent/turn_explainers.py b/agent/turn_explainers.py index 4e66025ffa..f564572443 100644 --- a/agent/turn_explainers.py +++ b/agent/turn_explainers.py @@ -41,6 +41,16 @@ _EXIT_REASON_EXPLANATIONS: Dict[str, str] = { "the request was interrupted mid-call before a reply was " "received. Send `continue` to retry." ), + "redirect_restart_limit_exceeded": ( + "the request was cancelled by a new correction on every attempt, " + "so the turn stopped instead of retrying forever. Your last " + "correction is queued as the next message." + ), + "rebuilt_restart_limit_exceeded": ( + "every provider in the fallback chain kept failing over, so the " + "turn stopped instead of retrying forever. Send `continue` or " + "switch provider." + ), "budget_exhausted": ( "the per-turn iteration/cost budget was exhausted before a " "final answer. Send `continue` to keep going." diff --git a/agent/turn_iteration_prep.py b/agent/turn_iteration_prep.py index e30d756f85..9d7daee131 100644 --- a/agent/turn_iteration_prep.py +++ b/agent/turn_iteration_prep.py @@ -423,6 +423,11 @@ def apply_retry_restarts( "refunding the iteration budget indefinitely.", max_retries, ) + # The correction that tripped the cap was never applied; hand it back as the + # next user turn (result["pending_steer"]) instead of losing it to clear_interrupt(). + _unapplied = agent._drain_pending_redirect() + if _unapplied: + agent.steer(_unapplied) return _verdict("break") # Cancelled request produced no valid assistant item: reuse the same logical # iteration after the outer loop appends partial context + correction.