本文由 AI 辅助生成并经结构化整理,代码为教学示例。
Agent 若只靠 while 循环推进,遇到重启、审批或超时后,很难知道任务走到哪一步。生产级实现应把执行过程建模为显式状态机,并持久化每次变化。
1. 状态模型
CREATED -> PLANNING -> RUNNING -> WAITING_APPROVAL-> FAILED -> SUCCEEDED
状态机带来三项能力:可恢复、可审计、可控。模型可以建议下一步,但只有系统能批准状态转换。
2. 声明合法转换
from enum import StrEnum
class State(StrEnum):CREATED="created"; PLANNING="planning"; RUNNING="running"WAITING="waiting_approval"; SUCCEEDED="succeeded"; FAILED="failed"TRANSITIONS = {State.CREATED: {State.PLANNING, State.FAILED},State.PLANNING: {State.RUNNING, State.FAILED},State.RUNNING: {State.WAITING, State.SUCCEEDED, State.FAILED},State.WAITING: {State.RUNNING, State.FAILED},
}
未声明的转换直接拒绝,终态不再接受后继状态。
3. 用乐观锁避免并发推进
UPDATE agent_runs
SET state=:next, version=version+1
WHERE id=:id AND state=:current AND version=:version;
影响行数为零,说明其他 Worker 已抢先推进,当前执行器应重新读取而不是覆盖。
4. 检查点存什么
{"run_id":"run_123","state":"running","step":4,"tool_results":["call_7","call_8"],"pending_action":null,"version":9
}
大对象放对象存储,数据库保存引用与校验值。恢复时加载最后检查点,再判断未完成工具调用能否安全重试。
5. 副作用必须幂等
idempotency_key = f"{run_id}:{step_id}:{tool_name}"
执行前写调用记录,执行后保存结果。恢复时如果同一键已成功,直接复用结果,避免重复发信或重复扣款。
6. 审批是一种正常状态
进入 WAITING_APPROVAL 后应释放 Worker,保存动作预览、风险等级、确认令牌和过期时间。用户确认产生新事件,再由调度器重新入队。
7. 失败与重试分离
技术性失败可以指数退避重试;业务拒绝不重试。保存稳定错误码、尝试次数和下次执行时间,避免无限循环。
验收清单
- 杀进程后任务能继续;
- 两个 Worker 不会重复推进;
- 重放事件不会重复产生副作用;
- 非法转换会被拒绝并记录;
- 审批等待不占计算资源;
- 每次转换能关联触发事件。
结语
状态机把 Agent 的不确定推理装进确定执行骨架。系统必须知道这一步是否允许、是否执行过,以及失败后从哪里恢复。