执行引擎与规划引擎:Agent 架构中最隐蔽的一条分界线
Agent 框架的核心设计决策不是"用哪个模型",而是把"思考"和"行动"放在哪一层管理。
引子
如果你看过几个 Agent 框架的源码,会发现一个有趣的现象:有的框架核心代码只有几百行,有的却有几万行。但这不一定是功能多少的区别——它反映的是一个更根本的设计选择:执行引擎和规划引擎,到底该不该分开。
最常见的陷阱:把 ReAct 当成全部
大多数人的第一个 Agent 长这样:
while True:
thought = llm.think(history + tools)
if thought.is_final:
return thought.answer
result = execute(thought.action)
history.append(result)
这就是经典的 ReAct 循环。它极度简洁,能跑通 OpenAI 的 Function Calling 演示,也能做点简单的搜索问答。但一旦进入真实场景,这个循环会暴露出三个致命问题。
第一,没有任务层级。 所有历史都摊平在一个列表里。如果 agent 先查了天气,又写了代码,再查了天气——第二次查天气的时候,第一次的结果还飘在上下文里,白白浪费 token。更糟的是,agent 没法区分"我正在写代码"和"我已经写完代码了"这两个状态。
第二,错误就是终点。 API 超时了怎么办?工具返回了意料之外的格式怎么办?模型产生了幻觉,调了个不存在的函数怎么办?在纯循环里,这些错误的唯一处理方式是"重新试一次整个循环"——而大多数实现甚至连重试都没写。
第三,思考与执行没有边界。 模型在回复中既要想下一步做什么,又要编排工具调用的参数。这在简单场景下没问题,但当工具链超过 5 个时,模型的注意力会被参数生成分散,推理质量明显下降。
分层设计的核心洞察
把执行和规划分开,本质上是承认一件事:让 LLM 思考什么时候调用工具,和让系统可靠地调用工具,是两件完全不同的事。
执行引擎负责的是:调用工具、处理返回值、管理上下文窗口、重试和错误恢复。它是确定性的、可测试的、可观测的。
规划引擎负责的是:决定下一步做什么、选择工具、分析中间结果。它是非确定性的、消耗 token 的、需要推理链的。
这两者的接口就是一个简单的数据结构:
@dataclass
class ExecutionRequest:
tool: str
args: dict
context: ConversationContext
@dataclass
class ExecutionResult:
success: bool
data: Any
error: Optional[str]
token_cost: int
规划引擎只负责生产 ExecutionRequest,执行引擎只负责消费它并返回 ExecutionResult。就这么简单。
这条分界线带来的实际好处
好处一:上下文窗口的精细管理
当执行引擎独立后,它可以对上下文做结构化的剪裁。比如:
- 只保留每个工具的最近一次调用结果
- 把超过 10 轮前的历史摘要化
- 动态决定哪些系统指令可以省略
这些逻辑不需要 LLM 参与,完全由确定性代码完成。
好处二:优雅的错误恢复
执行引擎可以内置 retry、fallback、timeout 策略。一个工具调用失败,不影响规划引擎的推理状态。执行引擎可以重试三次后返回"这个工具暂时不可用",规划引擎据此调整策略——而不是整个 agent 崩溃。
好处三:可观测性成为自然产物
分离之后,日志天然就有两条轴:规划日志(agent 每一步的思考)和执行日志(每个工具的调用耗时、返回大小、错误码)。这两类日志的消费对象完全不同——开发者看执行日志找性能问题,看规划日志找逻辑问题。
框架们是怎么做的
LangChain 的 AgentExecutor 是典型的"伪分离"——它在概念上区分了规划和执行,但实现上两者耦合在同一个循环里,导致 AgentExecutor 的代码复杂度一直上不去也下不来。
CrewAI 走得更彻底,直接把 Task 和 Agent 作为一等公民,每个 Task 有自己的执行上下文,Agent 在 Task 之间切换时需要重新加载上下文——这实际上是执行引擎在做"任务调度"。
而比较激进的做法(比如 AutoGPT 的早期版本)把规划完全交给了 LLM,系统层只做执行——结果是 planning 的 token 消耗爆炸,因为模型需要在每个步骤中重新理解全局状态。
一个更务实的路径
如果你正在设计自己的 Agent 框架,这条分界线的建议是:执行引擎先做,规划引擎再说。
执行引擎是基础设施,可以从第一天就开始写。它包含:
- 一个工具注册表和参数校验器
- 一个可替换的执行器(同步、异步、子进程)
- 一个上下文管理器(窗口控制、摘要策略、历史剪裁)
- 一个错误处理管道(重试、降级、fallback)
规划引擎可以一开始就走最简单的 ReAct,等需要更复杂的推理(DAG 任务编排、多 Agent 协作、反思循环)时,再逐步替换。
这不是银弹——它只是让你在踩坑的时候,知道该去修哪个模块。
评论
发表评论