Hierarchical Planning for AI Agents
Reviewed: June 4, 2026
Published: May 26, 2026 | Planning Agent Architecture
Complex tasks require decomposition. Hierarchical planning breaks goals into sub-goals, assigns them to specialized sub-agents, and dynamically replans when things go wrong.
The Planning Hierarchy
class HierarchicalPlanner:
"""Break complex goals into executable sub-tasks."""
def __init__(self, llm):
self.llm = llm
def decompose(self, goal: str, max_depth: int = 3) -> dict:
"""Recursively decompose a goal into sub-tasks."""
if max_depth == 0:
return {"task": goal, "type": "leaf"}
plan = self.llm.generate(f"""
Decompose this goal into 3-5 sub-goals:
Goal: {goal}
For each sub-goal, specify:
- Description
- Dependencies (which sub-goals must complete first)
- Success criteria
- Estimated complexity (low/medium/high)
Output as JSON tree.
""")
return self._parse_plan(plan)
def execute_plan(self, plan: dict, executor) -> dict:
"""Execute a hierarchical plan with dependency resolution"""
completed = set()
results = {}
def can_execute(node):
deps = node.get("dependencies", [])
return all(d in completed for d in deps)
def execute_node(node):
if node["type"] == "leaf":
result = executor(node["task"])
completed.add(node["task"])
results[node["task"]] = result
else:
for child in node.get("children", []):
if can_execute(child):
execute_node(child)
execute_node(plan)
return results
def replan(self, goal: str, failed_task: str, error: str) -> dict:
"""Generate a revised plan after failure."""
return self.llm.generate(f"""
Original goal: {goal}
Failed task: {failed_task}
Error: {error}
Generate an alternative approach that avoids the failure point.
Focus on: different decomposition, alternative tools, fallback strategies.
""")
Dynamic Replanning Strategies
- Checkpoint-based: Save state at each sub-goal completion — resume from last checkpoint
- Alternative path: Pre-compute 2-3 alternative paths for critical sub-goals
- Graceful degradation: Continue with partial results when a non-critical sub-goal fails
- Human escalation: Request human input when replanning fails twice
Production Patterns
# LangGraph implementation
from langgraph.graph import StateGraph
from typing import TypedDict
class PlanState(TypedDict):
goal: str
plan: dict
completed: list
results: dict
errors: list
def create_planning_graph():
graph = StateGraph(PlanState)
graph.add_node("decompose", decompose_node)
graph.add_node("execute", execute_node)
graph.add_node("validate", validate_node)
graph.add_node("replan", replan_node)
graph.add_edge("decompose", "execute")
graph.add_edge("execute", "validate")
graph.add_conditional_edges("validate",
lambda s: "complete" if s["plan_complete"] else "replan")
graph.add_edge("replan", "execute")
return graph.compile()
Part of the Agent Architecture series on DataGate.ch.
