智能体架构
如果每一步和每个分支都能在执行前写明,固定工作流就足够了。当下一项操作取决于尚未出现的信息时,智能体才真正有用,例如测试结果、搜索结果、用户决定或已经变化的环境。智能体架构就是那个封闭的决策循环:它把观测转化为下一个有边界的动作。
这个循环不只是一个模型加一份工具清单。它还需要控制器、整理后的上下文、动作接口、环境、状态转移和终止规则。工具调用只是动作接口的一种,可执行代码、图形界面操作、消息和环境原生命令也可以是动作接口。规划和记忆是循环中的设计选择,并不是每个智能体都必须具备的一组固定组件。
2023 年的两个重要系统分别展示了这片设计空间的一部分。ReAct 把显式的语言推理与特定任务的动作交错起来,让后续决定能够利用新观测 (Yao et al. 2023)。Toolformer 则生成、执行并筛选面向五个固定 API 的候选调用,再用保留下来的调用微调模型 (Schick et al. 2023)。它们证明模型可以学习并使用动作接口,但并不定义唯一正确的智能体架构。
一轮交互就是一次状态转移
在第 轮,运行时构造模型输入,控制器提出决定,随后运行时更新持久状态:
其中, 是轮次索引, 是任务目标, 包含用户指令与约束, 是本轮开始前的持久会话状态, 是本轮暴露的动作规范集合, 记录剩余的词元、动作次数、时间与成本预算, 是上下文整理器。它输出有边界的控制器输入 。参数为 的控制器 采样输出 ,解码器 把输出解析成决定 。更新器 将旧状态、决定与观测 合并,得到下一状态 。方程中的每个符号都对应一项可以记录和测试的运行时对象。
解析后的决定必须有明确类型。一个实用的最小集合是:
其中, 是请求执行动作或一批明确动作, 是向用户提问的问题, 是提交最终回答, 是结构化终止原因。动作产生的 可以是工具结果、执行错误或策略拒绝,用户回复也可以成为观测。最终回答必须在完成条件通过后才能离开循环。终止原因应记录成功、终局失败、取消、预算耗尽或其他已声明的终止条件。
状态 与模型上下文 不是同一个对象。状态可以保存完整事件日志、审批记录、外部资源句柄,以及绝不能进入提示词的数据。上下文则是经过选择和格式化的状态视图。将二者分开后,脱敏、摘要、回放和更换模型都不需要改写会话记录。
图 38.2 中的控制器可以采用 ReAct。ReAct 在动作之间插入可见的语言推理 (Yao et al. 2023),但通用循环并不要求展示这类轨迹。模型可以在内部推理,外部规划器可以提供计划,确定性工作流也可以决定部分状态转移。必须保持可观测的是决定记录,包括所选分支、动作参数、观测来源、审批结果、已消耗预算和完成证据。
架构是一组契约
规划、记忆和工具使用这些常见标签很有用,却混合了策略、状态与接口问题。把每项运行时角色写成契约,生产架构会清楚得多:
| 角色 | 契约 | 缺失后的故障 |
|---|---|---|
| 控制器 | 根据整理后的上下文提出一个带类型的决定。 | 自由文本被误当成可执行命令。 |
| 上下文整理器 | 选择、排序、标注并限制模型输入。 | 持久状态与恰好能放进一次提示词的内容混为一谈。 |
| 状态存储与更新器 | 保存事件,并据此推导下一份工作状态。 | 重试会丢失历史,或把同一观测应用两次。 |
| 动作目录 | 定义可用操作、参数规范、副作用和结果规范。 | 控制器无法区分合法操作与看似合理的文本。 |
| 引用监视器 | 验证、授权、请求审批并执行预算限制。 | 模型输出绕过产品的权限边界。 |
| 分发器与环境 | 执行获准动作,返回带状态和来源的规范化观测。 | 超时和部分失败被误当成任务结果。 |
| 完成检查器 | 独立于控制器的声明,检查用户要求的最终状态。 | 一句自信的最终回答让未完成任务提前结束。 |
| 终止策略 | 在成功、失败、取消或资源耗尽时停止。 | 循环四处游走、无限重试,或无上限地消耗资源。 |
这种拆分也将架构与运行框架的实现分开。架构规定状态必须留存、动作必须经过防护;第 41 章 中的运行框架则用队列、租约、重试、检查点和崩溃恢复,让这些契约在故障后仍然成立。
根据任务选择控制模式
智能体架构之所以有多种形态,是因为控制器不必对所有任务采用同一种模式。
| 模式 | 适用场景 | 必需反馈 | 主要故障模式 |
|---|---|---|---|
| 固定工作流 | 步骤和分支在执行前已经明确。 | 在声明的检查点返回状态。 | 未编码的情况无处可去。 |
| 反应式下一步动作 | 最新观测决定下一个小步骤。 | 几乎每次动作后都返回观测。 | 控制器四处游走,或丢失全局目标。 |
| 滚动时域规划 | 提前安排若干步骤有助于协调,但环境可能变化。 | 每次动作或检查点后重新规划。 | 重新规划成本占主导,或继续执行已经过时的计划前缀。 |
| 先规划后执行 | 依赖关系可预测,观测很少改变计划。 | 在步骤边界验证。 | 早期假设失效,连带破坏后续步骤。 |
| 分层规划器与执行器 | 高层分解与底层动作选择需要不同上下文或模型。 | 子目标完成信号与升级机制。 | 规划器与执行器对状态或成功条件理解不一致。 |
| 评估器与改进器 | 检查候选结果比一次就生成正确结果更便宜。 | 能指导修改的验证反馈。 | 评估器奖励表面变化,或改进过程永不停止。 |
| 分支搜索 | 生成多个候选很便宜,而且能够可靠比较。 | 评分器与明确的搜索预算。 | 成本增长快于有效多样性。 |
工作流能够表达任务时,通常应优先使用工作流。它成本更低,更容易测试,也更容易授权。只有当系统只能在设计时尚不可见的观测出现后才能选择动作时,由模型控制的循环才值得承担额外成本。
规划不是开关,而是一种节奏
一份不可修改的计划可能很快过时,但这并不意味着规划无用。真正的设计问题是何时制定计划、计划覆盖多远,以及什么情况触发修改。ReAct 用显式推理和动作展示了逐步适应 (Yao et al. 2023)。Reason for Future, Act for Now 会规划未来轨迹,只执行第一个动作,纳入反馈后再次规划 (Liu et al. 2024)。Plan-and-Act 则把训练过的高层规划器与执行器分开,并报告了长时程网页任务上的结果 (Erdogan et al. 2025)。这些系统采用的是不同的规划节奏,并不是同一套正确架构的迭代版本。
写下来的计划属于状态,不代表权限。每一步仍需检查当前前置条件、权限和预算。常见的重新规划触发条件包括前置条件失败、意外观测、用户约束发生变化、动作被拒绝、超时、完成检查失败,或剩余预算达到阈值。计划还应记录支撑它的观测,否则摘要可能保留步骤,却删掉当初证明该步骤合理的假设。
自适应控制不要求展示推理轨迹。ReAct 等研究系统中,这类轨迹可能有用;但运行审查应依靠稳定的产物,例如计划版本、决定类型、动作参数、验证器输出和状态转移。Reflexion 是一种具体方案,它把任务反馈转成文本反思,留给后续尝试使用 (Shinn et al. 2023)。这说明无需更新模型权重也能更新上下文状态,却不构成通用的正确性保证。
选择动作表示方式
动作接口决定控制器能表达什么,也决定运行时能验证什么。三种常见表示方式有不同取舍:
| 表示方式 | 优点 | 运行时必须执行的边界 |
|---|---|---|
| 结构化函数调用 | 明确的操作名与带类型参数支持规范验证、逐次审批和稳定日志。 | 完成语法检查后还要验证语义,授权具体操作与目标,并规范化所有结果和错误。 |
| 可执行代码 | 循环、变量、筛选和多项操作可以组合进一个动作。 | 在沙箱中运行,管控每项外部能力,限制 CPU、内存、网络和时间,并保存代码及其副作用。 |
| 环境原生动作 | 文本命令、机器人控制、点击、按键或消息可以直接对应环境。 | 限制合法动作集合,标识目标状态,并根据最新观测验证副作用。 |
Toolformer 研究模型如何学会在何时、以何种方式调用一小组固定 API (Schick et al. 2023)。CodeAct 研究另一种动作表示,也就是可执行 Python。作者在 API-Bank 和 M³ToolEval 上测试 17 个模型,与其比较的文本和 JSON 格式相比,报告成功率最高提高 20 个百分点 (Wang et al. 2024)。结果仅适用于这些模型、接口和基准,不能证明代码始终更安全或更便宜。
接口设计本身就会改变智能体表现。SWE-agent 为仓库浏览、编辑和测试设计了智能体与计算机之间的接口,再在软件工程任务上评测 (Yang et al. 2024)。更普遍的结论不是每个智能体都需要这套接口,而是动作名称、参数形状、观测格式和反馈延迟都属于架构,并非中性的连接层。
无论采用哪种表示,模型只负责提出动作,引用监视器决定是否允许执行。带副作用的请求需要稳定的幂等键,避免传输重试重复购买、发消息或写入。长期运行的工作需要持久句柄来标识,不能把一条仍然打开的连接当作身份。只有依赖关系和副作用互不冲突时,才能安全地并行动作。
让每一个分支都明确
最小循环不是“不断调用模型,直到它不再输出工具调用”。没有调用可能表示最终回答、澄清问题、拒绝、格式错误或模型故障。更安全的架构骨架如下:
state = initialize(task, user_constraints, permissions, budgets)
loop:
stop = check_termination(state)
if stop exists:
return recorded_outcome(stop, state)
context = assemble_context(state)
raw = controller(context)
decision = decode_typed_decision(raw)
if decision is invalid:
state = record_parse_error(state, raw)
continue # bounded by the parse-retry budget
if decision is ask_user:
suspend until reply or cancellation
state = record_user_reply(state, reply)
continue
if decision is final_response:
evidence = verify_completion(state, decision)
if evidence passes:
return recorded_outcome(success, state, evidence)
state = record_failed_completion(state, evidence)
continue
if decision is requested_action:
verdict = validate_authorize_and_budget(decision, state)
if verdict denies:
state = record_observation(state, verdict)
continue
request_id = idempotency_key(session_id, turn_id, decision)
result = execute_with_timeout(decision, request_id)
state = record_observation(state, normalize(result))
这份骨架可以向用户提问、请求执行动作、提交最终回答或终止。解析错误、授权拒绝、超时和工具故障都成为带类型的观测,不再作为异常悄悄抹掉一轮交互。终止检查覆盖成功、失败、取消和预算耗尽。运行框架可以用不同方式实现重试与恢复,但必须保留这些结果。
区分自主性与权限
自主性描述由谁选择下一项操作,权限描述系统可以执行哪些操作。它们是两条彼此独立的轴。控制器可以自主搜索只读语料库,却只有很小权限;固定工作流也可能拥有部署软件或转移资金的广泛权限。
这个区别会改变架构审查。增加规划器、延长任务时程或动态发现工具,可能增加自主性,却不改变权限。挂载可写凭据、扩大文件系统范围或移除审批门,即使控制循环不变,也会扩大权限。影响范围取决于权限、可达范围与可逆性,不能由“智能体化”这样的模糊标签决定。安全与授权控制见 第 56 章;架构必须暴露这些控制可以介入的决定点。
下层约束:上下文是一笔共享预算
上下文窗口必须同时容纳指令、任务数据、工作状态、动作规范,以及留给输出的空间。其词元记账方式是:
其中, 是第 轮预留的总词元数, 用于系统与策略指令, 用于用户目标和固定任务数据, 用于选中的会话状态, 用于已挂载的动作规范, 为控制器输出预留空间, 是模型支持的上下文上限。集合 包含第 轮暴露的动作, 是动作规范 序列化后的词元长度。每一项都是第 轮的实际词元预算。等式只是记账,并不表示每一份预算具有相同价值。
再挂载一个动作会产生确定的词元成本,但它对动作选择的影响需要实测,不是一条普遍成立的指数曲线,也不存在固定的工具数量阈值。结果取决于模型、任务、规范的相似程度、描述方式和提示词。BFCL 评测串行与并行调用、弃权,以及有状态的多轮行为 (Patil et al. 2025)。ACEBench 又加入含糊或不完整的指令和多轮智能体场景 (Chen et al. 2025)。这些基准揭示了多种故障,却没有给出一个适用于所有模型的目录规模上限。
应根据真实工作负载,在扁平目录、分阶段挂载、检索或显式发现之间选择。测量所需动作存在时的选择质量,加入无关工具和相似规范,测试没有动作适用时能否弃权,并在动态选择规范时报告检索召回率。工具检索可以节省上下文,也可能恰好隐藏解决任务所需的唯一动作。
显式规划与隐式规划之间没有普遍胜者。显式计划有助于协调长任务,也方便审查;反应式控制则能用较少的规划开销适应变化。Plan-and-Act 为独立规划器与执行器提供了限定场景的证据 (Erdogan et al. 2025);ReAct 和滚动时域系统则为更紧密的反馈提供了限定场景的证据 (Yao et al. 2023; Liu et al. 2024)。能否迁移取决于任务分布、模型、验证器和成本预算。
动作暴露方式同样没有定论。扁平目录简单且易于审计;检索或发现可以节省上下文,却增加召回失败。结构化函数调用便于逐项设防;可执行代码能组合多个操作,却把更多责任交给沙箱和引用监视器。应在相同的运行边界内比较这些选择,不能把它们排成一条通用的智能体成熟度阶梯。
把架构当作完整系统来验证
比较架构时,必须使用相同的模型检查点、任务分布、工具实现、权限和预算。否则,更强的模型、更宽的凭据或更多词元都可能被误认成更好的控制循环。
| 层面 | 测量项 |
|---|---|
| 任务结果 | 带置信区间的完成率;按任务类型和时程统计的完成率;独立的最终状态验证;用户纠正次数。 |
| 控制质量 | 无效动作率;不必要动作率;重新规划频率;动作被拒绝、失败或产生误导观测后的恢复率;过早提交最终回答的比例。 |
| 安全与权限 | 审批频率;权限拒绝率;意外副作用;重复副作用;超出请求范围的操作。 |
| 状态质量 | 回放成功率;事件缺失或重复;上下文截断;观测来源;动态动作检索召回率。 |
| 成本与服务 | 模型调用次数;输入与输出词元;动作数;工具与模型延迟;墙钟时间;每个完成任务的成本。 |
检查失败时,应按状态转移检查失败,而不只看最终分数。需要确定究竟是哪一环出了问题:所需事实从未进入上下文,控制器选错决定类型,动作规范含糊,授权拒绝了合法操作,环境返回误导性观测,状态更新器遗漏观测,还是完成检查器过早放行。它们属于不同的契约,需要不同的修复。
至此,架构已经明确了状态边界,却还没有决定哪些内容只保留一轮、一个会话,或跨越多个会话。下一章讨论 第 39 章。
延伸阅读
- Yao et al., “ReAct: Synergizing Reasoning and Acting in Language Models” (ReAct 的 ICLR 归档论文,把显式文字推理轨迹与任务专用动作交错执行), 2023. arXiv:2210.03629ReAct 让语言模型交替生成文字推理与环境动作,使后续决策能够纳入新观察。
- Schick et al., “Toolformer: Language Models Can Teach Themselves to Use Tools” (从筛选后的生成调用中学习何时以及如何调用五个固定 API), 2023. arXiv:2302.04761Toolformer 生成候选 API 标注,执行调用并按语言模型损失筛选,再微调模型决定何时及如何使用五个固定 API。
- Liu et al., “Reason for Future, Act for Now: A Principled Architecture for Autonomous LLM Agents” (规划未来轨迹,只执行第一步,再根据反馈重新规划), 2024. proceedings.mlr.pressRAFA 实现滚动时域控制:规划未来动作、执行第一步、保存反馈,再从更新后的状态重新规划。
- Erdogan et al., “Plan-and-Act: Improving Planning of Agents for Long-Horizon Tasks” (把训练得到的高层规划器与环境专用执行器分开), 2025. proceedings.mlr.pressPlan-and-Act 训练规划器生成高层计划,再由独立执行器把计划转换成长时程网页任务中的环境动作。
- Shinn et al., “Reflexion: Language Agents with Verbal Reinforcement Learning” (保存来自任务反馈的文字反思,供后续试验使用,而不更新权重), 2023. proceedings.neurips.ccReflexion 把任务反馈转成保存在情节记忆中的文字反思,通过上下文而非参数更新来改变后续决策。
- Wang et al., “Executable Code Actions Elicit Better LLM Agents” (在 API-Bank 和 M3ToolEval 上比较可执行 Python、文本和 JSON 动作格式), 2024. arXiv:2402.01030CodeAct 以可执行 Python 作为动作表示,并在其评测模型与基准上报告了相对比较格式最高 20 个百分点的成功率提升。
- Yang et al., “SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering” (研究智能体计算机接口如何改变软件工程任务中的行为), 2024. proceedings.neurips.ccSWE-agent 为代码仓库导航、编辑与测试设计模型接口,说明动作与观察接口本身会影响智能体表现。
- Patil et al., “The Berkeley Function Calling Leaderboard (BFCL): From Tool Use to Agentic Evaluation of Large Language Models” (评估串行调用、并行调用、弃答和有状态多轮行为), 2025. proceedings.mlr.pressBFCL 评测串行、并行、弃权和有状态多轮函数调用,而不是把工具使用简化为单一参数匹配分数。
评论
登录后评论