Agent Planning: Turning Goals into Executable, Revisable State Diagrams
Understand planning–execution separation, rolling planning, checkpoints, and local replanning through goals, preconditions, artifacts, and completion predicates.
1Why a checklist of steps is not yet a planIntuition
When assigning a task to an AI Agent, the most common approach is to write down a sequence of natural-language steps, such as “read code—modify—test—commit.” This sequence looks complete: it covers all stages from understanding to implementation, and the order is reasonable. But when you hand it to the AI Agent, it may still go wrong at the first step. The reason is not that there are too few steps, but that the steps are not connected to the facts on which execution depends.
A natural-language checklist lacks four things. First, it does not say which files to read: the task is to fix a bug, and the codebase has dozens of files; the “read code” step cannot tell the executor which module to open, so the executor can only guess, or scan all the files. Second, it does not say which facts the “modification” depends on: which line to change, what behavior to preserve, which test constrains this change—the checklist records none of this, and after making the change the executor cannot prove that it was changed correctly. Third, “when a test counts as passing” is not defined: running a test command and the test passing are two different events; the former is a tool call, the latter is an objective fact that must be proved by assertion results. Fourth, it does not state where to go back after failure: if the test fails, should we go back to “read code” to understand again, or go back to “modify” to try a different change? The checklist gives no answer; the executor has to decide on its own, and deciding on its own often means losing context.
A more subtle problem is that the checklist mistakes “calling a tool” for “goal completion.” Writing “commit” does not mean the code has entered the main branch; writing “test” does not mean the defect has been verified as fixed. A tool call is just an action; after the action is completed, whether the world state has actually changed must be proved by external observation—check test reports, check merge results, check runtime logs. The checklist erases the boundary between action and state, so the executor can tick off items one by one yet never reach the goal.
What an executable plan must do is transform this checklist into a sequence of state changes in which every step can be checked and proved. It must refer to the current world state, not to dangling verbs; it must specify for each step the precondition (what must already hold when entering this step), the action (what to execute), the artifact (what observable change is added to the world after this step), and a machine-checkable completion predicate (what condition is used to determine that this step is truly complete), and it must leave traceable evidence for each state change. With these fields, “when is it really complete” and “where to go back after failure” finally have definite answers.
Three layers need to be distinguished here. The goal is the world state that the AI Agent wants to reach, for example “the defect is fixed and all related tests pass.” The plan is a hypothesis about causal relationships: it asserts “if these actions are executed in sequence, the world will transition from the current state to the goal state.” This hypothesis is not necessarily true; the role of execution and observation is to test it: after each step, the observer confirms whether the world really changed as expected; once a deviation is found, it means the plan's hypothesis was wrong, and the plan needs to be revised, rather than continuing down the original checklist.
Therefore, the input to an executable plan consists of five things: goal, current world state, constraints, available tools, and risks; the output is a state graph with preconditions, actions, artifacts, completion predicates, and fallback paths. The core problem it solves is the two questions that a natural-language step checklist cannot answer—“when does it truly count as complete” and “where to go back after failure.” In the state graph, a tool call is just one value of the action field and can never replace the completion predicate; the world state must be proved by external observation, not by the executor's self-reported completion.
2How Do the Planner, Executor, and Observer Divide Responsibilities?Mechanism
Handing planning, execution, and observation to the same AI Agent—letting it think and directly modify all states at once—poses the greatest risk of confusing “thinking” with “doing”: the model judges during its reasoning that a step has been completed, so it writes “completed” in the plan; this text is then treated as actual completion in the world, and all subsequent steps are built on this unverified assumption. Once there is a fabrication along the way, the whole chain collapses. Therefore, the planning system splits the work across three roles, and each role produces only one kind of thing: the planner produces plans, the executor produces actions, and the observer produces facts. The three outputs are kept separate, and none of them can testify on behalf of another.
The planner’s inputs are the goal, constraints, and the currently known state. It does not make any modifications; it does only one thing: it expands these inputs into a finite-horizon dependency graph—each node is a step, and each edge means “which must be completed before which can start.” A finite horizon means the planner makes precise arrangements only for the near-term trustworthy parts, while distant parts are kept as placeholders and refined only after observation brings new facts. In this way the planner neither fabricates long chains out of thin air when information is insufficient, nor wastes effort on far-off details that will soon become invalid.
The executor’s inputs are the dependency graph and the current state, and its responsibility is minimized: it executes only the nodes that are currently ready. “Ready” means that all of the node’s predecessors have been verified as completed by the observer. The executor has no authority to decide “close enough to start,” nor is it responsible for judging whether the result is good or bad; it applies the action to the world and then hands over the result. This constrained execution ensures that every action happens after its preconditions are established, not in the planner’s imagination.
The observer is the only role authorized to write the world state into facts. It reads the objective traces left by execution—command exit codes, file diffs, test reports, logs—and translates these traces into factual states. An exit code of zero is one fact; all test assertions passing is another fact, and the two cannot replace each other. The observer’s output does not pass through the executor’s retelling, nor through the planner’s inference, so “completed” in the plan cannot masquerade as real completion: only facts recorded by the observer can move a node from “executed” to “completed.”
The controller glues the three together into a loop. It compares each node’s expected effect with the actual observation: if the observed result matches the expectation, it writes the factual state back, marks the node as completed, and then advances to the next batch of ready nodes; if the observed result deviates from the expectation, the controller chooses among four actions—retry (do the same step again), rollback (undo the changes that have already happened), proceed (continue with subsequent nodes), or local replanning (redraw only the affected part of the dependency graph). The whole causal chain can be written as:
Goal and forbidden states → dependency graph → select ready nodes → constrained execution → observation and verification → update state → proceed or local replanning.
Note that the chain’s starting point contains both the goal and forbidden states. Planning not only specifies what to reach, but also what must not be entered: intermediate states that violate constraints need to be identified by the observer and intercepted by the controller just as much as final states do. The inputs to the role division are the goal, constraints, dependency graph, ready nodes, execution results, and external observations; the output is one of four: proceed, retry, rollback, or local replanning. In this way, every state change has a clear producer and verifier, and no link in the chain can unilaterally declare success.
3What fields should a step contain?Task contract
Disagreement between the executor and the verifier about the criteria for “done” is the common root of all execution incidents. The executor thinks that having run the commands means done, but the verifier requires that the world state has actually changed; the executor says “I have understood it,” but the verifier wants to see the code and tests. In order for both sides to have the same meaning for the same word, every step must be written as a machine-readable task contract. The contract consists of five fields: preconditions, actions and tools, artifacts, completion predicate, and rollback. Missing any one of these fields corresponds to a typical failure mode.
Take a cache isolation fix as an example. The symptom is cross-user value leakage: two users read each other's cached data. The five fields for this node are written as—preconditions: the cross-user value leakage has been reproduced and the relevant cache code has been located; actions and tools: modify the key construction logic with a minimal patch; artifacts: a patch diff and an isolation regression test; completion predicate: both the isolation test and the original hit test pass; rollback: revert the patch and keep the failure log.
Look at the cost of missing each field. Without preconditions, the executor can only guess and modify the module it thinks is wrong, and may edit the wrong file on the first step. Without a limited action scope, the execution scope expands without bound: originally just modifying the key construction, it conveniently refactors the cache layer and changes the serialization format, turning a small fix into a large-scale change. Without artifact requirements, what the executor delivers is only claims in the chat log; “I've fixed it” cannot be inspected by anyone. Without a completion predicate, the executor treats “ran the tests” as “tests passed”—the test command was indeed executed, but the assertion failures are set aside. Without a rollback path, the only choices after failure are to start over from scratch or to stack modifications on the original patch; the former wastes all completed facts, and the latter lets errors accumulate layer by layer.
The completion predicate is the field most easily written incorrectly among the five. It must check the world state, not intentions or actions. Legitimate predicate forms include: the file hash matches the expected value, the test count reaches a threshold, the API returns the agreed-upon structure, the approval record already exists. Expressions like “I have understood” and “the tool was invoked” are never completion predicates—the former checks the executor's inner state, the latter checks whether an action occurred, and neither is related to whether the world has changed. In this example, the predicate requires two sets of tests to pass simultaneously: the isolation test proves the fix itself is effective, and the original hit test proves the fix does not break existing behavior. A predicate that merely says “ran” will be rejected, because “ran” carries no assertion about the result.
For high-risk nodes, the contract also adds two declarations: the approval authority and forbidden states. The approval authority specifies who has the right to confirm that this node can proceed to the next step, preventing the executor from self-acceptance; the forbidden states spell out world states that must absolutely not be entered on this path, such as “do not clear the cache directory during the repair,” so that the observer knows what to intercept. Thus, the input of a task contract is the precondition facts, limited actions, observable artifacts, machine completion predicate, rollback plan, and approval authority; the output is a node definition shared by the executor and the verifier. The executor executes according to the contract and delivers the diff and tests in the artifact field; the verifier only acknowledges the completion predicate. The two sides no longer need to argue about the word “done.”
| Field | Cache isolation fix example | Risk if missing |
|---|---|---|
| Preconditions | Cross-user value leakage reproduced; relevant cache code located | Modify wrong module by guessing |
| Action/Tool | Minimal patch modifies key construction | Execution scope expands without limit |
| Artifacts | Patch diff + isolation regression test | Only claims in chat |
| Completion predicate | Both isolation test and original hit test pass | Treat "ran the tests" as "tests passed" |
| Rollback | Revert the patch and keep failure log | Start over from scratch or stack modifications after failure |
4How to draw a repair task as a dependency graphWorked example
Drawing a dependency graph answers two questions: which steps can run in parallel, and which steps must wait for real evidence. Take the cache isolation fix as an example; the task is broken into five nodes: S0 reproduce (5 minutes), S1 locate (8 minutes), S2 contract (3 minutes), S3 patch (6 minutes), S4 verify (10 minutes). The number on each node is the estimated duration, and the arrow on an edge indicates the dependency direction. The process of drawing is to ask each node: “Before entering it, which step’s facts must have been confirmed by the observer?”
S0 reproduce has no dependencies; it is the starting point of the entire graph. S1 locate depends on S0: only after reproducing the cross-user value leakage does locating the relevant cache code become meaningful. S2 contract also depends on S0: the preconditions, predicates, and rollback to be written in the contract all come from the phenomena and facts obtained from reproduction. Therefore S1 and S2 share the same predecessor node, and after S0 completes they have no dependency on each other—they can run in parallel. S3 patch depends on both S1 and S2: if the code location is not complete, there is no way to start the patch; if the contract is not determined, it is unclear what deliverable the patch should produce and by what predicate it should be accepted. S4 verify depends only on S3: the object of verification is the patch itself.
The dependency graph gives every “can they run in parallel” judgment a basis: parallelism occurs only between nodes that share a predecessor and have no edge between them; whenever a dependency edge exists, they must wait, and what they are waiting for is not time, but real evidence—the observer confirms that the predecessor node's completion predicate has been established.
The dependency graph also directly gives the critical path. Summing the five nodes serially gives 5+8+3+6+10=32 minutes. After letting S1 and S2 run in parallel, the two branches are S0→S1 (5+8=13) and S0→S2 (5+3=8), merging at S3; S3 must wait for both branches to complete, so its earliest start time takes the larger of the two, 13 minutes. Thus the earliest completion time of the entire chain is the critical path S0→S1→S3→S4, i.e., 5+8+6+10=29 minutes. The only time saved by parallelism is the 3 minutes not on the critical path—the period during which S2 finishes earlier than S1 was already idle waiting. This result illustrates a boundary of the dependency graph: parallelism can compress only branch waiting, not the strongly dependent chain itself; promoting strongly dependent tasks as “arbitrarily faster after parallelization” is wrong, and 29 minutes is the lower bound of this graph under the current constraints.
The inputs to the dependency graph are the node definitions from S0 to S4, the dependency edges, and the estimated durations of 5/8/3/6/10 minutes; the outputs are three things: the parallel ready set at each moment, the critical path, and the earliest completion time of 29 minutes. The ready set changes over time—initially only S0; after S0 completes it becomes {S1, S2}; after both complete it becomes {S3}, then {S4}. Each round the executor only takes nodes from the ready set, which is exactly the implementation of the previous section's “only execute ready nodes” rule.
This graph also determines the scope of redoing after a failure. Suppose S4 verification fails, and a local redraw is needed. Only the patch node and its downstream are invalidated: S3's patch was wrong, so S4 is naturally void. But S0's reproduction facts and S2's contract investigation have already been verified by the observer; they are not within the invalidated scope and do not need to be cleared and redone. The dependency graph turns “which facts have already been established” into structure, and when failure comes, replanning happens only in the invalidated region.
Scroll horizontally to view the full diagram on small screens.
| Node | Estimated 5/8/3/6/10 minutes | Dependency | Earliest completion |
|---|---|---|---|
| S0 Reproduce | 5 | None | 5 |
| S1 Locate | 8 | S0 | 13 |
| S2 Contract | 3 | S0 | 8 |
| S3 Patch | 6 | S1, S2 | 19 |
| S4 Verify | 10 | S3 | 29 |
5Why Use Receding-Horizon PlanningUncertainty
The more unknown the environment, the less you should predefine twenty steps in rigid detail. The reason is an asymmetry in information itself: the input state for nearby steps is already available, and the observer has provided the facts, so these steps can be made concrete enough—precise down to files, commands, and predicates; while distant steps depend on tool outputs that have not happened yet, and those outputs do not exist at this moment, so any “details” anyone writes now can only be guesses. Forcing this level of detail would make the model fabricate files, interfaces, or results that do not yet exist in order to fill out the list, producing a plan that is rhetorically complete but factually false.
Receding-horizon planning represents the same graph in two segments. The near segment is expanded into concrete nodes; the far segment only keeps coarse goals and budget, such as “complete the cache refactor, expected to take four steps within two rounds,” without writing the actions for each step. After execution reaches a new high-uncertainty point—some tool has produced an output, some acceptance check has produced a conclusion—the observation brings new certain information, and only then do you expand the next segment into concrete nodes. The whole process is isomorphic to receding-horizon control: you precisely control only the visible window in front of you, the window slides forward as execution advances, and distant details are never generated until they can be seen.
The direct benefit of receding-horizon planning is fewer stale plans. A long plan written in advance may already be invalid by the time the second observation arrives, while in receding-horizon planning the invalid parts exist only in coarse goals that have not yet been expanded, so the cost of replacing them is close to zero. At the same time, receding-horizon planning removes the motive to “fill out the list” from the model: the list never required distant details, so fabrication no longer has a reason to exist.
Rolling updates have one discipline that must be followed: each update replaces only the subgraph affected by the new observation, preserving the goals and safety invariants unchanged. The goals and safety invariants are the premises on which the whole graph holds; observations can affect only “how to get there,” not “where to get to” or “what must never be entered.” Alongside this is versioning: each rolling update of the plan forms a new version, and the version records what evidence triggered this update and which nodes were invalidated. With this record, you can later audit each change to see which observation caused it and which part of the graph was altered, rather than having a text that has been repeatedly overwritten with no one knowing its provenance.
There is also a more hidden risk: a new observation may conflict with old state. For example, the observer reports “the cache module has been deleted,” while the plan still says “the cache module has been located.” The correct order at this point is to mark the conflict first, then determine the authoritative source—is the observer misreading the environment, or is the old state simply outdated? In any case, the last written text must not silently overwrite verified facts; the old fact was established by some evidence, and if a new fact is to overturn it, its source must be recorded so that the conflict between the two can be inspected.
Receding-horizon planning can therefore be summarized as an input-output loop: inputs are the known near-term state, uncertain distant dependencies, new observations, and the goals and safety invariants; outputs are concrete nodes in the near term, coarse goals in the distance, and the new version of the subgraph. At each high-uncertainty point, expand the next segment; each replacement is limited to the subgraph affected by the observation and records the triggering evidence and invalidated nodes; new text can update the plan, but cannot silently overwrite verified facts.
6How to Replan Locally After FailureRecovery
When a test fails, the most expensive reaction is to “draw up a complete plan again.” Full replanning means tearing down already validated artifacts and redoing them: re-collecting reproduction facts, redoing dependency analysis, rewriting contracts that have already been written. The facts underlying these steps have not changed; redoing them is duplicated work, and each round of repetition introduces new opportunities for error. The correct approach is to first classify the failure into one of four categories, each corresponding to a clear update scope.
The first step is always to compare the expected effect of the failed node with the actual observation. The expectation is written in the node contract, and the observation is given by the observer; the type of difference between the two determines what to do next.
The first category is transient execution errors: the action itself and its preconditions are fine, but the external conditions for this run broke down, for example test process timeout or temporary network jitter. The update scope is the current node; the handling strategy is limited retries under an idempotency policy—retries have an upper limit, the action itself must be repeatable, and retries leave no accumulated side effects.
The second category is precondition fact errors: the node fails not because of itself, but because the precondition it relies on to start does not hold. For example, if the premise of a fix is “the application uses first-level cache” but it actually uses second-level cache, then the entire call chain was located incorrectly. The update scope is the fact source and all its downstream; the handling strategy is to go back to the nearest node that produced that fact and investigate again, rather than continuing to patch on the incorrect premise.
The third category is patch side effects: the precondition facts hold, and the patch solves the target problem, but it introduces new breakage—cache isolation is fixed, but the hit rate drops to zero. The update scope is the patch node and the acceptance nodes; the handling strategy is to invalidate only the patch and its downstream, keeping already validated artifacts such as reproduction, localization, and contracts unchanged.
The fourth category is a change in goal or forbidden state: the task itself has changed, for example from a single-tenant fix to a cross-region consistency migration. This is the only situation that requires expanding the replanning scope, because all dependencies must be re-examined against the new goal.
These four categories can be viewed side by side as a comparison table. Transient execution errors correspond to the current node; an example is a test process timeout, with limited retries. Precondition fact errors correspond to the fact source and its downstream; an example is actually using second-level cache, requiring re-localization of the call chain. Patch side effects correspond to the patch and acceptance nodes; an example is isolation fixed but hit rate zero. Goal change corresponds to re-checking all dependencies; an example is changing from a single-tenant fix to a cross-region consistency migration. The update scopes of the four categories grow in order, and only the fourth touches the global scope.
For local replanning to work, it also depends on one piece of infrastructure: already validated artifacts must be pinned with stable IDs and versions. Reproduction results, contracts, and passed tests each carry immutable identifiers and version numbers, and during replanning they are referenced directly rather than having the model search again and generate a new copy. Without this pinning, replanning itself becomes a new round of searching and overwriting; the model may find a similar but different old artifact and continue using it as the original fact. After version pinning, rolling back a patch means referencing the node version before the rollback, rather than manually undoing several stacked modifications.
The input to local replanning is therefore five things: the failed node, the difference between expectation and actual observation, stable checkpoints, dependency downstream, and the failure type. The output is one of four actions—limited idempotent retry, return to the nearest fact source, invalidate the patch subgraph, or full replanning. A failure triggers only the minimal update commensurate with its type; validated facts are protected by version numbers, and duplicated work is excluded by design.
| Failure type | Update scope | Example |
|---|---|---|
| Transient execution error | Current node | Test process timeout, limited retries |
| Precondition fact error | Fact source and its downstream | Actually uses second-level cache, re-localizing the call chain |
| Patch side effect | Patch and acceptance nodes | Isolation fixed but hit rate drops to zero |
| Goal change | Re-check all dependencies | From single-tenant fix to cross-region consistency migration |
7When should planning give way to workflow or searchBoundary
Not every long task requires a language model planner. Planning has a cost: every extra layer of planning adds an extra layer of inference that could go wrong and an extra piece of plan text that needs auditing. The choice of execution mechanism depends on three attributes of the task itself: path predictability, action space size, and degree of environment dynamics.
When steps are fixed, branches are known, and failure semantics are stable, a deterministic workflow is the better choice. All paths of such tasks are determined at coding time, and the behavior on failure is also defined in advance. Execution with a workflow is cheaper and more testable—the same input always follows the same path, and regression tests can cover every branch. Introducing a language model planner instead turns something certain back into something uncertain, needlessly increasing cost and the surface for errors.
When candidate actions are clear and can be exhaustively enumerated, tree-of-thought or traditional search is more appropriate. The task becomes selecting and backtracking within a finite set of candidates; expansion, evaluation, and pruning are all mechanical operations. The completeness and efficiency of the search algorithm can be computed directly, without relying on the model's ad hoc judgment each time. The planner here adds no new information, only new noise.
Only when the environment path is unknown and tool feedback changes subsequent decisions does AI Agent planning become truly valuable. Cache repair is a typical task of this type: the length and direction of the call chain are known only after the first exploration results, how the contract should be written depends on what the reproduction observes, and each time a tool returns output, the decision space for what follows changes. In such tasks, the planner's role is to continuously redraw the subgraph based on new evidence, which is exactly the mechanism described in the previous sections.
The three criteria can be condensed into one sentence: fixed branches use workflows, enumerable candidates use search, and only unknown environment paths require AI Agent planning.
No matter which mechanism is chosen, there is a boundary that cannot be crossed: the planner cannot replace tool permissions, transactions, idempotency, and human approval. These four things belong to execution safety, enforced by external systems rather than declared by plan text. Writing “file backed up” or “user approved” in a text plan is just two strings; they can appear, but they have no factual effect. The controller must read from the file system whether the backup actually exists, read from the approval service whether the approval actually occurred, and read from the tool return code whether the action actually executed. The model cannot announce on its own that high-risk preconditions have been met—self-announcement is a wish written into the text, whereas high-risk steps require records in external systems.
Therefore, the determination of planning boundaries can be formalized as an input-output mapping: the inputs are path predictability, action space, environment dynamics, tool feedback, and risk permissions; the output is one of four: fixed workflow, traditional search, tree-of-thought, or AI Agent planning. After the mechanism is chosen, permissions, transactions, idempotency, and approval are still uniformly enforced by external systems, regardless of which mechanism is chosen; “backed up” or “approved” in the text does not constitute a fact under any mechanism.
8How to evaluate plans without rewarding polished textEvaluation
Final success is the easiest metric to manipulate: a verbose and inefficient plan may also succeed, because success only indicates that the goal was reached, not how the journey went. Evaluating a plan must answer two questions at once: whether it actually has flaws, and whether it creates more value than simpler alternatives. The method is to record three trajectories in parallel for the same task—direct action, fixed workflow, and planner—and then compare a set of metrics.
This set of metrics includes eight dimensions. Final success: whether the task reaches the goal; this is a passing line, not the whole story. Plan executability rate: how many steps in the plan are actually executed; if many nodes are invalidated or skipped along the way, it indicates a large deviation between plan and reality. Precondition errors: how many steps are started when their preconditions are not met, directly exposing gaps in the dependency graph. Invalid or duplicate steps: how many steps do not advance state, or repeat work already done. Number of replans: how many times the plan is overturned; the more often, the less credible the initial plan. Distance from failure point to recovery point: how far back execution must retreat after a failure before it can move forward again; the shorter the distance, the more finely the dependency graph is sliced and the more effective local recovery. Critical path delay: how much later the actual execution is compared with the theoretical critical path; the excess comes from waiting, rework, or erroneous serialization. Total cost: the actual tool calls and time consumed to complete the same task.
Among these eight metrics, the combination of cost and success rate is the best at exposing plans that are “polished but useless.” If a planner turns 8 tool calls into 20, and the success rate is the same as direct action, it has created no value—the extra 12 calls are all overhead, with no corresponding benefit. Conversely, if the planner has a higher success rate and shorter recovery distance in failure scenarios, the extra calls gain justification. Evaluation is therefore always comparative: the value of the planner exists only in the difference from simpler baselines.
In addition to post-execution trajectory comparison, there are two kinds of pre-execution static checks. The first kind targets the plan text itself: whether referenced tools actually exist; whether the dependency graph has cycles—a cycle means there is a set of nodes in the graph that can never become ready; whether every node has an artifact and a completion predicate—a node without a predicate cannot be accepted, which amounts to handing completion back to guesswork; whether parallel nodes compete for the same resource—two nodes modifying the same file at the same time will corrupt each other and must be serialized or locked. The second kind targets recovery capability, verified through fault injection: artificially create one tool failure and one precondition violation, and observe whether the plan retries within the expected limit and whether it retreats only to the nearest source of truth. Polished text has no place to hide in the face of fault injection; truly effective local recovery must be able to be triggered and verified repeatedly.
Thus, the input to plan evaluation is three trajectories on the same task: direct action, fixed workflow, and planner trajectories; the output is eight metrics: final success, executability rate, precondition errors, duplicate steps, number of replans, recovery distance, critical path delay, and cost. First perform static checks—tools exist, dependency graph has no cycles, nodes have artifacts and predicates, parallel nodes do not contend for the same resource—then use fault injection to verify local recovery. A long, polished plan that merely doubles the calls while success remains unchanged does not constitute any value by its polish.
9Connecting the Causal ChainSynthesis
Connect the content of the previous sections end to end, and you get a complete causal chain from problem to verifiable practice. The starting point is a concrete problem: a natural-language step checklist cannot answer “when is it truly done” and “where to return after failure”, because tool calls are miswritten as goal completion and world state is not proven by anyone. The endpoint is a planning mechanism that can be executed, audited, and verified through fault injection. Every step in between builds on the output of the previous step.
Step one: define goals and forbidden states. Planning starts by clearly writing down two state sets: what to reach and what must never be entered. The goal is the final predicate for acceptance; forbidden states are red lines that the observer must intercept at all times. Without this step, all subsequent judgments have no reference point.
Step two: annotate preconditions and artifacts. Each step changes from a narrative into a node contract: which proven facts are required to enter it, and which observable artifacts it leaves behind when exiting. This step moves the meaning of “done” from the executor’s inner state to the world state.
Step three: construct the dependency graph and critical path. Edges between nodes indicate which facts must be established first, which steps can therefore run in parallel, and which must wait for real evidence. The critical path gives the earliest completion time and also delineates which verified artifacts can be retained in case of failure.
Step four: execute only currently ready nodes. Each round, the executor takes nodes only from the ready set—nodes whose all predecessor nodes have been confirmed complete by the observer. This constraint ensures every action occurs after its preconditions are established, rather than in the planner’s imagination.
Step five: update state with real observations. Exit codes, file diffs, test results, and approval records are translated by the observer into facts; the controller compares expected with actual and decides to advance, retry, roll back, or replan. The word “done” in the plan text no longer has any effect from this point on; only observation records can move the chain forward.
Step six: local replanning from stable checkpoints. Failures are categorized by type into the minimal update scope: transient errors are retried a limited number of times; precondition fact errors return to the nearest source; patch side effects invalidate only the patch and its downstream; only a change in goals expands replanning. Verified artifacts are fixed with stable IDs and versions, so duplicated effort is excluded.
The six steps each answer one question on the chain, while the chain as a whole answers the original one: how to turn goals into an executable, revisable state graph. Executable, because each node has preconditions, artifacts, and a completion predicate; revisable, because observation-driven rolling updates replace only the affected subgraph and recover locally from stable checkpoints. The output of planning changes from a piece of polished text into a state machine—each step has a clear producer, verifier, and rollback path, and no link can unilaterally declare success.
- Plan-and-Solve Prompting: plan first, then solve
- ReWOO: Decoupling Reasoning from Observations: decouples planning from tool observations
- Language Agent Tree Search: planning, search, and environment feedback
- ReAct: action-observation loop