状态机——Agent 的行为骨架
前言 做 Agent 开发时,最让工程师头疼的问题往往不是底层大模型(LLM)不够聪明,而是 Agent 的行为难以可控。在真实的业务场景中,用户的一句话可能隐含多种意图,或者意图非常模糊。这就要求 Agent 必须学会在不同的"对话阶段"之间灵活切换——从最初的寒暄问候,到多轮的信息收集,再到决定调用外部工具,最后与用户确认并结束对话。 如果仅仅依靠 Prompt 让大模型自主决定下一步该做什么(例如纯粹的 ReAct 模式),系统会变得极其脆弱。模型可能会陷入死循环、产生幻觉,或者跳过关键的业务校验步骤。为了解决这种复杂性,我们需要引入软件工程中久经考验的标准工具:状态机(State Machine)。它能为概率性的 LLM 提供一个确定性的行为骨架。 什么是状态机 理解状态机最直观的方法是想象一扇普通的门。这扇门有两个状态:开 与 关。你可以对它施加两个事件(动作):推 与 拉。 如果你对一扇处于关状态的门执行推事件,门就会进入开状态。但如果门已经是开的状态,再执行推就没有任何意义(甚至是一个非法操作)。这就是状态机的核心逻辑:当前状态 + 触发事件 $\to$ 新状态。 在计算机科学中,它的形式化定义通常是一个五元组: 状态集合($S$):系统所有可能状态的有限集合。 初始状态($s_0$):系统启动时的默认状态($s_0 \in S$)。 事件集合($E$):触发状态改变的输入或条件。 转移函数($\delta: S \times E \to S$):定义了在特定状态下接收到特定事件时,应该转移到哪个新状态。 终止状态集合($F$):表示流程结束的状态集合($F \subseteq S$)。 在构建 Agent 时,我们通常会遇到两种常见的状态机类型: 有限状态机(Finite State Machine, FSM):状态和事件的数量是有限的,所有的状态流转(转移函数)都是在代码中严格预先定义好的。它非常适合逻辑固定、边界清晰的任务。 图状态机(Graph-based State Machine):这是目前复杂 Agent 框架的主流(如 LangGraph)。它的状态流转可以是动态计算的,原生支持条件分支、循环回路以及并行处理,更适合处理多轮对话和复杂的逻辑编排。 为什么 Agent 需要状态机 一个可靠的 Agent 绝不能是一个"黑盒"。它的运行生命周期应该经历明确的阶段,并且每个阶段(状态)都有单一、清晰的职责。我们来看一个典型的 Agent 运转流程: flowchart TD A[空闲 IDLE] -->|用户提问| B[分析意图 ANALYZING] B -->|需要工具| C[调用工具 TOOL_CALL] B -->|无需工具| D[生成回复 RESPOND] C -->|工具完成| D D -->|发送回复| A 在这个流程中,核心关键点在于意图分析后的条件分支。有些用户请求(如"你是谁?")可以直接生成回复;而有些请求(如"今天香港的天气如何?")则必须先去调用天气 API。 ...