Agent 三层架构的误区:感知-决策-执行并不够
很多团队把 Agent 画成“感知-决策-执行”三层就开始写代码,结果上线后到处是状态丢失、工具雪崩与不可复盘。本文用工程视角补齐缺失的状态机、工具图与失败恢复层,让三层架构真正能跑系统。

📷 Photo by Google DeepMind via Pexels
三层架构的“漂亮图”与“能跑系统”之间差了什么
很多 Agent 文章会给你一张非常顺眼的图:
- Perception(感知):读输入、提取意图
- Decision(决策):规划步骤、选择工具
- Action(执行):调用工具、产出结果
这张图没有错,但它只回答了:Agent 怎么把信息从输入搬运到输出。
线上真正棘手的问题是:
- 工具超时了,状态怎么保存?
- 半成功(前两步成功、第三步失败)怎么办?
- 多个工具互相依赖,怎么避免顺序错乱?
- 同一个请求被重复触发,怎么保证不重复扣费/不重复发邮件?
这些问题都不在“三层”里。
要把三层架构变成工程系统,你至少还需要补三块:
- 状态机(State Machine):把“进行到哪”说清楚
- 工具图(Tool Graph):把“依赖关系”画出来
- 失败恢复(Recovery):把“不确定性”纳入设计
一、状态机:你需要的是“可恢复执行”,不是“下一句话”
1)把 Agent 的“阶段”显式化
一个最常见的线上故障是:执行到一半,模型输出变了、上下文被截断、或服务重启。
如果你没有状态机,系统只能“从头再来”,然后:
- 重复调用工具
- 重复扣费
- 重复写入数据
最小可用的状态机模型(示意):
IDLEPLANNINGWAIT_TOOL(toolName)VALIDATINGDONEFAILED
关键不是状态数量,而是:每个状态的输入/输出边界要可验证。
2)状态必须可持久化,且能重放
建议用“事件”而不是“快照字符串”来驱动状态:
UserRequestReceivedPlanGeneratedToolCallRequestedToolCallSucceededToolCallFailedResultValidated
状态机只做一件事:根据事件推进状态。
这样你就能:
- 重放:把历史事件喂一遍恢复现场
- 回归:把线上事故样本变成测试
- 审计:回答“到底执行过什么”
二、工具图:Planner 不是“列清单”,而是“建依赖图”
1)从步骤列表升级到依赖图
很多 Planner 只输出一个列表:
- 查客户资料
- 生成报价
- 发邮件
但真实系统里通常有:
- 条件分支:如果客户是 VIP,走另一套模板
- 并行子任务:查资料与拉库存可以并行
- 资源竞争:两个工具共用同一个限流额度
这时你需要的不是列表,而是“工具图”。
最小工具图要表达三件事:
- 依赖:A 完成后才能执行 B
- 互斥:A 与 B 不能并行
- 预算:这个子图最多花多少时间/多少 token/多少外部配额
2)把“可并行”标出来,再做调度
不要一上来就并行。
更稳妥的路径是:
- 第一版:全串行,保证正确性
- 第二版:在工具图里标注独立子图,按预算并行
- 第三版:加仲裁器(Arbiter)处理冲突(配额、锁、顺序)
并行不是优化技巧,而是系统设计题。
三、失败恢复:默认世界会失败
1)失败类型不是“成功/失败”二选一
你至少要区分:
- 可重试错误:网络抖动、429、短暂超时
- 不可重试错误:权限不足、参数不合法、资源不存在
- 半成功:写入成功但回执丢了、邮件已发但确认失败
如果你不分类,重试会变成“重试风暴”。
2)幂等与回滚:把“重复执行”当成常态
两条底线:
- 写操作必须有幂等键(idempotency key)
- 需要回滚的动作必须有补偿(compensation)
示例:
- 已创建工单但后续失败:补偿动作是“关闭/标记取消”
- 已扣费但发送失败:补偿动作是“退款/发放额度”
不要幻想“一次就成功”,要设计“失败也可控”。
四、把三层架构补齐成一个可上线的最小形态
你可以用下面这个最小落地架构做对照:
- 输入层(Perception):解析输入 + 提取不可丢约束
- 规划层(Decision):生成工具图(不是列表)+ 预算
- 执行层(Action):按图调度 + 幂等 + 超时
- 状态层(State):状态机 + 事件日志(可重放)
- 治理层(Ops):观测指标 + 失败分类 + 回归集
如果你现在只有“三层”,建议先补:
- 事件日志(能复盘)
- 状态机(能恢复)
- 幂等(不重复)
这三件事能把大多数“线上玄学”变成“可定位的问题”。
五、最小指标:没有指标就没有架构
建议至少落地这些指标:
- 任务完成率(按任务类型拆分)
- 平均工具调用次数(越高通常越不稳)
- 重试次数分布(识别重试风暴)
- 半成功比例(最容易埋雷)
- 幂等冲突命中率(识别重复触发)
当你能把失败归类到“状态/工具/恢复”的某一层,架构才真正开始工作。
常见问题
我需要做多复杂的状态机?
先做到“可恢复”,再谈“优雅”。能用 6-10 个状态解决 80% 的线上问题,就不要一开始做几十个状态。
工具图一定要 DAG 吗?
不一定,但 DAG 是最容易解释与调度的起点。遇到循环依赖或长任务重入时,再引入更强的工作流能力。
只做单 Agent,也要这些吗?
要。单 Agent 只是“少一个协调维度”,但超时、重试、幂等、回滚仍然存在。想做 MVP,可以从“状态机 + 串行工具调用 + 最小观测”开始。