Plan-and-Execute 执行架构
学习目标
理解 CrewAI 的 Plan-and-Execute 架构如何通过 Flow Router 模式实现计划驱动的执行、依赖解析、并行调度和动态重规划。
前置知识
- StateGraph Agent 循环 — 基于有向图的状态机架构
下文假设你已理解上述概念,直接聚焦 CrewAI 的具体实现。
项目实践
两套执行循环
CrewAI 存在两套 Agent 执行循环:
| 循环 | 状态 | 特点 |
|---|---|---|
CrewAgentExecutor | 已废弃 | 传统 ReAct 循环,简单但无计划能力 |
AgentExecutor | 默认 | Flow-based Plan-and-Execute,支持计划和重规划 |
AgentExecutor 的 Flow Router 架构
AgentExecutor 继承自 Flow[AgentExecutorState],使用 Flow 的装饰器系统实现声明式编排:
核心状态
AgentExecutorState: messages: list[LLMMessage] # 对话历史 iterations: int # 当前迭代次数 plan: str | None # 生成的执行计划 todos: TodoList # 待办事项列表 observations: dict[int, StepObservation] # 每步观察 execution_log: list[dict] # 审计日志PlannerObserver 三级推理努力
PlanningConfig 控制观察和规划的开销:
| 级别 | 行为 | LLM 调用 |
|---|---|---|
low | 启发式观察(不调 LLM),继续执行 | 0 |
medium | 每步 LLM 观察,失败时 replan | 1/步 |
high | 完整管道:观察 → 决策 → replan/refine/early-goal | 2+/步 |
PlannerObserver 在每步执行后调用 LLM 分析:这一步完成了什么、学到了什么新信息、剩余计划是否仍然有效、是否需要 replan。返回 StepObservation 对象,直接应用于剩余 todo 的描述,无需第二次 LLM 调用。
依赖解析与并行执行
get_ready_todos_method() 检查依赖已满足的可执行 todo:
- 单 todo 就绪:串行执行
- 多 todo 就绪:通过
asyncio.gather并行执行 - 依赖死锁:触发 replan(todo 之间形成循环依赖时)
问题与规避
计划过于详细导致 LLM 调用次数激增
- 每个 todo 步骤都可能需要独立的 LLM 调用
- 对策:对简单任务设置
planning=False,使用 ReAct 循环直接执行
计划过于粗糙导致并行度不足
- 如果计划只生成了少量大步骤,无法利用并行执行
- 对策:使用
medium或high级别的 planning,让 PlannerObserver 在每步后细化后续步骤
依赖死锁
- 当 todo 之间形成循环依赖时,无法找到可执行的 todo
- 对策:
get_ready_todos_method()检测到死锁后自动触发 replan
设计取舍
Flow Router vs 硬编码 while 循环
- Flow Router 的优势是每个阶段可独立替换和扩展,声明式编排比硬编码更易维护
- 代价是 Flow 的
max_method_calls限制(默认 100 次),对于非常长的任务可能需要调整 - ReAct 循环(旧版)更简单直接,适合不需要计划能力的场景
参考来源
- 源码验证:
lib/crewai/src/crewai/experimental/agent_executor.py - 源码验证:
lib/crewai/src/crewai/agents/planner_observer.py