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 看成它们外面的一层“交通系统”:它规定状态怎么流动、执行何时转弯、失败从哪里回来。

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