Skip to main content

Replanning & Recovering From Failure

Introduction

This is the finale of the planning section — and it closes a loop the whole section has been circling. You learned to decompose (L127), to choose between planning upfront and reasoning as you go (L128), to reflect (L129), and to search over reasoning (L130). Every one of those came with the same warning: a plan is made before you see any results, so reality will diverge from it. This lesson is what you do when it does.

A plan is the start of the work, not a contract. The moment a step fails, an assumption breaks, or the world changes, a rigid agent is dead in the water. A robust one closes the loop: monitor → detect → recover.

In this lesson:

  • Open-loop vs closed-loop execution — the one distinction that separates a demo from a robust agent
  • Detecting divergence (you can't recover what you don't notice) and the recovery menu (retry · repair · replan · backtrack · escalate)
  • Replanning smart (partial, not global), and bounding recovery so it can't spiral
  • The 2026 reality, and how this completes the plan → act → monitor → recover loop

Scope: this synthesizes Section 4. It builds directly on L125 (Handling Tool Errors & Retries) (tool errors — the step level), L128 (Plan-and-Execute vs ReAct) (plan-and-execute), L129 (Self-Reflection & Self-Critique) (reflection-as-recovery), and L130 (Tree-of-Thought & Search-Based Reasoning) (backtracking). Next, the course turns to Memory (L132 — Why Agents Need Memory) — how an agent remembers across runs.

An infographic titled 'Replanning & Recovering From Failure'. A plan is a guess made before seeing results, so reality diverges from it — and the agent must CLOSE THE LOOP. OPEN-LOOP execution runs the plan blindly with no monitoring, so when a step fails or an assumption breaks it barrels ahead and cascades into failure. CLOSED-LOOP execution adds monitor, detect, recover around every step: plan, execute, monitor, recover, repeat. STEP 1, DETECT the divergence (you can't recover what you don't notice): a tool error (the L125 layer), an observation that contradicts the plan, a precondition or assertion that fails, a stuck or looping state (the same failure repeating, no progress), a verifier or critic flagging the output, or a step or cost budget exhausted. STEP 2, pick a RECOVERY strategy matched to the failure: RETRY for a transient glitch (step-level, L125); REPAIR in place for a minor mismatch that leaves the plan valid (AdaPlanner's in-plan refinement); REPLAN from the current state when the plan's premise is broken (out-of-plan regeneration) — replan the REMAINDER and keep the valid progress; BACKTRACK to a prior good state and try a different branch when stuck (the search idea from L130); reflect then retry with a stored lesson (Reflexion); or ESCALATE to a human (or degrade gracefully) when it is unrecoverable. DON'T SPIRAL: replanning can loop forever, so bound it with a recovery budget, a loop detector (never retry an unchanged action that already failed), and an escalate backstop after N attempts. THE 2026 NUANCE: reasoning models self-correct internally, but external replanning is essential because only EXECUTION reveals that the plan failed — the environment's feedback is information the model cannot get by thinking; recovery logic lives in the harness, which is most of an agent's reliability. SECTION SYNTHESIS: decompose (L127), choose an architecture (L128), reflect (L129), search (L130), and recover (L131) together form the complete plan, act, monitor, recover loop. Takeaway: a plan is the start, not the contract — close the loop, detect divergence, match the recovery to the failure, and always have a bounded escalation path.

Open-Loop vs Closed-Loop

Here's the single idea this lesson rests on, borrowed from control theory:

  • Open-loop execution runs the plan blindly — no feedback, no monitoring. It's the pure plan-and-execute of L128: make a plan, run every step, hope it works. It's efficient when nothing goes wrong — and catastrophic when something does, because it has no idea anything did. (The L128 — Plan-and-Execute vs ReAct rigid-plan failure, and the L131 — Replanning & Recovering From Failure widget's open-loop mode.)
  • Closed-loop execution wraps each step in monitor → detect → recover. After acting, the agent checks the result against the plan, and if reality has diverged, it adapts — repairs, replans, backtracks, or escalates. This is what makes an agent robust.

The state of the art even varies the loop tightness by uncertainty (AdaPlanner, Sun et al. 2023): when the agent is confident, it runs longer open-loop stretches (cheap); when uncertainty spikes — an unfamiliar state, a risky step — it tightens to closed-loop, checking after every move. That's the L128 (Plan-and-Execute vs ReAct) "how often do you re-reason?" axis, now applied to monitoring: monitor as often as the risk demands.

Open-loop asks "what's the plan?" once. Closed-loop also keeps asking "is the plan still working?" — and that second question is the whole game.

Step 1 — Detect the Divergence

Recovery is impossible without detection — you can't fix a failure you never noticed (and the worst failure is the silent one, where the agent sails on thinking it succeeded). So the first job of a closed loop is to watch for divergence. The signals, from cheapest to deepest:

  • A tool/infra error — the step threw, timed out, or returned is_error (the L125 — Handling Tool Errors & Retries layer).
  • An observation that contradicts the plan — the result doesn't match what the step expected (the sold-out flight; an empty DB result). The plan's assumption just broke.
  • A failed precondition / assertion — a check you placed before or after a step doesn't hold.
  • A stuck / looping state — the same failure is repeating, or no progress is being made over several steps.
  • A verifier or critic flags it — a grounded check or evaluator (L129) says the output is wrong.
  • A budget tripwire — too many steps, too much cost, too long. (Bound everything.)

In code, detection is a set of checks in the executor — assertions that turn a silent drift into an explicit trigger:

result = execute(step)

# DETECT divergence — you cannot recover what you do not notice:
if result.is_error:                       diverge("transient")    # tool/infra error (L125)
elif not satisfies(result, step.expects): diverge("premise")      # observation ≠ the plan's assumption
elif no_progress(history):                diverge("deadend")      # same failure repeating / stuck
elif steps_taken > STEP_BUDGET:           diverge("budget")       # bound the run
else:                                     plan.mark_done(step)     # on track — continue
# A failed check is the TRIGGER to recover. No monitoring = no recovery.

This is exactly how robust planners (e.g. AdaPlanner) work: assertions in the executed plan; a failed assertion is the trigger to recover. No checks → no triggers → open-loop → silent failure.

Step 2 — The Recovery Menu

Once you've detected a divergence, the skill is choosing the right response — recovery is not one move, it's a menu, and the choice depends on the kind of failure:

FailureRecoveryWhy
Transient (timeout, 429)Retry (with backoff)It'll likely work next time — step-level, L125 (Handling Tool Errors & Retries)
Minor mismatch (format off, plan still valid)Repair in placeFix the step; the plan is fine — AdaPlanner's in-plan refinement
Premise broke (assumption invalid)Replan from current stateNo retry/repair helps — regenerate the remaining plan (out-of-plan)
Dead-end / stuck (looping)BacktrackUndo to a prior good state, try a different branch — the L130 (Tree-of-Thought & Search-Based Reasoning) idea
Learnable failureReflect → retryReflect on why, store the lesson, retry — Reflexion (L129)
Unrecoverable (no permission/info)Escalate / degradeHand off to a human, or return a partial result — L125 (Handling Tool Errors & Retries)

Notice the hierarchy (from robust agents): low-level action errors get cheap, local fixes (retry, repair, predefined corrective routines); high-level plan failures trigger LLM replanning. Matching the level of the response to the level of the failure is the difference between a quick recovery and either a wasteful over-reaction (replanning a transient blip) or an under-reaction (retrying a broken premise forever).

See It — Close the Loop, Match the Recovery

Below, a plan is mid-flight when something breaks. Pick the failure type and flip between open-loop and closed-loop:

A plan is mid-execution toward “get me to the SF conference tomorrow, cheapest” when something goes wrong. Pick the failure type and flip between OPEN-LOOP (execute blindly, no monitoring) and CLOSED-LOOP (monitor → detect → recover). Open-loop fails EVERY time — it barrels ahead on a broken plan (books a hotel for a trip with no flight, loops forever, fabricates). Closed-loop detects the divergence and applies the RIGHT recovery from the menu: a minor format mismatch → REPAIR in place; a sold-out flight (premise broken) → REPLAN from the current state; a stuck loop → BACKTRACK to a prior branch; a missing permission → ESCALATE to a human. The lesson lands: you must close the loop, match the recovery to the failure, and keep escalate as the bounded backstop.

Two things to take away:

  • Open-loop fails every time — with no monitoring, it barrels ahead on a broken plan (books a hotel for a trip with no flight, loops forever, fabricates a result). That's the lesson: you must close the loop.
  • Closed-loop picks the recovery that fits the failure — repair a minor mismatch, replan a broken premise, backtrack a dead-end, escalate the unrecoverable. The menu highlights which strategy each failure demands.

Replan Smart — Partial, Not Global

When the answer is replanning, how you replan matters enormously. The naive move is a full (global) replan — throw away everything and regenerate the whole plan from scratch. It's simple but wasteful: you discard the steps that already succeeded, pay full planning cost again, and may even undo good work.

The better move is a partial replan — regenerate only the remaining / affected subtasks, from the current state, keeping the valid progress (this is the "beyond global replanning" / hierarchical-recovery idea). Concretely, the closed-loop executor:

plan = make_plan(goal)
recoveries = 0
while not plan.done() and budget_left():
    step   = plan.next()
    result = execute(step)
    div    = detect_divergence(result, plan)     # ← the closed loop
    if div is None:
        plan.mark_done(step); continue

    if recoveries >= MAX_RECOVERIES or repeating(div):
        return escalate(div)                     # ← bounded backstop — never spiral

    recoveries += 1
    if   div == "transient": retry_with_backoff(step)               # L125
    elif div == "minor":     plan = repair_in_place(plan, result)   # in-plan refinement
    elif div == "premise":   plan = replan(goal, state=current())   # out-of-plan: REPLAN the REMAINDER
    elif div == "deadend":   plan = backtrack(plan)                 # to a prior state (L130)
    else:                    return escalate(div)                   # human / graceful degrade
# Replan from the CURRENT state — keep the progress that's still valid; don't start over.

Note replan(goal, state=current()) — it replans the remainder given what's already done, not the whole thing. This is also AdaPlanner's split: in-plan refinement (repair a subplan, plan structure intact) for minor issues vs out-of-plan refinement (regenerate the plan) for major ones. Reserve the expensive full replan for when the goal or the whole approach is invalidated; otherwise, patch the remainder and keep moving.

Don't Spiral — Bound Recovery & Escalate

Recovery has a dangerous failure mode of its own: the recovery spiral. Replan → the new plan fails → replan again → fail → ... forever, burning tokens and time. (You saw the same risk in L125 — Handling Tool Errors & Retries's retry loops and L129 — Self-Reflection & Self-Critique's over-reflection.) A robust agent bounds recovery with three guards:

  • A recovery budget — cap the number of recoveries (and the total steps/cost). When it's spent, stop.
  • A loop detector — never retry an unchanged action that already failed, and detect a repeating failure signature. If you're seeing the same error a third time, more of the same won't help.
  • An escalation backstop — when the budget is exhausted or you're out of options, escalate: hand off to a human, ask for the missing input, or degrade gracefully (return partial results + what failed).

Escalation is not failure — it's the responsible ending. A clean handoff ("I couldn't book a flight; here are train options, your call") beats both an infinite spiral and a confident fabrication. The single most important guard is the simplest: after N attempts, stop trying and escalate. Every production agent needs that backstop, or it will eventually loop.

Think of it as a circuit breaker for plans (L125): CLOSED (executing) → too many recoveries → OPEN (stop, escalate). The loop must always have an exit.

The 2026 Nuance — Only Execution Reveals the Plan Failed

Like the rest of this section, reasoning models change part of the picture — but here, external replanning stays essential, and it's worth being precise about why.

A reasoning model can self-correct its reasoning internally (L129, L130 — Tree-of-Thought & Search-Based Reasoning) — but it cannot know that its plan failed in the world without executing it. "The flight is sold out," "the API returned 500," "the file wasn't there" — these are facts from the environment, information that no amount of internal thinking can produce. That's the irreducible role of the closed loop: execution generates the feedback; the harness detects it and decides to recover.

So in 2026:

  • The model handles much of the reasoning-level recovery (re-deriving a step, fixing its own logic).
  • Your harness owns the execution-level recovery — monitoring real results, detecting divergence, bounding retries, and escalating. As L125 (Handling Tool Errors & Retries) put it, the harness is ~98% of an agent's reliability, and recovery logic is the heart of it.

And this completes the whole arc of Section 4 — the loop every capable agent runs:

decompose (L127) → choose a plan/ReAct architecture (L128) → reason & reflect (L129) → search when stuck (L130) → and when reality breaks the plan, detect and recover (L131). Plan → act → monitor → recover → repeat. That is what it means for an agent to be robust.

🧪 Try It Yourself

Reason through these, then use the lab to confirm:

  1. Predict: in the lab, set Assumption broke → open-loop. What does the agent do, and why is open-loop wrong here?
  2. A step returns prices in EUR but the plan assumed USD; everything else is fine. Repair, replan, or backtrack — and why?
  3. Your agent's chosen API is permanently down and it has replanned around it 7 times, each failing. What guard is missing, and what should happen?
  4. Why is partial replanning usually better than global replanning?
  5. A reasoning model is great at self-correction. Why do you still need external replanning in your harness?

(1) With no monitoring it barrels ahead on the broken plan — tries to book the sold-out flight, then books a hotel for a trip that can't happen → cascade failure. Open-loop can't detect that the plan's premise died. (2) Repair in place — it's a minor mismatch and the plan is still valid; just convert € → $ and continue (AdaPlanner's in-plan refinement). Replanning would be wasteful; backtracking unnecessary. (3) A recovery budget + loop detector + escalation backstop is missing — it's spiraling. After N failed recoveries (or a repeating failure), it must stop and escalate (human / graceful degrade). (4) Partial replanning regenerates only the remaining/affected steps from the current state, so it keeps valid progress and is far cheaper than discarding everything and starting over. (5) Because only execution reveals that the plan failed in the world — "flight sold out," "API 500" are environment facts the model can't get by thinking. The harness must monitor real results, detect divergence, and recover.

Mental-Model Corrections

  • "A plan is a contract to follow." A plan is a guess made before results. Reality diverges — treat the plan as a starting hypothesis you monitor and revise.
  • "Make a good plan and execute it." That's open-loop — robust agents are closed-loop: monitor → detect → recover after every step.
  • "Recovery means replanning." Replanning is one option. Match the strategy to the failure: retry (transient), repair (minor), replan (premise broke), backtrack (dead-end), escalate (unrecoverable).
  • "When the plan breaks, start over." Prefer a partial replan from the current state — keep the progress that's still valid; a full global replan wastes the work already done.
  • "Just keep retrying/replanning until it works." That spirals. Bound recovery with a budget + loop detector, and escalate after N — the loop must have an exit.
  • "Escalating to a human is failure." It's the responsible ending for an unrecoverable case — far better than an infinite spiral or a confident fabrication.
  • "A reasoning model replans itself, so I don't need to." It self-corrects reasoning, but only execution reveals a plan failed in the world — the harness must monitor and recover.

Key Takeaways

  • A plan is the start, not the contract. It's made before results, so reality diverges — the agent must close the loop: monitor → detect → recover. Open-loop fails the moment anything goes wrong.
  • Detect divergence (you can't fix what you don't notice): tool error (L125), observation ≠ plan, failed assertion, stuck/loop, a critic, or a budget tripwire. Put checks in the executor.
  • The recovery menu — match strategy to failure: retry (transient) · repair (minor, in-plan) · replan (premise broke, out-of-plan) · backtrack (dead-end, L130 — Tree-of-Thought & Search-Based Reasoning) · reflect→retry (Reflexion, L129 — Self-Reflection & Self-Critique) · escalate (unrecoverable).
  • Replan smart: prefer a partial replan from the current state (keep valid progress) over an expensive global restart.
  • Don't spiral: bound recovery with a budget + loop detector, and make escalation the backstop — the loop must have an exit. Escalating is the responsible ending, not a failure.
  • 2026: models self-correct reasoning internally, but only execution reveals a plan failed in the world — execution-level recovery lives in the harness (~98% of reliability).
  • Section 4, complete: decompose (L127) → architecture (L128) → reflect (L129) → search (L130) → recover (L131) = the full plan → act → monitor → recover loop.
  • Next — Section 5: Memory for Agents (L132, Why Agents Need Memory): how an agent remembers across steps and across runs.