Agent 中的状态机

用状态机管理 Agent 的执行流程:定义状态、转换条件和动作。状态机让 Agent 的行为可预测、可测试、可恢复。

#type / concept #status / evergreen #tech / ai #tech / architecture

[!info] related notes

Agent 中的状态机

一句话定义

状态机是用有限个状态和状态之间的转换规则来描述 Agent 行为的模型。它让 Agent 的执行流程从”模型自由发挥”变成”在预定义的状态空间中转换”,从而可预测、可测试、可恢复。

它解决什么问题

完全由 LLM 自由决定执行流程的 Agent 有两个问题:

  1. 不可预测: 你不知道 Agent 下一步会做什么
  2. 难以恢复: 中断后不知道应该回到哪个状态

状态机通过预定义状态和转换规则,给 Agent 一个”有限的行为空间”。

核心原理

状态机的基本组成

状态 (State):    Agent 当前处于什么阶段
转换 (Transition): 从一个状态到另一个状态的条件
动作 (Action):   进入/退出状态时执行的操作
事件 (Event):    触发转换的外部或内部信号

Agent 状态机示例

┌─────────┐     用户输入     ┌──────────────┐
│  Idle   │ ──────────────→ │ Collecting   │
│ (空闲)  │                 │ (信息收集)    │
└─────────┘                 └──────┬───────┘
      ↑                            │ 信息完整
      │                            ▼
      │                     ┌──────────────┐
      │                     │ Processing   │
      │                     │ (推理处理)    │
      │                     └──────┬───────┘
      │                            │ 需要工具
      │                            ▼
      │                     ┌──────────────┐
      │                     │ Tool Calling │
      │                     │ (工具调用)    │
      │                     └──────┬───────┘
      │                            │ 工具完成
      │                            ▼
      │                     ┌──────────────┐
      │        完成          │ Generating   │
      └──────────────────── │ (生成回复)    │
                            └──────────────┘

状态定义

from enum import Enum

class AgentState(Enum):
    IDLE = "idle"                    # 空闲,等待用户输入
    COLLECTING = "collecting"        # 收集信息
    PROCESSING = "processing"        # LLM 推理中
    TOOL_CALLING = "tool_calling"    # 工具执行中
    GENERATING = "generating"        # 生成回复
    WAITING_APPROVAL = "waiting"     # 等待人类审批
    COMPLETED = "completed"          # 完成
    ERROR = "error"                  # 错误

转换规则

TRANSITIONS = {
    (AgentState.IDLE, "user_message"): AgentState.COLLECTING,
    (AgentState.COLLECTING, "info_complete"): AgentState.PROCESSING,
    (AgentState.PROCESSING, "need_tool"): AgentState.TOOL_CALLING,
    (AgentState.PROCESSING, "no_tool"): AgentState.GENERATING,
    (AgentState.TOOL_CALLING, "tool_done"): AgentState.PROCESSING,
    (AgentState.TOOL_CALLING, "need_approval"): AgentState.WAITING_APPROVAL,
    (AgentState.WAITING_APPROVAL, "approved"): AgentState.TOOL_CALLING,
    (AgentState.WAITING_APPROVAL, "rejected"): AgentState.PROCESSING,
    (AgentState.GENERATING, "done"): AgentState.COMPLETED,
    (AgentState.GENERATING, "error"): AgentState.ERROR,
}

典型工程实现

用 LangGraph 实现状态机

LangGraph 的 StateGraph 本质上就是一个状态机:

from langgraph.graph import StateGraph, END

graph = StateGraph(AgentState)

# 节点 = 状态的动作
graph.add_node("collect", collect_info)
graph.add_node("process", process_with_llm)
graph.add_node("call_tool", call_tool)
graph.add_node("generate", generate_response)

# 边 = 转换规则
graph.set_entry_point("collect")
graph.add_conditional_edges("collect", route_after_collect)
graph.add_conditional_edges("process", route_after_process)
graph.add_edge("call_tool", "process")
graph.add_edge("generate", END)

状态持久化

from langgraph.checkpoint import SqliteSaver

# 状态持久化到数据库
checkpointer = SqliteSaver.from_conn_string(":memory:")
app = graph.compile(checkpointer=checkpointer)

# 每次转换都自动保存 checkpoint
# 中断后可以从 checkpoint 恢复

常见设计模式

1. 分层状态机

顶层状态(如”对话中”、“执行中”)内部嵌套子状态机。

2. 事件驱动状态机

状态转换由事件触发,而不是由代码主动轮询。

3. 有限状态 + LLM 决策

状态是有限的,但每个状态内的具体行为由 LLM 决定。

常见坑

  1. 状态太多: 超过 10 个状态就难以维护
  2. 转换条件模糊: 导致状态机”卡住”
  3. 不做状态持久化: 重启后丢失状态
  4. 状态和行为混在一起: 状态机只管转换,行为应该在节点函数中

和其他概念的关系

  • vs 图工作流: 状态机是图工作流的特例(有状态的有向图)
  • vs 工作流编排: 状态机是编排的一种实现模式
  • vs Run State: Run State 是状态机的具体应用
  • vs Checkpoint: Checkpoint 是状态持久化的机制

总结

状态机让 Agent 的行为从不可预测变成有限可预测。它不是限制 Agent 的能力,而是给 Agent 一个可靠的执行框架。

参考资料

创建于 2026/6/30 更新于 2026/7/15