Skip to content

Handoffs and Advisors for Runs

A handoff is a typed decision point.

A handoff in a real run — the implement gate rejects, the run pauses for your call, you pick retry_feedback, and it loops back and recovers (press play, or scroll it into view):

run lifecycle · a real run · gate rejects, operator decides, recovers
  1. plan Claude
  2. validate_plan Codex
  3. implement Claude gate: broad-non-e2e
  4. review_changes Codex
  5. repair_changes Claude
  6. final_acceptance Codex
  7. delivery
A real run's lifecycle. The implement phase's broad-non-e2e gate rejects, so the run pauses for a human decision instead of shipping — the operator picks retry_feedback with fix tests, and the run loops back through implement and recovers. Gates are a trust boundary; you still hold the wheel. Driven by the run's phase.handoff_requested event.

It does not mean “the agent is confused” and it does not mean “the run is broken.” It means the selected profile or gate policy reached a point where continuing automatically would hide an important operator decision.

phase result -> handoff payload -> operator decision -> resume or stop
Control pointWhen it appearsMain surfaceTypical next action
Pre-run intakeCheckout already has uncommitted changes before the run starts.CLI promptinclude, exclude, commit, or halt
Phase handoffA phase policy pauses the run, usually after a rejected or incomplete verdict.awaiting_phase_handoffdecide, then resume
LLM handoff adviceA paused handoff needs a structured recommendation.orcho_handoff_advice tool, or the orcho_review_paused_run workflow recipeinspect advice, confirm, then decide
Resume pending decisionA client tries to resume a run that still has an unresolved handoff.orcho_run_resume resultdecide the handoff first
Delivery gate decisionFinal delivery or correction is parked after the run reaches a release state.orcho_delivery_gatedecide delivery or correction
Correction follow-upA terminal rejection needs new repair work.orcho_delivery_decide, orcho_run_startstart a child follow-up

These are related, but not interchangeable. A phase handoff resumes the same run after a decision. A correction follow-up starts new work because the parent run reached a terminal rejection.

Phase handoff is the core mechanism.

It appears as:

status = awaiting_phase_handoff
meta.phase_handoff = {
handoff_id,
phase,
verdict,
available_actions,
findings
}

The normal MCP flow is:

orcho_run_status(run_id)
orcho_run_evidence(run_id, slice="findings")
orcho_phase_handoff_decide(run_id, handoff_id, action, feedback?)
orcho_run_resume(run_id)

The decision tool writes the decision artifact. It does not advance execution by itself. For continue, retry_feedback, and continue_with_waiver, resume the run after the decision is recorded. For halt, the run is terminal.

ActionMeaningFeedback requiredWhat happens next
continueProceed despite the handoff verdict.noRecord override, then resume.
retry_feedbackGive the worker or reviewer a concrete correction and run another attempt.yesRecord feedback, then resume into the next attempt.
continue_with_waiverAccept the finding as known risk and continue with a durable waiver.yesRecord waiver text, then resume.
haltStop the run at this handoff.noMark the run halted. Do not resume.

Use retry_feedback when the finding should be fixed. Use continue_with_waiver only when the operator intentionally accepts the risk. Do not use continue as a way to avoid reading the findings.

An LLM advisor is not the handoff decision.

The advisor reads the paused run and recommends the smallest honest next step. It can return a recommended action, confidence, rationale, risks, suggested retry feedback, expected files, and a durable advice artifact.

This is what the advisor looks like in a real run: the review_changes gate rejects with a P1 finding, the handoff offers six actions — two of them advisor-powered — and the operator picks retry_with_advice. An handoff_advice LLM step then reads the findings and drafts the repair feedback in ~12 seconds; the operator confirms, and it loops into repair_changes. The advisor prepares the next move but never takes the decision (press play, or scroll it into view):

handoff advisor · a real run · the LLM drafts the fix, you still choose
  1. review_changes REJECTED
    P1
    Summary gates marks non-success states as successful pipeline/project/run.py:174 — the gates glyph shows even when a gate is MISSING, STALE, or carries an errors: line
  2. The run pauses. The handoff offers six actions — two of them ask an LLM advisor for help:

    • 1 ✅ continue accept the verdict, run the rest
    • 2 🔁 retry_feedback retry with operator feedback
    • 3 🛑 halt terminate the run
    • 4 📝 continue_with_waiver accept with a durable waiver
    • 5 💡 advice LLM explains + recommends a step
    • 6 🤖 retry_with_advice LLM drafts repair feedback, then retries

    operator picks 6 · retry_with_advice — let the advisor draft the fix

  3. handoff_advice · codex · reading the findings… ✓ 11.8s · ~$0.087
  4. advisor drafted the repair feedback →
    Fix _gate_summary_line() / _failing_gate_names() so the final gates glyph accounts for every non-success state — at least FAIL, MISSING/STALE, and the presence of an errors: line. Add a summary test so those inputs render ✗ gates … and never pass as ✓ gates.

    advice is a draft, not a decision — the operator still confirms; the note keeps the advice provenance.

  5. retry_feedback · with advice repair_changes · round 2
The advisor half of a handoff. A real run's review_changes rejects with a P1 finding; the operator chooses retry_with_advice, and an handoff_advice LLM step reads the findings and drafts the repair feedback — then the operator confirms and it loops into repair_changes. The advisor prepares the next move; it never takes the decision. Driven by the run's phase.handoff_requested and advice artifact.
orcho_handoff_advice(run_id, handoff_id?)

For MCP clients, orcho_review_paused_run is a guided workflow recipe — a step-by-step prompt the server publishes, not a tool the client calls. It walks the client through the same loop: read status, read findings, propose a decision, wait for operator confirmation, then call orcho_phase_handoff_decide.

For interactive and MCP-led operation, the boundary is strict:

  • advisor writes advice, not a decision;
  • advisor can prepare a ready next action, but it is not applied automatically;
  • operator confirmation is still required for the actual handoff decision;
  • the decision note should preserve advice provenance when advice was used.

--no-interactive changes the handoff question because there is no terminal operator to ask.

For eligible rejected or incomplete handoffs, Orcho can run a bounded CI advice path: ask the advisor for retry feedback, evaluate safety gates, write ci_agent provenance, and retry through the same handoff decision/resume path used by human feedback.

That path is intentionally narrow. It can retry the honest, low-risk case, but it stops for waiver, destructive action, out-of-scope files, low confidence, repeated blockers, or exhausted budget. A stop leaves typed state for a later operator or client decision instead of pretending the run succeeded.

Read Unattended runs and CI for the full non-interactive operating model.

When advice exists, the evidence bundle can include handoff_advice.

That section answers:

  • how many advice calls happened;
  • which action was recommended;
  • which action was actually applied;
  • whether an applied retry resolved, repeated, stopped, or stayed unknown;
  • how much observe-only advisor usage was recorded.

This matters because advice should be inspectable after the run. A useful advisor is not merely one that sounded reasonable in the moment. It should leave enough evidence to ask whether it helped.

Delivery gate decisions happen after the run reaches a release or correction state. They are not phase handoffs.

Use:

orcho_delivery_gate(run_id)
orcho_delivery_decide(run_id, action, note?)

Common actions:

ActionMeaning
approveCommit the retained worktree diff into the target checkout.
applyApply the retained diff without committing it.
fixMark the run correction-ready after a rejected release verdict.
skipClose the gate without changing the target checkout.
haltLeave the retained worktree for manual inspection.

If the decision is fix, the next step is usually a correction follow-up, not a checkpoint resume.

If the client lost the run id or context, use the workspace decision inbox:

orcho_workspace_pending_decisions

It lists runs paused on actionable handoffs. Use it to recover the decision context, not to guess from old terminal output.

  • Do not call orcho_phase_handoff_decide twice with different payloads for the same handoff.
  • Do not resume a run that is still awaiting_phase_handoff.
  • Do not treat LLM advice as if it were already applied.
  • Do not hide continue_with_waiver from the operator.
  • Do not use delivery decisions to patch files by hand through MCP.
  • Do not start a correction follow-up when checkpoint resume is the correct continuation.

The canonical engineering doc lives with the code: