Planning
Design a bounded observe-act loop with explicit state, stopping conditions and a verifiable task outcome.
THE IDEA
Planning
A plan is the agent's hypothesis about how to reach the goal. It was made with incomplete information, so it can be wrong. When the first move works but the second hits a locked door, the right response is to update what the agent knows and plan again from where it stands, not to retry the same move forever. In the square of rooms the optimistic plan A, B, C costs 2 moves; discovering that B–C is locked turns it into 5 attempted actions in total.
A plan organises intended work; it is not a guarantee. When the evidence contradicts a step, revise it. If every route is blocked the honest outcome is stuck, not success.
Predict first. Does writing a detailed plan guarantee the environment supports it?
Chapter context
An agent chooses actions based on a task and observations, often over several model calls. Useful autonomy requires bounded resources, explicit feedback and a stopping rule that recognizes both success and inability to continue.
TRY IT YOURSELF
Part 1. Do it hands-on
Replan around a locked door by hand, then write a planner that learns from failures.
A plan organises intended work; it is not a guarantee. When the evidence contradicts a step, revise it. If every route is blocked the honest outcome is stuck, not success.
- To do: Four rooms in a square: A–B, B–C, C–D, D–A. Goal C from A. The optimistic shortest plan has how many moves?
- To do: The door B–C turns out to be locked once the agent stands in B. The revised path from B to C avoiding that door: how many moves remain?
- To do: Total actions attempted: move to B (ok), move to C (blocked), then the revised moves
- To do: Does writing a detailed plan guarantee that the environment supports it? Type yes or no
Part 2. Do it in code
- G (PROVIDED) is a square of rooms A–B, B–C, C–D, D–A. An edge is written as frozenset({a, b}).
- bfs_path(graph, start, goal, blocked=()): the shortest path as a list of rooms, visiting neighbours in sorted order, never crossing an edge in `blocked`; None if there is no path.
- plan_moves(path): ["move:<room>", ...] for every room after the first.
- run_plan(graph, locked, start, plan, limit=None): execute the moves in order. A move fails if the target is not a neighbour or the edge is in `locked`. Stop at the first failure or after `limit` attempts. Return {"room", "done" (successful moves), "failed_at" (index of the failed move or None), "attempted"}.
- agent(graph, locked, start, goal, max_actions=20): plan optimistically with no knowledge of locks, execute, and when a move fails remember that edge and replan from the current room. Count every attempted move (including failed ones). Return {"status": "done" | "stuck" (no path left) | "budget" (max_actions used up), "actions", "room", "known_blocked": sorted list of sorted tuples}.
Stuck, or something not working? You can come back to it any time.
CHECK YOUR UNDERSTANDING
Does writing a detailed plan guarantee the environment supports it?
Chapter reference: math, worked example & code
This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.
Math and notation
Represent a run as states s0,s1,... and actions a0,a1,... with observed transitions. A budget constraint can bound the sum of measured call costs. History-dependent token growth means a constant per-step estimate is only a simplifying model.
Worked example
A simulated agent may take at most three actions. It moves from room A to B, inspects a clue, then moves to C. The trace contains three actions. If the objective still is not satisfied, the correct result is budget exhausted with partial progress, not a fourth unapproved action or a fabricated success.
Reference code
The following example uses the Python standard library and does not call a remote service.
actions=['move:A->B','inspect:clue','move:B->C']
budget=3
assert len(actions) == budget
objective_satisfied=False
status='complete' if objective_satisfied else 'budget-exhausted'
assert status == 'budget-exhausted'
assert len(actions)*.002 == .006
Python examples are provided for study and local execution; this page does not execute Python.
Common mistakes
A plan is not execution evidence. Reflection can repeat the original mistake. A step budget is useful only if every executed action is counted consistently.