图工程有两重含义。《深入图工程》讨论的是以图数据为中心的系统工程——图数据库、图计算引擎、知识图谱。本文讨论第二重:当 Coding Agent 系统本身成为一个图结构的工程制品时,传统图工程的哪些原理可以复用,哪些问题是全新的。

2024-2026 年间,Agent 系统的复杂度从"一个 LLM 调用 + 几个工具"膨胀到"多个 Agent 组成有向图协作完成多步任务"。LangGraph、CrewAI、AutoGen 等框架的核心抽象无一例外都是图——状态图、工作流 DAG、协调拓扑。Agent 的编排本质上是一个图调度问题,而图调度的工程经验在分布式系统领域已经积累了二十年。

Agent 系统中的三类图结构

Agent 系统至少包含三类不同性质的图,它们在生命周期、变化频率和工程约束上各不相同:

执行图(Execution Graph):Agent 单次任务执行的控制流。每个节点是一个计算步骤(LLM 调用、工具执行、条件判断),边表示控制转移。LangGraph 的 StateGraph 是这一类的典型代表。执行图在运行时动态展开,可能包含循环(Agent 反复修正直到满足条件),因此严格说不是 DAG 而是有向图。

协调图(Coordination Graph):多个 Agent 之间的通信和协作拓扑。节点是 Agent 实例,边表示消息通道或委派关系。这类图的拓扑在设计时确定,但运行时可能动态增减节点(如按需创建 sub-agent)。

知识图(Knowledge Graph):Agent 用于理解代码的结构化上下文。节点是代码实体(函数、类、模块、变量),边是调用关系、继承关系、数据流依赖。这类图在 Agent 的 planning 阶段被查询,为 LLM 提供定位精确的上下文而非全量代码。

三类图的交叉点是:协调图决定"谁来做",执行图决定"怎么做",知识图决定"做什么"。一个成熟的 Coding Agent 系统需要同时管理这三类图,它们之间通过状态传递耦合。

执行图:从 LangGraph 状态机说起

LangGraph 的图语义

LangGraph(LangChain 团队,2024 年发布 1.0)是 2026 年 Coding Agent 领域使用最广的有状态编排框架。其核心模型:

  • 节点(Node):一个 Python 函数,接收当前状态、返回状态更新。可以是 LLM 调用、工具执行、纯逻辑判断。
  • 边(Edge):节点间的转移关系。支持条件边(根据状态值路由到不同下游节点)和无条件边。
  • 状态(State):贯穿整个图执行的共享数据结构,由 TypedDict 或 Pydantic model 定义。每个节点只能通过 reducer 函数修改状态的特定字段。
  • 检查点(Checkpoint):状态的持久化快照。支持断点续跑、time-travel debugging、human-in-the-loop 中断。

与传统工作流引擎(Airflow、Temporal)的关键差异:LangGraph 的边支持循环。Agent 可以反复执行"思考→行动→观察"循环直到任务完成,而不是只走一遍 DAG。这使得 LangGraph 本质上是一个有限状态机(FSM)框架而非纯 DAG 调度器。

执行图的工程问题

把 Agent 工作流建模为图之后,传统图工程的若干经典问题立即浮现:

状态爆炸。一个有 N 个条件分支节点的执行图,理论上有 O(2^N) 种路径。测试时不可能穷举所有路径组合——这与模型检查(model checking)领域的状态空间爆炸是同一问题。工程上的应对是:限制图的循环次数上限(LangGraph 的 recursion_limit)、对关键路径做 property-based testing、在 checkpoint 层面做回归快照对比。

非确定性。LLM 的输出本质上是概率性的,即使相同输入也可能产生不同的条件分支决策。这意味着同一个执行图的两次运行可能走出完全不同的路径。传统工作流引擎假设节点行为确定性,重试语义清晰(幂等重跑);Agent 图的重试需要额外设计——是重跑整个子图还是只重跑失败节点,重跑时的上下文是否要包含前一次的失败信息。

热点节点。执行图中某些节点被多条路径共享(类似图论中的高入度节点)。比如一个"代码审查"节点被"编写代码"、“修复 bug”、"重构"三条路径共用。这个节点的延迟和资源消耗会成为整个图的瓶颈。缓解手段类似图计算中的 vertex-cut:把热点节点复制为多份独立实例,各自服务不同的上游路径。

可观测性。执行图的 trace 天然是树形或 DAG 结构——OpenTelemetry 的 span 模型恰好可以映射。LangSmith、Langfuse 等 Agent 可观测性平台本质上是在做图的可视化和路径分析:哪条路径延迟最高、哪个节点失败率最高、哪个循环最容易发散。

与传统工作流的对比

维度 传统工作流(Airflow/Temporal) Agent 执行图(LangGraph)
图结构 DAG(无环) 有向图(允许循环)
节点行为 确定性 概率性(LLM 驱动)
边路由 编译时确定或基于简单条件 运行时由 LLM 输出决定
状态模型 XCom / 外部存储 一等公民,内置 reducer
错误恢复 重试 + 幂等 重试 + 上下文感知回退
终止条件 所有 leaf 节点完成 满足目标条件或达到递归上限

协调图:多 Agent 拓扑

四种基本拓扑

当系统需要多个 Agent 协作时,它们的通信结构形成一张协调图。2026 年的框架和生产系统中观察到四种基本拓扑:

星形(Supervisor)。一个中心 Agent 负责任务分解和分发,多个专职 Agent 执行子任务并向中心报告。LangGraph 的 multi-agent 示例、Claude Code 的 subagent 模式都是这种拓扑。优点是控制流清晰、容易推理;缺点是中心 Agent 成为瓶颈和单点故障。

链式(Pipeline)。Agent 按固定顺序依次处理,前一个的输出是后一个的输入。适合明确的阶段性任务(需求分析 → 设计 → 编码 → 测试)。CrewAI 的 sequential process 属于此类。优点是简单可预测;缺点是缺乏反馈循环,前期错误会传播到后期。

层级(Hierarchical)。多层 supervisor 形成树状结构,顶层 Agent 分解为子任务,子任务 Agent 可以进一步分解。AutoGen 的嵌套对话和 LangGraph 的子图(subgraph)机制支持这种模式。适合复杂任务的递归分解。

网状(Mesh/Swarm)。Agent 之间平等通信,没有固定的中心控制者。OpenAI Swarm(2024 年开源的实验框架)探索了这种模式:Agent 之间通过 handoff 传递控制权,谁最适合处理当前状态就由谁接手。优点是灵活、无单点故障;缺点是难以推理全局行为、容易出现活锁。

协调图的工程约束

从图工程角度看,协调图的设计面临几个硬约束:

通信开销与图直径。两个 Agent 之间的信息传递跳数(协调图的直径)直接影响协作延迟。星形拓扑的直径是 2(任意两个 worker 通过 supervisor 中转),网状拓扑在最坏情况下直径等于节点数。实际系统通常在星形和全连接之间寻找平衡——让需要频繁通信的 Agent 直接连接,其他走中心路由。

状态一致性。多个 Agent 并发修改共享代码库时,一致性问题等同于分布式系统中的并发写入。实际方案包括:乐观锁(每个 Agent 基于当前快照修改,提交时检测冲突并重做)、悲观锁(一次只有一个 Agent 持有某文件的修改权)、或分区隔离(每个 Agent 只修改自己负责的文件集)。

容错与优雅降级。协调图中的某个 Agent 失败(LLM 调用超时、工具执行报错)时的处理策略:重试该节点、将任务转交给其他同类 Agent、或向 supervisor 报告并由其重新规划。这与分布式系统中的故障检测和任务重调度是同构问题。

Agent 记忆的图结构

Episodic Memory Graph

Agent 的对话历史和任务执行轨迹形成一张时序事件图(episodic memory graph)。节点是事件(用户请求、Agent 决策、工具调用结果),边表示因果关系或时间顺序。当 Agent 需要回顾"上次遇到类似问题时怎么解决的",本质上是在这张图上做模式匹配。

Mem0、Zep 等 Agent 记忆系统采用的正是图存储:将对话片段抽取为实体-关系三元组存入图数据库,查询时通过图遍历而非向量相似度来召回相关记忆。优势在于因果链路的保持——向量检索只能找到"语义相似"的片段,图遍历可以找到"因果相关"的片段。

Skill Dependency Graph

Coding Agent 的能力集合形成一张依赖图。每个 skill(如"运行测试"、“创建 PR”、“安装依赖”)是一个节点,skill 之间的前置条件是有向边。比如"创建 PR"依赖"提交代码",“提交代码"依赖"通过测试”。

Claude Code、Codex 等 harness 系统中,这张依赖图决定了 Agent 的 planning:给定一个目标状态,系统需要在 skill dependency graph 上找到一条从当前状态到目标的可行路径。这本质上是图上的路径规划问题——带权最短路径(权重是预估的执行成本和风险)。

代码知识图谱作为 Agent 运行时上下文

代码知识图谱将代码库的结构关系(调用图、继承树、模块依赖、数据流)持久化为可查询的图结构。与直接在 prompt 里塞代码文本相比,图结构的优势是支持精确的多跳定位:

  • “这个函数的调用者中有哪些也修改了同一个全局变量”——两跳查询
  • “这个接口的所有实现类里,哪些覆盖了 validate 方法”——条件过滤遍历
  • “从这个入口函数出发,经过最多 3 次调用能到达哪些数据库操作”——限定深度的可达性分析

Graphify(tree-sitter AST + LLM 抽取 + Leiden 聚类)和 Sourcegraph SCIP/LSIF 是两种代表性方案。前者侧重语义关系(“这个类负责什么”、“这两个模块的关系是什么”),后者侧重精确的符号级引用关系。两者在 Coding Agent 系统中扮演互补角色:SCIP/LSIF 提供精确的定义-引用跳转,Graphify 提供模块级的概念地图。

关键工程决策是知识图谱的更新策略。代码库在开发过程中持续变化,知识图谱如果不能增量更新就会快速过时。实际方案分三种:

  1. 全量重建:每次 Agent 任务开始时重新扫描整个代码库。简单但慢,只适合小型代码库。
  2. 增量更新:监听文件变更事件,只重建受影响的子图。需要精确的依赖追踪——修改一个函数签名可能需要更新所有调用者节点。
  3. 惰性验证:图结构保持旧状态,查询结果在使用前与当前文件内容做一致性校验。查到的节点如果对应的代码已变更则标记为 stale 并实时刷新。

从传统图工程到 Agent 图工程

可复用的原理

传统图工程的若干核心洞察直接适用于 Agent 图系统:

幂律分布依然存在。Agent 系统中某些节点的负载天然远高于其他节点——supervisor agent 收到的消息量遵循幂律分布,代码知识图谱中核心模块的入度远高于外围工具类。处理方式与超级节点一致:分片、副本、采样。

分区的 trade-off 不变。多 Agent 系统的任务分配等价于图分区——把一个大任务切成子任务分配给不同 Agent,目标是最小化 Agent 间通信(等价于最小化跨分区边)。这是 NP-hard 问题,启发式方案的质量决定了整体协作效率。

可观测性工具可以迁移。图数据库领域的查询分析工具(执行计划可视化、热点路径分析、慢查询检测)在概念上可以直接应用到 Agent trace 分析——LangSmith 本质上就是"Agent 图的慢查询分析器"。

全新的挑战

但 Agent 图有几个传统图工程从未面对的问题:

节点行为不可预测。传统图计算中,每个顶点的计算逻辑是确定的函数;Agent 图中,节点的行为由 LLM 驱动,相同输入不保证相同输出。这使得传统的死锁检测、终止性证明等形式化分析方法失效。

图结构在运行时自我修改。Agent 可以在执行过程中决定创建新的 sub-agent(增加协调图的节点)、发现新的代码依赖关系(扩展知识图谱的边)。图的拓扑不是静态的设计时产物,而是运行时的涌现结果。

成本模型完全不同。传统图计算的成本主要是 CPU 和网络带宽;Agent 图的瓶颈是 LLM API 调用的延迟和费用。一次"不必要的 LLM 调用"的代价远高于传统图计算中一次"多余的消息传递"。这要求在图设计阶段就考虑"哪些边的激活是高成本的",优先用确定性逻辑(非 LLM)实现的节点来过滤,减少 LLM 节点的触发次数。

工程实践模式

执行图的分层设计

生产级 Coding Agent 系统通常采用分层执行图:

  • 顶层:任务级 DAG(需求分析 → 方案设计 → 实现 → 验证),节点间是粗粒度依赖
  • 中层:每个顶层节点内部展开为一个可循环的状态机(思考 → 行动 → 观察 → 判断是否完成)
  • 底层:单次 LLM 调用 + 工具执行的原子操作

这种分层与操作系统的进程-线程-指令层次类似,也与图计算中的超图(hypergraph)分解有对应关系。分层的价值是隔离复杂度:顶层负责全局 planning 的正确性,中层负责单步执行的鲁棒性,底层负责 LLM 调用的效率。

测试 Agent 图

Agent 图的测试困难程度高于传统工作流:

  • 路径覆盖不现实:有循环的图路径数量无限,只能测试关键路径和边界条件
  • 断言难以写:LLM 输出的正确性是模糊的("回答是否有帮助"没有精确的 assertEqual)
  • 环境依赖重:Coding Agent 需要真实的代码库、文件系统、构建工具链作为测试环境

实际方案是分层测试:

  1. 节点级单测:用确定性的 mock LLM 响应测试单个节点的状态更新逻辑
  2. 子图集成测试:用小型代码库 fixture 测试关键子图的端到端行为
  3. 全图回归测试:录制生产 trace 的 checkpoint 序列,用新版本的图重放关键 checkpoint,对比输出的 diff

图的版本管理

Agent 执行图本身也需要版本管理。当你修改了一个 Agent 的 prompt 或增加了一条条件边,如何确保不会引入回归?

LangGraph 的检查点机制提供了一种思路:每次图结构变更后,选取一组有代表性的输入,分别在新旧图上运行,对比 checkpoint 序列的差异。这类似于数据库 schema migration 中的 shadow testing——在生产流量上同时跑两个版本,对比结果但只用旧版本的输出。

选型参考

需求场景 推荐起点 理由
单 Agent + 工具调用 + 简单循环 LangGraph StateGraph 状态管理和循环支持是核心价值
固定流程的多 Agent 协作 CrewAI sequential/hierarchical 声明式配置比编程式 graph 更快上手
需要动态创建/销毁 Agent LangGraph + 子图动态实例化 子图机制支持运行时拓扑变更
研究性多 Agent 对话 AutoGen / Microsoft Agent Framework 对话式协调比图式调度更灵活
代码库级别的知识图谱构建 Graphify + 图数据库(Neo4j/FalkorDB) tree-sitter 精确 + LLM 语义补充
需要 Human-in-the-loop LangGraph checkpoint + interrupt 内置中断/恢复机制

参考资料