Planning Agent 和 Action Agent 有什么区别?
前言:为什么我会学这个问题
前面的系列已经介绍了Langgrahp中的基础概念和如何使用,但只能实现简单工作流,实现复杂的Agent还需新的知识补充,比如Agent 要自动拆解成多个步骤再执行"
这让我开始研究另一种 Agent 架构:Planning Agent。这才发现,原来 Agent 有两种截然不同的决策方式,分别适用于不同场景。
一、问题背景
两种决策困境
假设场景:用户说"帮我订明天北京到上海的机票,还要订酒店"
Action Agent 的思路:
- 先想第一步:查机票
- 查完机票,想第二步:查酒店
- 再想第三步:订机票
- 再想第四步:订酒店
- …
每一步都是"当前状态 → 决定下一步",单步决策,像走路时边走边看红绿灯。
Planning Agent 的思路:
- 先想:用户要完成"出差安排"这个目标
- 拆解计划:1) 查明天北京到上海的机票 2) 对比价格和时间 3) 查上海酒店 4) 预订机票和酒店 5) 发送确认
- 按计划执行,中间根据反馈调整计划
先规划,再执行,像出门前先看地图规划路线。
二、核心概念
Action Agent(反应式 Agent)
定义:每一步都基于当前状态做出反应,单步决策,不提前规划整体路径。
典型代表就是 ReAct 模式(Thought-Action-Observation 循环)。
特点:
- 实时响应,速度快
- 适合简单、线性的任务
- 不擅长处理长程依赖和复杂拆解
Planning Agent(规划式 Agent)
定义:先制定完整计划,再按计划执行,可以在执行过程中动态调整计划。
典型实现:Chain of Thought 扩展、Hierarchical Task Network、LLM+P(用规划器辅助)等。
特点:
- 有全局视角,能处理复杂任务
- 可以预判困难,提前准备
- 执行效率可能较低(规划耗时)

核心区别对比
| 维度 | Action Agent | Planning Agent |
|---|---|---|
| 决策时机 | 每步决策 | 先规划后执行 |
| 全局视角 | 无,只看当前 | 有,知道整体目标 |
| 适用场景 | 简单任务,快速响应 | 复杂任务,多步拆解 |
| 计算成本 | 低 | 高(规划消耗) |
| 容错性 | 低,一步错可能全错 | 高,可重新规划 |
三、错误理解 / 常见误区
误区 1:Planning Agent 一定比 Action Agent 好
不一定。Planning Agent 的规划本身需要消耗 token 和时间,对于"查天气"这种简单任务,用 Planning Agent 反而杀鸡用牛刀。
误区 2:ReAct 就是 Action Agent,没有规划能力
不完全对。ReAct 虽然是单步决策,但 LLM 本身的推理能力让它隐式地有一定的规划能力。区别在于这是"隐式规划"还是"显式规划"。
误区 3:Planning Agent 不会走弯路
错误。Planning Agent 的计划基于对世界的"假设",执行时发现假设不对,就得调整计划重新规划。所以 Planning Agent 也可能走弯路,只是走弯路的代价更大(规划沉没成本)。
误区 4:两种 Agent 非此即彼
现实中经常结合使用。比如外层用 Planning Agent 拆解任务,内层每个子任务用 Action Agent 执行。
四、正确实现思路
何时选 Action Agent
- 任务步骤少(1-3 步)
- 每步的结果可预测
- 需要快速响应
- 实时性要求高
何时选 Planning Agent
- 任务步骤多(5 步以上)
- 步骤之间有依赖关系
- 需要全局优化(如成本最低、时间最短)
- 任务可能需要用户确认后才能继续
混合架构实现
class HybridAgent:
"""混合 Agent:外层规划 + 内层执行"""
def __init__(self, llm, tools):
self.llm = llm
self.tools = tools
def plan_and_execute(self, task: str) -> str:
"""规划-执行主循环"""
# 第一阶段:规划
plan = self.create_plan(task)
print(f"生成计划:{plan}")
# 第二阶段:按计划执行
context = {}
for step in plan["steps"]:
# 如果是简单 action,直接执行
if step["type"] == "action":
result = self.execute_action(step["action"], step["params"], context)
context[step["key"]] = result
# 如果是需要规划的,先规划再执行
elif step["type"] == "plannable":
sub_plan = self.create_plan(step["description"])
for sub_step in sub_plan["steps"]:
sub_result = self.execute_action(sub_step["action"], sub_step["params"], context)
context[sub_step["key"]] = sub_result
return context.get("result", "完成")
def create_plan(self, task: str) -> dict:
"""使用 LLM 生成计划"""
prompt = f"""任务:{task}
请将这个任务拆解成具体步骤,返回 JSON 格式:
{{
"steps": [
{{"type": "action", "action": "工具名", "params": {{}}, "key": "结果变量名"}},
...
]
}}
"""
response = self.llm.generate(prompt)
return json.loads(response)
def execute_action(self, action: str, params: dict, context: dict) -> any:
"""执行单个 action"""
if action in self.tools:
# 解析上下文中的变量
resolved_params = self.resolve_params(params, context)
return self.tools[action](**resolved_params)
return None
def resolve_params(self, params: dict, context: dict) -> dict:
"""解析参数,支持从上下文引用"""
resolved = {}
for key, value in params.items():
if isinstance(value, str) and value.startswith("$"):
# 引用上下文变量
var_name = value[1:]
resolved[key] = context.get(var_name)
else:
resolved[key] = value
return resolved
单步规划器实现
class SimplePlanner:
"""简单的 Planning Agent 实现"""
def __init__(self, llm):
self.llm = llm
def plan(self, task: str, max_steps: int = 5) -> list:
"""生成执行计划"""
prompt = f"""任务:{task}
你是一个任务规划专家。请将上述任务拆解成不超过 {max_steps} 个步骤。
输出格式(每行一个步骤):
1. 步骤描述 | 工具名 | 参数
例如:
查北京天气 | get_weather | {{"city": "北京"}}
"""
response = self.llm.generate(prompt)
# 解析计划
steps = []
for line in response.strip().split('\n'):
if line.strip():
parts = line.split('|')
if len(parts) >= 3:
steps.append({
"description": parts[0].strip(),
"action": parts[1].strip(),
"params": eval(parts[2].strip()) # 简化,实际应该用 JSON 解析
})
return steps
五、代码示例
完整的 Action Agent vs Planning Agent 对比
from enum import Enum
from typing import List, Dict, Any, Callable
import json
class AgentType(Enum):
ACTION = "action"
PLANNING = "planning"
class ActionAgent:
"""纯反应式 Action Agent"""
def __init__(self, llm: Callable, tools: Dict[str, Callable]):
self.llm = llm
self.tools = tools
def run(self, task: str, max_iterations: int = 10) -> str:
"""ReAct 风格的单步决策循环"""
history = []
for i in range(max_iterations):
# LLM 决定下一步
prompt = self._build_prompt(task, history)
decision = self.llm(prompt)
action = decision.get("action")
action_input = decision.get("action_input", {})
# 结束
if action == "finish":
return decision.get("output", "完成")
# 执行工具
if action in self.tools:
observation = self.tools[action](**action_input)
else:
observation = f"未知工具: {action}"
history.append({
"thought": decision.get("thought"),
"action": action,
"observation": observation
})
return "达到最大迭代次数"
class PlanningAgent:
"""规划式 Agent:先规划后执行"""
def __init__(self, llm: Callable, tools: Dict[str, Callable]):
self.llm = llm
self.tools = tools
def run(self, task: str) -> str:
"""规划-执行模式"""
# 阶段 1:生成计划
plan = self._create_plan(task)
print(f"📋 生成计划:共 {len(plan)} 个步骤")
# 阶段 2:按计划执行
context = {}
for i, step in enumerate(plan):
print(f" Step {i+1}: {step['description']}")
# 解析参数(支持引用上下文)
params = self._resolve_params(step.get("params", {}), context)
# 执行
if step["action"] in self.tools:
result = self.tools[step["action"]](**params)
else:
result = f"未知工具: {step['action']}"
# 存入上下文
if step.get("save_as"):
context[step["save_as"]] = result
# 检查是否需要重新规划
if step.get("verify"):
if not self._verify_result(step["verify"], result, context):
print(f" ⚠️ 验证失败,重新规划...")
new_plan = self._replan(task, context)
plan = new_plan # 替换计划
continue
return context.get("_final_result", "完成")
def _create_plan(self, task: str) -> List[Dict]:
"""生成执行计划"""
prompt = f"""任务:{task}
请将这个任务拆解成具体的执行步骤。
返回 JSON 数组格式:
[
{{
"description": "步骤描述",
"action": "工具名",
"params": {{"参数名": "参数值"}},
"save_as": "结果变量名",
"verify": "验证条件"
}}
]
要求:
- 步骤之间有依赖关系时,通过 save_as 变量传递
- 复杂的验证条件用自然语言描述
"""
response = self.llm(prompt)
return json.loads(response)
def _resolve_params(self, params: dict, context: dict) -> dict:
"""解析参数中的变量引用"""
resolved = {}
for key, value in params.items():
if isinstance(value, str) and value.startswith("$"):
resolved[key] = context.get(value[1:], value)
else:
resolved[key] = value
return resolved
def _verify_result(self, condition: str, result: Any, context: dict) -> bool:
"""验证步骤结果"""
# 简化:实际可以用 LLM 判断
return True
# 测试对比
if __name__ == "__main__":
# 模拟 LLM
def mock_llm(prompt):
if "ReAct" in prompt or "action" in prompt.lower():
# Action Agent 的决策
return {
"thought": "需要先查天气",
"action": "get_weather",
"action_input": {"city": "北京"}
}
else:
# Planning Agent 的规划
return json.dumps([
{
"description": "查询北京天气",
"action": "get_weather",
"params": {"city": "北京"},
"save_as": "beijing_weather"
},
{
"description": "查询上海天气",
"action": "get_weather",
"params": {"city": "上海"},
"save_as": "shanghai_weather"
},
{
"description": "比较两个天气",
"action": "compare",
"params": {"a": "$beijing_weather", "b": "$shanghai_weather"},
"save_as": "_final_result"
}
])
# 模拟工具
def get_weather(city: str) -> str:
weathers = {"北京": "晴 25°C", "上海": "雨 22°C"}
return weathers.get(city, "未知")
def compare(a: str, b: str) -> str:
return f"比较结果:{a} vs {b}"
tools = {"get_weather": get_weather, "compare": compare}
# 测试 Action Agent
print("=" * 50)
print("Action Agent(ReAct)执行:")
print("=" * 50)
action_agent = ActionAgent(mock_llm, tools)
result = action_agent.run("北京和上海的天气怎么样?")
print(f"结果:{result}")
# 测试 Planning Agent
print("\n" + "=" * 50)
print("Planning Agent 执行:")
print("=" * 50)
planning_agent = PlanningAgent(mock_llm, tools)
result = planning_agent.run("北京和上海的天气怎么样?")
print(f"结果:{result}")
六、运行结果 / 流程图
运行上述代码:
==================================================
Action Agent(ReAct)执行:
==================================================
结果:北京晴 25°C
==================================================
Planning Agent 执行:
==================================================
📋 生成计划:共 3 个步骤
Step 1: 查询北京天气
Step 2: 查询上海天气
Step 3: 比较两个天气
结果:比较结果:北京晴 25°C vs 上海雨 22°C
两种 Agent 的流程对比:

七、项目中怎么用
实际选型建议
-
客服机器人(简单问答) → 用 Action Agent(ReAct)
- 用户问题简单直接,不需要复杂拆解
- 需要快速响应
-
旅行助手(多步骤规划) → 用 Planning Agent
- 需要查机票、酒店、景点、交通
- 各步骤有依赖关系(先定机票才能定酒店)
-
代码助手(复杂任务) → 混合架构
- 外层 Planning Agent 拆解任务
- 内层 Action Agent 执行具体代码操作
注意事项
- 规划消耗资源:Planning Agent 的规划阶段需要额外 LLM 调用,要评估成本
- 计划可能失效:外部环境变化时,计划需要动态调整
- 用户参与:复杂计划执行前,最好让用户确认
系列关联:本文探讨了 Planning Agent 和 Action Agent 的区别,下一篇《如何让 Agent 记住对话历史?》会讲到,无论是哪种 Agent,都需要解决"对话历史管理"的问题,这是构建真正实用 Agent 的基础。
八、总结 + 下篇预告
核心要点
- Action Agent:单步决策,实时响应,适合简单任务。代表是 ReAct 模式。
- Planning Agent:先规划后执行,有全局视角,适合复杂任务。
- 混合架构:外层规划 + 内层执行,兼顾灵活性和效率。
- 选型原则:简单任务用 Action Agent,复杂任务用 Planning Agent 或混合架构。
下篇预告
下一篇我们将探讨《如何让 Agent 记住对话历史?》,理解如何让 Agent 在多轮对话中保持上下文记忆,不会"说完就忘"。这涉及到消息历史管理、摘要压缩、向量检索等技术。
延伸阅读
更多推荐

所有评论(0)