Agent Graph 详解:用图组织 AI Agent 的工作流

Agent Graph 工作流

Agent Graph 不是“把几个 Agent 画在一张图上”,而是把一次智能任务明确建模成:状态在节点之间流动,边根据结果决定下一步,直到任务完成或被安全终止。

它解决的核心问题也不是让模型变聪明,而是让原本藏在 Prompt 和循环里的执行逻辑变得可见、可控、可恢复。

本文脉络:

  • 一、为什么需要 Agent Graph
  • 二、Agent Graph 到底是什么
  • 三、四个核心元素:节点、边、状态、运行时
  • 四、一个客服 Agent Graph 是怎么运行的
  • 五、它与 Agent Loop、DAG、多智能体有什么区别
  • 六、Agent Graph 真正带来了什么
  • 七、什么时候值得用,什么时候别用
  • 八、怎样设计一张靠谱的 Agent Graph
  • 九、常见陷阱
  • 十、常见问题

一、为什么需要 Agent Graph

最简单的 Agent,通常只有一个循环:模型判断下一步,调用工具,读取结果,再判断下一步。只要任务不复杂,这种写法完全够用。

麻烦出现在流程开始分叉之后。

假设我们要做一个售后客服 Agent,它收到用户消息后可能需要:

  • 查询订单;
  • 判断是否符合退款规则;
  • 缺少信息时追问用户;
  • 高风险退款交给人工审核;
  • 工具超时时重试;
  • 退款完成后发送通知;
  • 无法解决时转人工。

如果这些逻辑全塞进一个循环和一段 Prompt,系统很快会变成“模型自己看着办”。正常路径也许能跑,出错时却很难回答三个问题:它现在走到哪了,为什么走到这里,失败后应该从哪恢复?

Agent Graph 就是把这套隐含流程摊开。

模型仍然负责理解和判断,工具仍然负责执行动作;但谁先运行、下一步去哪、哪些状态要保存、什么条件必须停下来,由图结构明确表达。

二、Agent Graph 到底是什么

Agent Graph 可以翻译成“智能体图”或“Agent 图式工作流”。这个名字容易让人误以为图上的每个节点都是一个 Agent,其实并不是。

一个更准确的定义是:

Agent Graph 是一种用有向图描述 Agent 执行过程的编排模型。节点执行计算或动作,边控制流程跳转,共享状态承载任务上下文。

节点可以是一次 LLM 调用,也可以是普通代码、工具调用、规则校验、人工审批,甚至是另一个子图。真正构成图的,不是“用了几个模型”,而是流程是否被拆成了可识别的步骤和跳转关系。

例如,一个研究型 Agent 可以抽象为:

理解问题 → 制定检索计划 → 搜索 → 评估证据
↑ ↓
└── 证据不足
↓ 证据足够
撰写答案 → 引用检查 → 结束

这里最重要的是那条返回“搜索”的边。它说明 Agent Graph 往往不是一条流水线,而是允许循环:证据不够就继续搜,引用不可靠就退回重写。

三、四个核心元素:节点、边、状态、运行时

理解 Agent Graph,不需要先记框架 API。先把下面四样东西分清楚。

节点:在这里做一件事

节点接收当前状态,完成一项职责,然后返回更新后的状态。常见节点包括:

节点类型 例子 是否一定调用 LLM
推理节点 意图识别、计划生成、结果归纳 通常是
工具节点 查订单、搜网页、执行代码 否
规则节点 金额校验、权限检查、格式验证 否
人工节点 审批退款、确认高风险操作 否
子图节点 调用一套完整的研究或写作流程 不一定

我的建议是:一个节点只承担一个容易描述、容易测试的职责。 “调用模型并处理所有事情”虽然也能成为节点,却失去了画图的意义。

边:决定下一步去哪

边连接节点。它既可以是无条件跳转,也可以根据当前状态选择不同分支。

例如退款判断之后:

def route_refund(state):
if not state["eligible"]:
return "explain_rejection"
if state["amount"] > 500:
return "human_review"
return "execute_refund"

这里的条件最好来自明确的结构化字段,而不是反复让模型用自然语言猜。能用规则稳定判断的事情,就别浪费一次 LLM 调用。

状态:整张图共享的任务快照

状态是 Agent Graph 的“工作台”。节点不应该靠不可见的全局变量互相传话,而应读写一份明确的数据结构:

class SupportState(TypedDict):
user_message: str
intent: str
order_id: str | None
order: dict | None
eligible: bool | None
retry_count: int
messages: list
final_answer: str | None

状态与聊天记录不是一回事。聊天记录只是状态的一部分;订单数据、审批结果、错误次数和下一步计划也都可能属于状态。

状态设计得越含糊,后面越难调试。不要只放一个不断膨胀的 messages,然后期待每个节点都从自然语言历史里重新猜出事实。

运行时:让图真正跑起来

图只是声明,运行时负责执行。一个成熟的运行时通常还要处理:

  • 状态持久化与检查点;
  • 节点重试、超时与错误传播;
  • 暂停和恢复;
  • 并行分支与结果合并;
  • 日志、链路追踪和成本统计;
  • 人工介入。

这部分很容易被忽略。生产里的 Agent Graph,难点往往不在“画出节点”,而在中途挂掉以后能否安全续跑。

四、一个客服 Agent Graph 是怎么运行的

把前面的售后场景串起来,一次退款请求可能这样走:

  1. classify_intent 识别用户要退款,并提取订单号。
  2. 如果订单号缺失,进入 ask_for_order_id,图暂停,等待用户补充。
  3. load_order 调用订单系统,查询商品、支付状态和金额。
  4. check_policy 用确定性规则判断是否满足退款条件。
  5. 不符合规则时,进入 explain_rejection;符合规则则继续。
  6. 小额退款由 execute_refund 直接处理,大额退款进入 human_review。
  7. 审核通过后执行退款,最后由 notify_user 生成回复。

如果查询订单超时,流程不必从意图识别重新开始。运行时可以从最近的检查点恢复,只重试 load_order。如果人工第二天才审批,前一天的任务状态也还在。

这正是图式编排的价值:每一个关键状态都有落点,每一种重要结果都有去向。

五、它与 Agent Loop、DAG、多智能体有什么区别

这些概念经常混在一起,其实它们描述的是不同维度。

概念 核心关注点 能否循环 典型用法
Agent Loop 模型在“思考—行动—观察”中迭代 能 单 Agent 自主调用工具
DAG 工作流 有依赖关系的任务按顺序或并行执行 不能形成环 ETL、批处理、固定流水线
Agent Graph 状态驱动的节点编排和条件跳转 能 有分支、重试、人工介入的 Agent
多智能体系统 多个角色或自治单元如何协作 取决于实现 专家协作、监督者—执行者模式

Agent Loop 可以放进一个节点,也可以由整张图表达。Agent Graph 可以只有一个 Agent,也可以让多个 Agent 分别占据不同节点。

所以,“用了多 Agent”不等于“用了 Agent Graph”,“画了一个 DAG”也不一定能支持 Agent 所需的循环和恢复。

更实用的判断方式是看控制权:

  • 下一步几乎都由模型临场决定,这是偏自主的 Agent Loop;
  • 下一步主要由程序预先规定,这是确定性工作流;
  • 程序限定可走的路线,模型在局部做判断,这是 Agent Graph 最常见的形态。

最后一种通常更适合生产系统。它没有把控制权全部交给模型,也没有把每一步写死。

六、Agent Graph 真正带来了什么

可控,但不必牺牲灵活性

开发者可以限定 Agent 只能进入经过设计的节点,又允许模型在特定节点做语义判断。退款金额必须由规则校验,用户意图可以交给模型识别,两者不冲突。

可观察

“Agent 失败了”是个几乎没法行动的描述。“失败发生在 check_citation 节点,过去一周通过率从 96% 降到 81%”才是工程问题。

图提供了天然的观测边界:可以统计每个节点的耗时、错误率、Token 成本和分支分布,也能回放某次任务经过的路径。

可恢复

有了持久化状态和检查点,长任务不必因为一次网络超时全部重跑。人工审批、用户补充信息这类可能等待数小时的流程,也能先暂停再恢复。

可测试

可以单独测试一个节点,也可以固定状态,验证路由函数是否走向正确分支。相比“给同一个大 Prompt 输入各种案例”,这种测试更接近普通软件工程。

不过别把图当成可靠性的免费午餐。状态合并、幂等、重试上限、循环退出条件,一个都不会因为画了图自动消失。

七、什么时候值得用,什么时候别用

下面这些信号出现两个以上,就值得考虑 Agent Graph:

  • 流程存在多个条件分支;
  • 某些步骤失败后需要局部重试或回退;
  • 任务会暂停,等待用户或人工审批;
  • 多个专家节点需要共享结构化状态;
  • 需要审计执行路径,或统计每一步的质量和成本;
  • 单次任务持续很久,不能接受从头重跑。

反过来,一个“查一次数据,再让模型总结”的功能没必要上图。三步固定流水线也优先写普通函数。图编排会增加状态模型、持久化、调试和运维成本;节点拆得过细,读代码反而比看流程更累。

一个很朴素的起步标准是:当 while 循环里的 if/else 已经让你不敢改,才该认真考虑把它显式建模成图。

八、怎样设计一张靠谱的 Agent Graph

从状态开始,不要从节点开始

先列出任务必须保存的事实、过程数据和控制字段,再决定谁负责更新它们。状态不清楚,节点只会互相甩自然语言。

状态字段还要区分来源。例如 order_amount 来自订单系统,不能被模型生成的文本覆盖;user_intent 来自模型,应保留置信度或原始依据。

把确定性逻辑留给代码

权限、金额阈值、重试次数、必填字段、合规规则,都适合由代码判断。LLM 擅长理解模糊语义,不擅长充当稳定的规则引擎。

给循环设置硬边界

任何环都应有退出条件:最多检索几轮、最多重试几次、什么情况下转人工。否则“继续思考”很容易变成烧 Token 的无限循环。

让有副作用的节点幂等

发邮件、扣款、退款、创建工单都可能因为重试而执行两次。应使用幂等键、执行记录或业务侧去重,不能只相信图运行时“应该不会重复”。

把人工介入当成正常节点

Human-in-the-loop 不是失败兜底,而是一种正常路径。高风险操作在执行前暂停,展示理由和关键状态,等待批准后从检查点继续。这比事后让人收拾残局便宜得多。

节点输出尽量结构化

路由依赖的字段最好使用枚举、布尔值或受约束的对象,并做运行时校验。不要让下一条边依赖“模型回答里好像提到了同意”。

九、常见陷阱

陷阱 直接后果 改进方式
每个动作都包装成 Agent 成本高、延迟大、结果不稳定 规则和普通代码继续用函数
所有信息都塞进消息历史 状态难查询,事实容易被覆盖 单独维护结构化业务状态
图只有成功路径 工具失败后无处可去 显式设计超时、重试、降级和转人工
循环没有次数限制 无限调用模型或工具 设置预算、轮次和终止条件
节点有副作用却不幂等 恢复或重试时重复执行 使用幂等键与执行日志
图拆得过细 节点数量爆炸,理解成本上升 按可测试的业务职责划分边界
把框架 API 当架构 换框架后设计全部推倒 先定义状态、节点契约和路由语义

还有一个常见误区:为了显得“智能”,把所有路由都交给 LLM。实际项目里,最稳的做法往往是混合控制——模型处理模糊判断,代码守住业务边界。

十、常见问题

问题 回答要点
Agent Graph 是一个具体框架吗? 不是。它是一种架构和编排方式,可以由不同框架实现,也可以自己实现。
图上的每个节点都是 Agent 吗? 不是。节点可以是模型、工具、规则、人工步骤或子图。
Agent Graph 必须是 DAG 吗? 不必须。Agent 经常需要反思、重试和补充信息,因此有向图通常允许环。
单 Agent 能用 Agent Graph 吗? 可以。图描述的是执行流程,不要求有多个 Agent。
多 Agent 一定需要图吗? 不一定。简单的主从调用可以直接实现;协作关系复杂时,图会更清楚。
有了 Graph 就能避免幻觉吗? 不能。图能约束流程、增加校验节点,但模型输出仍需证据、规则和评测。
最先应该观测什么? 每个节点的成功率、延迟、Token 成本、重试次数,以及任务实际走过的路径。
最适合从哪里开始? 先把现有流程画出来,只挑一个最痛的分支或恢复问题改造成图,不要一开始做“大一统工作流”。

如果你已经理解 Planner、Executor、Memory 和 Tools,可以把 Agent Graph 看成它们外面的一层“交通系统”:它规定状态怎么流动、执行何时转弯、失败从哪里回来。

真正值得追求的也不是一张看起来复杂的图,而是一条出了问题还能解释、还能恢复、还能继续改进的执行路径。