
Agent 状态机设计别让对话历史替你管理流程一、Agent 需要显式状态很多 Agent 项目早期只靠对话历史推进流程。用户说一句模型猜下一步工具返回一段文本模型再猜下一步。Demo 阶段看起来灵活进入生产后就会出问题步骤跳过、重复执行、失败后不知道退到哪里。Agent 不是聊天窗口它在执行任务。任务就应该有状态机。我第一次把 Agent 放上线时犯过一个典型错误计划器拆完步骤后每个步骤执行完全依赖 prompt 里的请根据上一步结果决定下一步。测试时表现不错但上线两天后出现了一个致命 bug——某用户的文件处理任务卡在第三步工具调用超时了Agent 没有重试也没有报告失败而是直接跳过第三步开始执行第四步。第四步依赖第三步的结果所以直接报错。用户看到的是系统错误日志里只有工具返回那个 null我花了两个小时才定位到问题发生的位置。如果当时有显式状态机执行工具失败会触发明确的重试或降级状态而不是模型自己猜下一步。二、先拆任务状态flowchart TD A[接收任务] -- B[澄清需求] B -- C[生成计划] C -- D[执行工具] D -- E{是否成功} E --|是| F[汇总结果] E --|否| G[重试或降级] G -- C状态机的价值是让系统知道当前处于哪一步、允许哪些动作、失败后能去哪。没有状态机Prompt 再长也只是软约束。agent_states: - collecting_requirements - planning - executing - reviewing - completed - failed状态名称不要太玄。工程团队、产品和运维都能看懂后续排障才方便。状态数量不是越多越好。见过有团队的状态机有 15 个状态——等待用户输入等待工具返回重试计划中降级评估中……流程复杂到维护人员都看不懂。建议控制在 6-8 个核心状态每个状态对应一个用户可见的阶段。产品侧也更容易理解任务在规划中比任务在 RETRY_EVALUATION_PENDING 状态强得多。三、状态转换要可验证type AgentState string const ( StatePlanning AgentState planning StateExecuting AgentState executing StateReviewing AgentState reviewing ) type Transition struct { From AgentState To AgentState Reason string }每次状态转换都要记录原因。比如从 executing 到 reviewing是因为工具全部执行成功从 executing 到 planning是因为工具失败需要重新规划。状态变化不能只存在模型回答里。还要限制非法转换。已经 completed 的任务不应该再执行工具failed 的任务需要人工恢复或重新创建。系统层拦住非法转换比指望模型自觉可靠。实现时建议用一个 allowlist 控制合法转换。比如 collecting_requirements 只能转到 planning 或 failedplanning 只能转到 executing 或 failed如果计划不可行。用 map 硬编码这些规则不要依赖模型判断哪些转换合法。曾经遇到过一个线上事故Agent 在 completed 状态后因为用户追问了一句能再细化一下吗模型在对话历史里看到之前的工具调用成功直接在 prompt 里要求再次调用写入工具创建了重复的工单。如果有 allowlist系统会直接拒绝completed 状态下不允许调用写作工具拦截这次异常操作。四、状态机要连接观测和恢复Agent 出问题时排障人员需要知道任务卡在哪个状态、最近一次工具调用是什么、失败原因是否可重试。状态机如果只在内存里一重启就丢那还不如没有。agent_state_store: persist_state: true record_last_tool_call: true record_retry_count: true support_resume: true支持恢复也很重要。任务执行到一半服务重启系统应该能从持久化状态继续而不是重新执行所有工具。尤其是创建工单、发送通知、写数据库这类有副作用动作重复执行会制造新事故。恢复时要重新加载上下文包括对话历史、工具调用历史、当前状态和剩余预算。但如果对话历史太长可以压缩后加载不必全量恢复。关键是不丢失状态不是不丢失每一段对话文字。状态机还可以给用户更清晰的反馈。不要只显示处理中而是显示正在检索资料正在执行工具正在复核结果。用户知道系统在做什么就更愿意等待。最后状态机不要设计得过细。每个小动作都变成状态会让流程难以维护。状态粒度应该和恢复、观测、权限控制有关能支撑工程动作就够。状态机还要有版本。Agent 流程升级后旧任务可能仍停留在旧状态定义里不能强行套新流程。可以在任务记录里保存state_machine_version恢复时按对应版本解释状态。agent_state_versioning: persist_version: true allow_migration: explicit_only reject_unknown_state: true这样做虽然多一层管理但能避免流程升级把历史任务恢复坏。版本迁移也要慎重。如果旧状态和新状态差异太大与其强行迁移不如让旧任务在旧流程里走完新任务用新流程。强制迁移可能把正常任务变成无法处理的任务。五、总结Agent 状态机要显式管理任务阶段、允许动作、状态转换、失败恢复和用户反馈。对话历史可以提供上下文但不能替你管理流程。真正可落地的 Agent需要一套能被代码检查的状态机。生产系统里硬编码的 allowlist 比 prompt 里的请严格遵守流程可靠得多。