跳转到内容

Plan-and-Execute 执行架构

学习目标

理解 CrewAI 的 Plan-and-Execute 架构如何通过 Flow Router 模式实现计划驱动的执行、依赖解析、并行调度和动态重规划。

前置知识

下文假设你已理解上述概念,直接聚焦 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 观察,失败时 replan1/步
high完整管道:观察 → 决策 → replan/refine/early-goal2+/步

PlannerObserver 在每步执行后调用 LLM 分析:这一步完成了什么、学到了什么新信息、剩余计划是否仍然有效、是否需要 replan。返回 StepObservation 对象,直接应用于剩余 todo 的描述,无需第二次 LLM 调用。

依赖解析与并行执行

get_ready_todos_method() 检查依赖已满足的可执行 todo:

  • 单 todo 就绪:串行执行
  • 多 todo 就绪:通过 asyncio.gather 并行执行
  • 依赖死锁:触发 replan(todo 之间形成循环依赖时)

问题与规避

计划过于详细导致 LLM 调用次数激增

  • 每个 todo 步骤都可能需要独立的 LLM 调用
  • 对策:对简单任务设置 planning=False,使用 ReAct 循环直接执行

计划过于粗糙导致并行度不足

  • 如果计划只生成了少量大步骤,无法利用并行执行
  • 对策:使用 mediumhigh 级别的 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