跳到主要内容

在写第一个 Prompt 之前,先设计好你的 Agent 状态机

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数工程师在构建第一个 LLM agent 时,都会遵循相同的流程:写一个系统提示词,添加一个调用模型的循环,撒上一些工具调用逻辑,然后看着它在简单的测试用例上运行。六周后,这个 agent 变成了一团难以理解的嵌套条件、粘贴在 f-string 里的 prompt 片段,以及散落在三个文件中的重试逻辑。添加一个功能需要通读整个代码。遇到生产 bug 就得盯着一个上千 token 的上下文窗口,试图重建模型当时在"想"什么。

这就是"意大利面式 agent"问题,在以 prompt 为起点而非设计为起点的团队中几乎普遍存在。解决方案不是更好的提示技巧,也不是换一个框架,而是一种纪律:在写第一个 prompt 之前,先设计好状态机

为什么 Prompt 优先的构建方式在规模化时总会失败

Prompt 优先开发的吸引力是真实存在的。你可以在一小时内让系统跑起来。模型能处理那些显式编码需要数周时间的歧义。感觉就像直接跳到了有趣的部分。

但 prompt 优先的 agent 携带着快速积累的结构性债务。没有显式状态,agent 的行为被隐式编码在 prompt、上下文历史以及模型调用周围散落的条件逻辑中。"agent 现在处于什么状态?"这个问题没有权威答案,因为这个概念在你的系统中根本不存在——只有一个不断增长的对话历史 blob,模型每次运行时对它的解读都不同。

一项分析了七个主要框架中超过 1,600 条标注 agent 执行轨迹的研究发现,42% 的失败可以追溯到系统设计问题:规范不完整、agent 被赋予了模糊的需求、没有清晰地定义"完成"意味着什么。另有 37% 是多 agent 场景下的协调失败,agent 在不同的共享状态心智模型下运行,并悄悄覆盖彼此的工作。这些不是模型失败,而是架构失败——而且通过显式状态设计完全可以预防。

状态机能给你什么

agent 的状态机在概念上很简单:一组有限的命名状态、状态之间的定义转换,以及触发每个转换的显式条件。它对 LLM agent 的强大之处在于,它将所有你本来会烘焙进 prompt 的隐式决策外部化了。

考虑一个客服 agent。没有显式状态,你会有一个系统提示词,大意是"你是一个有帮助的支持 agent,帮助用户解决问题,必要时进行升级"。"必要时"这个词承担了巨大的工作量。有了状态机,你会有:

  • greeting — 从用户那里收集问题陈述
  • classifying — LLM 确定问题类别,路由到适当的解决路径
  • resolving — LLM 提出解决方案,查询知识库
  • confirming — 用户确认解决方案是否有效
  • escalating — 触发人工交接,并附上完整上下文
  • closed — 终止状态,记录结果

每个状态都有明确的目的、明确的输入和明确的退出条件。LLM 是特定状态的组件——而不是所有行为的全局协调者。当出现问题时,你能精确知道它处于哪个状态、收到了什么输入、以及哪个转换触发错误了。

这不仅仅是理论上的整洁。它改变了在操作层面什么是可能的:你可以记录每个状态转换。你可以从保存的检查点重放任何执行。你可以编写单元测试,断言"在状态 X 给定这个输入,agent 应该转换到状态 Y"。当 agent 的逻辑主要存在于 prompt 内部时,这些都是不可行的。

在接触 LLM 之前设计拓扑结构

实际操作过程是:将 agent 设计视为与设计数据库 schema 或 API 合同一样的一等工件——在写任何代码之前进行审查。

从映射快乐路径开始。成功完成任务有哪些离散阶段?给每个阶段起一个对阅读日志文件的人有意义的名字,而不是对 LLM 有意义的名字。然后映射失败边——不是作为异常处理器,而是作为一等状态。retrying_tool_call 状态比 try/except 块更好。waiting_for_human_review 状态比塞在条件语句里的升级 prompt 更好。

对于每个状态,明确回答三个问题:

进入这个状态时,agent 知道什么? 这定义了你的状态 schema——携带跨转换上下文的类型化数据结构。LangGraph 鼓励使用带有标注 reducer 函数的 TypedDict;具体工具不重要,但定义哪些数据流经其中的纪律至关重要。状态 schema 迫使你决定哪些信息是真正需要的,哪些只是"在对话历史的某个地方"。

agent 在这个状态下可以采取哪些行动? 这约束了 LLM 可用的工具调用。处于 classifying 状态的 agent 可能不应该能够发起退款。按状态限制可用工具消除了整类幻觉工具调用——这是长视野任务中最常见的失败模式之一。

从这个状态出去的有效转换是什么,是什么触发了它们? 这是你将 LLM 调用映射到拓扑结构的地方。模型的输出——一个分类、一个是/否判断、一个结构化决策——是触发转换的事件。模型不决定下一步去哪里;状态机根据模型返回的内容来决定。这是一个微妙但至关重要的反转。LLM 提供推理;状态机提供控制流。

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates