Graph Engineering 又一个新工程?

Graph Engineering 是把复杂 Agent 工作里的任务、依赖、验证、重试和人工决策画成一张可执行的控制图。节点负责一件边界清楚的事,边决定结果往哪里走、什么条件能放行、失败后回到哪里,状态记录这次运行走到哪一步。

Loop Engineering 管一个局部闭环怎么持续工作,Harness Engineering 管整套运行环境怎样可靠。Graph Engineering 关心多个 loop、Agent、脚本、测试和人之间如何协作。先把一个小 loop 跑稳,再把周围真正需要的并发、验证和审批接上去,才是实用的路径。

什么是 Graph Engineering

一个 Agent 改小功能时,线性流程很自然:读代码,改代码,跑测试,提交结果。任务只有一条路径,写成顺序步骤没什么问题。

事情一多,线性写法会把关系藏起来。比如审一个 PR,正确性、安全性和性能检查通常互不依赖;把三项检查写成先后顺序,只会让后两项平白等待。三份报告出来后,去重、复现和裁决又需要看到完整结果,那里才应该汇合。确认的问题交给修复节点,测试失败再回到修复节点,这时已经有分叉、汇合和回环了。

新 PR
  │
  ├── 正确性审查 ─┐
  ├── 安全审查 ───┼── 去重与复现 ── 独立验证 ── 修复 ── 测试 ── 发布审查
  └── 性能审查 ───┘                              ▲        │
                                                 └────────┘
                                                   测试失败

Graph Engineering 就是把这些关系从模型的临场判断里拿出来,写成系统可以检查和执行的结构。本文说的图主要是控制图,排的是谁先执行、谁可以并行、谁能放行或打回,不是数据库里的数据血缘图。

图里的节点不一定是 Agent。一个节点可以是测试套件、JSON 校验、去重脚本、人工审批、CI 记录,或者某个外部事件。能由普通代码稳定完成的事,应该继续交给普通代码,别为了画图把每一步都变成模型调用。

图里的东西 它回答的问题
节点 谁负责什么工作,输入是什么,输出是什么
哪些结果要交给谁,谁必须等待谁,什么条件才能放行
状态 这次运行已经完成什么,失败在哪里,恢复时从哪继续
证据 节点凭什么算完成,谁可以否决它
权限与预算 哪些动作能自动执行,花到什么程度必须停下来

一张图通常有两部分。执行图处理任务拆分、并发、汇合、修复和重试。验证与治理图处理谁确认结果正确、哪个指标会失真、谁可以否决一个看似成功的节点。只画执行图,任务可能跑得很顺,却不一定朝正确目标前进。

Graph Engineering、Loop Engineering 和 Harness Engineering 的区别

这三个词说的是同一套系统的不同层次。

概念 它关心什么 一个最小例子
Prompt 模型一次要完成什么 分析这段报错并给出修复建议
Loop Engineering 一件事怎样行动、验证、调整和停止 跑 typecheck,修错误,再跑一次
Graph Engineering 多个任务和多个 loop 怎样依赖、并行、汇合和互相约束 审查、验证、修复、测试、审批组成的系统
Harness Engineering 这些节点靠什么可靠运行 工具、项目知识、状态、权限、验证、恢复和日志

Loop 是图里的局部反馈路径

Loop 最小的形状是:行动,观察结果,判断是否达标,未达标就调整后再试。修复和测试是一条 loop;每周检查 CI 的 routine 是一条 loop;研究任务里不断搜索、去重和验证新发现,也是一条 loop。

Graph 没有取代 Loop。修复和测试之间的回环,只是 PR 审查图里的一小段。Graph 还要处理正确性、安全性和性能审查能否并行,哪几个结果必须汇合,什么证据才能让修复进入发布审查,验证器结论冲突时谁来裁决。

DAG 也属于 Graph。DAG 只沿有向边往前走,适合拉取资料、提取事实、生成报告这类不需要回头的任务。测试失败回到修复节点后,流程有了 cycle,不再是 DAG,但仍然是一张图。实际系统里,主路径通常尽量保持 DAG,失败和复核走少量受控循环。

Harness 是图能跑起来的环境

图规定谁该做什么,Harness 决定节点有没有工具可用、能不能读到正确的项目知识、失败后能不能恢复、危险动作会不会被拦住。

一个图里写了“跑回归测试”,Harness 要提供可运行的测试命令、环境、日志和测试数据。一个图里写了“独立验证”,Harness 要保证验证器拿到的是验收契约和真实证据,而不是实现 Agent 的自我报告。一个图里写了“并行修改代码”,Harness 要提供 worktree、沙箱、文件边界和合并检查。

没有 Harness 的图,很容易停在白板上。没有 Graph 的 Harness,复杂工作又会重新塞回一个聊天窗口,依赖和职责靠模型临场猜。

Graph 需要接触图外的现实

图再完整,也可能只是在组织一群互相确认的 Agent。实现 Agent 修改了验收标准,reviewer 对照另一个 Agent 写的摘要,测试又只测到错误 mock 的逻辑,所有节点都说通过,系统仍然是错的。

每个关键节点都需要独立证据:真正跑过的测试、实际浏览器路径、CI 记录、可检查的 commit、真实用户或生产观测。这类证据常被称为 Reality Anchor。它让图里的完成状态能在图外被核验。

客服 Agent 的例子也能说明这一点。如果它只优化结单时间,可能学会快速关闭对话。结单速度下降了,续约率却下降。把续约、重复打开工单和人工投诉接入验证图,系统才能看见局部指标带来的副作用。代码任务里也一样,实现节点不能自己修改测试后宣布成功。

怎么用上 Graph Engineering

Graph Engineering 适合任务多、依赖交错、需要独立验证,或者要跑很久的工作。代码审查、跨目录功能开发、批量迁移前的检查、持续研究、CI 故障分流,都很适合画图。

单文件改名、文案修正、已经明确的线性 bug 修复,直接执行更快。认证、支付、数据删除、数据库迁移和生产发布,即使画成了图,也不该在第一版里交给自动运行的节点。

可以从一个重复、低风险、又确实有并行空间的任务开始。比如给一个服务做接口权限巡检:不同路由可以独立检查,检查结果统一去重,确认的发现再交给修复和回归测试。

收集路由清单
  │
  ├── 路由 A 权限检查 ─┐
  ├── 路由 B 权限检查 ─┼── 发现去重 ── 复现验证 ── 修复 ── 回归测试
  └── 路由 C 权限检查 ─┘                              ▲        │
                                                     └────────┘

先写节点契约

节点不能只写“研究支付模块”或“处理所有失败”。范围太大,不好并行,也不好验收。一个节点只做一件边界清楚的事,输入、输出、完成证据和失败去向都能说出来。

节点:复现权限发现

输入:
- 去重后的发现列表
- 目标路由和测试账户
- 当前分支的运行环境

输出:
- 可复现或已否定的发现
- 最小复现步骤
- 相关请求和响应记录

完成条件:
- 每条保留的发现都有复现证据
- 无法复现的发现明确标记为 rejected

允许修改:
- 只读检查,不改业务代码

失败处理:
- 环境不可用时记录原因,交给环境修复节点

结果要被后续代码或其他 Agent 消费时,输出最好是结构化数据。自由文本报告适合给人读,不适合当跨节点协议。比如把每条发现写成 idrouteseverityreproductionevidence 这些字段,去重和验证节点就不需要再猜报告里到底写了什么。

再画真实的边

最容易犯的错,是把每个“然后”都画成一条边。判断很简单:下一个节点是否读取上一个节点的结果?如果不读,两件事没有数据依赖,可以独立运行。

图里常见的边有几种:

  • 数据边:验证节点消费审查节点产出的发现列表。
  • 依赖边:集成测试要等服务端和客户端实现都完成。
  • 守卫边:测试绿了、PR 已创建、审批通过,后面的节点才可以开始。
  • 重试边:测试失败只回到修复节点,不重跑整张图。
  • 人工边:碰到架构分歧、高风险权限或预算上限时,流程停在等待人工决策的节点。

守卫边要检查真实证据。前一个节点结束了,不代表下一个节点就该开始。一个 Agent 说测试已通过不能放行,真实的测试退出码、日志、CI 记录才可以。

并发后的汇合也要克制。全局去重、排序、综合报告这些操作确实需要等全部分支完成,适合用 barrier。某个下游节点只依赖路由 A 的结果,就不该被路由 B 和 C 的慢任务卡住,可以把它做成 pipeline,拿到 A 的结果就继续。

把图和状态分开落盘

图描述可能的路径,状态记录这一次运行实际走到了哪里。两者混在聊天记录里,恢复时最容易出错。

{
  "task": "接口权限巡检",
  "nodes": {
    "audit-routes": { "status": "completed", "evidence": "artifacts/routes.json" },
    "review-route-a": { "status": "completed", "evidence": "artifacts/route-a-findings.json" },
    "review-route-b": { "status": "running" },
    "verify-findings": { "status": "pending", "depends_on": ["review-route-a", "review-route-b"] }
  },
  "budget": { "attempts": 3, "deadline": "2026-07-21T18:00:00Z" }
}

第一版不需要专门的图数据库或复杂调度平台。一份可读的状态文件,加上稳定的目录、日志和证据路径,已经能让系统在中断后恢复,也让人能检查它为什么做出某个决定。

节点状态的更新要由调度器或明确的状态拥有者串行处理,别让多个 Agent 同时覆盖同一份状态文件。任务开始跨仓库、跨队列或由 webhook、定时器触发时,再把这份图交给工作流运行时或调度器。工具可以替换,状态模型和证据规则应该留在仓库里。

并行写代码时隔离工作区

只读任务最容易并行。多个 Agent 分别看不同路由、不同数据源或不同文件,最后把结构化结果交给汇合节点,冲突相对少。

写代码不一样。两个节点同时改同一个配置、公共类型或核心模块,即使任务名称不同,也会在合并时相互踩踏。并行写入至少要满足三件事:每个节点有明确允许修改的目录或文件;每个节点在独立 worktree 或沙箱里运行;汇合节点负责集成测试和冲突处理。

去重、JSON 校验、排序、状态持久化和预算计数这些确定性工作,不需要 Agent。让普通脚本承担它们,模型节点留给需要理解代码、判断语义或处理模糊信息的地方。

给循环加出口,给人留决定权

图里最危险的边通常不是并发边,而是回环边。修复失败后回到修复,研究没有新发现后继续研究,自动 review 不通过后再开一轮 review,这些都可能无限运行。

每条回环至少要写清四件事:

  • 哪个事件触发重试。
  • 重试回到哪个节点,哪些已经验证过的结果可以复用。
  • 最大尝试次数、时间和成本预算。
  • 什么时候停下来交给人。

连续两次没有新增发现、同一测试失败三次、改动触及权限或数据迁移、验证器之间结论冲突,这些都可以是人工节点的进入条件。人不需要盯每一次工具调用,但应该保留目标、风险边界和例外处理的决定权。

动态重规划也该有边界。一个节点发现新的依赖或证明原假设错误,可以提交 replan 请求,更新图和状态后再继续。涉及范围、验收条件、权限或预算的变化,要经过对应负责人确认。让 Agent 在运行中悄悄换目标、改验收条件或绕过守卫边,图再完整也不可信。

从一个 Loop 长成一张 Graph

如果手里已经有一个能稳定运行的 Harness,可以按下面的顺序加图:

  1. 选一个重复、低风险的任务,把它拆成 3 到 6 个节点。
  2. 给每个节点写输入、输出、完成证据、允许修改范围和失败去向。
  3. 删掉没有真实数据关系的边,留下能并行的节点。
  4. 用一份状态文件记录节点状态、证据路径、重试次数和人工阻塞原因。
  5. 先人工调度一两轮,确认节点边界和证据是否靠谱,再自动化 fan-out、重试和恢复。
  6. 并行写入时使用独立 worktree,把集成测试放在汇合节点。
  7. 给每条回环设置退出条件,把高风险节点接到人工审批。

Graph Engineering 要做的事很具体:把已经隐含在长 prompt、子 Agent 对话和人工脑子里的关系写出来。什么可以并行,什么必须等待,什么证据能放行,失败回到哪里,谁能按下暂停键。图画出来之后,才有地方审查、测试、恢复和改进。


参考资料: