Agent Planning: Workflows, HTN, Plan-Execute
Pick a workflow, an HTN or evolutionary planner, or a replanning executor. Stdlib Python from the lessons.
- Concepts and terms
- Tasks and commands
- Annotated code
- Diagrams
- Comparisons
- Defaults and numbers
- Troubleshooting
- Questions and tips
Pick a planner#
| Factor | Workflow | HTN + ChatHTN | AlphaEvolve | ReAct / ReWOO |
|---|---|---|---|---|
| Who decides | Engineers | Symbolic layer | Evaluator selects | The model |
| Guarantee | Bounded step count | Provable soundness | Best plan by fitness | No formal guarantees |
| Needs | Steps you can enumerate | Operator schema | Machine-checkable fitness | LLM in the loop |
| Fits | Predictable, compliance-bound | Scheduling, policy-bound | Compiler optimization | Open-ended research |
| LLM role | Calls on fixed code paths | Fallback decomposition | Proposes mutations | Picks each step |
Five workflow patterns in code#
| Task | Code |
|---|---|
| Prompt chaining: output N is input N+1 | prompt_chain(input_text, |
| Routing: classify, then dispatch | route(input_text, |
| Parallelization: N runs, majority vote | parallel_vote(prompt, |
| Orchestrator-workers: pick specialists | orchestrator_workers(task, |
| Evaluator-optimizer: loop until PASS | evaluator_optimizer(task, |
| Unknown route label | handlers.get("default") gives "escalate to human" |
| Run all five demos | python3 code/ |
Evidence plan waves#
Run a replanning agent#
agent = PlanExecuteAgent( planner=make_deterministic_planner(fail_step_id=2, recovery="route_around"), executor=executor,(tool_name, args) -> result, raises ToolFailure max_steps=12, max_replans=5,both budgets are hard)res = agent.run("ship the report")res.status, res.reason"completed" and "goal_met"res.revisionslist of PlanDiffr.to_dict()revision, removed, added, revisedStep(2, "transform", {"mode": "v2"}, "computed via fallback")HTN planner with LLM fallback#
op = Operator("open_editor", ("logged_in",), ("editor_open",))m = Method("ship_change_m1", "ship_change", ("logged_in",), ("open_editor", "write_tests", "run_tests", "open_pr"))planner = HTNPlanner(operators=operators, methods=methods, llm=llm)plan = planner.plan("ship_change", {"logged_in"})list of operators or Noneplanner.cached_methodsLLM decompositions kept for the next callplanner.llm.calls0 new calls on a cache hitDefaults#
| Setting | Default | Note |
|---|---|---|
max_steps | 12 | All step executions, replans included |
max_replans | 5 | Planner calls after the first plan |
max_depth | 12 | HTN recursion limit, then None |
max_iter | 5 | Evaluator-optimizer rounds |
n | 5 | Voters in parallel_vote |
generations | 12 | Evolutionary demo, keep top 3 of 6 |
Plan-execute executor#
Planning terms#
- Operator
- primitive action with preconditions and effects.
- Method
- a way to break a compound task into subtasks, with preconditions.
- ChatHTN
- the symbolic planner asks the LLM when no method matches.
- Fitness function
- deterministic, machine-checkable score over outputs.
- Augmented LLM
- LLM plus search, tools and memory. The atomic unit.
- expected_outcome
- planner's success condition. The executor does not enforce it.
- Replan
- hand the error to the planner. This turns a script into an agent.
Failures and fixes#
| Symptom | Cause | Fix |
|---|---|---|
failed, reason replan_budget | Planner returns the same broken plan | Feed last_error and route around it |
failed, reason step_budget | Replans add steps past max_steps | Shorter plans or reuse history |
failed, reason no_plan | Planner returned [] | Add a recovery plan for that error |
dependency cycle among: | Items wait on each other | Resolve the disagreement behind it |
has no repository evidence | Item has empty evidence | Cite a repository fact |
has no proof command | Empty proof | Give one exact check |
| HTN soundness collapses | No precondition/effect schemas | Validate LLM output against operators |
| Evolution does not converge | LLM asked if the code is better | Use a deterministic, fast evaluator |
Commands#
| Command | What it does |
|---|---|
python3 code/ | Runs the lesson demo and prints the trace |
python3 -m unittest discover code/ | Runs the evidence plan tests |
outputs/ | Written by lesson 44, status ready or blocked |
Questions#
- Workflow or agent?
- Workflow when you can enumerate the steps. Agent when the next step depends on the last result.
- Why cap replans and steps?
- A capped replan fails faster with a clearer reason.
- Why is ChatHTN sound?
- LLM output enters only as candidate decompositions. The schema rejects invalid ones.
- Which steps run together?
- Steps in the same wave. Integration waits for both branches.
Tips#
- Start with direct API calls. Reach for ReAct or ReWOO before HTN.
- Define the contract before its implementations.
- Give each work item an id, change, evidence, dependencies and proof.
- Emit a plan diff on each revision. Do not rewrite the plan silently.
- Store the plan next to the work, not in chat checkboxes.