pub enum NextMove {
Batch {
purpose: String,
steps: Vec<Step>,
},
Done {
summary: String,
extracted_data: Value,
},
Fail {
reason: String,
},
Clarify {
question: String,
},
}Expand description
What the reactive planner decides to do next, given the current state.
Each turn of the agent loop is: observe → ask planner for the next move → execute it → observe again. The planner never commits past the next batch; if the first step of a batch reveals something surprising the planner will see it on the next call and pivot.
The old “upfront Plan with a fixed list of SubGoals” is gone — it forced the LLM to commit to a structure before it had perception, which meant Numbers-on-launch-shows-Open-dialog and similar surprises broke whole runs.
Variants§
Batch
Execute this batch of steps one after another, then ask the planner again. A batch is “commit to this short sequence” — typically 1–5 steps. Larger commitments are a smell; use smaller batches and trust the loop to re-plan.
Fields
Done
Goal achieved — return success.
Fail
Give up — goal can’t be completed given the state.
Clarify
Refuse to act — the goal is too ambiguous or destructive to attempt safely, and the planner is asking the user for clarification instead of guessing.
Terminal like Fail, but distinct in intent: the agent isn’t
stuck, it’s deliberately declining to act on insufficient
information. Surfaced as GoalOutcome::Refused with question
in the summary so the eval harness, CLI, and MCP server can
display it back to the user without rendering it as an error.
Use cases (see NEXT_MOVE_SYSTEM_PROMPT for the prompt rule):
- “Delete it” with no clear referent on screen.
- “Send the email” with no recipient identified.
- Destructive prompts (delete / overwrite / send / pay) without explicit confirmation in the goal text.