Graph Engineering with Claude:如何停止运行一条线,开始指挥一支舰队
核心结论: Graph Engineering 不是“多叫几个 Agent”,而是把任务的控制流、状态流和验证路径显式设计出来。它真正解决的问题,是删掉假依赖、扩大可并行部分,并让错误在进入最终答案前经过独立验收。
两篇 X 材料抓住了一个重要变化:Agent 工程正在从“优化一条 Loop”走向“设计一张可执行的图”。但需要先校正两个容易被口号带偏的地方:
- Loop 没有死。 Loop 是一个节点内部反复执行的机制;Graph 决定多个 Loop 如何分工、汇合、返工和停止。
- Graph 不会天然提高正确率。 它只提供结构。正确率来自节点契约、证据锚、失败隔离、独立验证和明确停止条件。
Anthropic 官方披露的 Research 系统,确实采用 Lead Agent 编排多个并行 Subagent 的 orchestrator-worker 架构,并在其内部研究评测中比单 Agent 高 90.2%;但官方同时指出,多 Agent 系统约消耗普通聊天 15 倍 Token,并不适合依赖紧密、共享上下文很重的任务。因此,“舰队”是一种高价值任务的架构选择,不是所有任务的默认答案。
一、先建立直觉:Prompt、Loop、Harness、Graph 各管什么
| 层级 | 回答的问题 | 典型产物 |
|---|---|---|
| Prompt | 这一次要模型做什么? | 指令、输入、输出格式 |
| Loop | 单个 Agent 如何持续推进? | 思考、行动、观察、重试、停止 |
| Harness | 如何约束和支撑 Agent? | 工具、权限、上下文、预算、日志、检查点 |
| Graph | 多项工作如何组织? | 节点、边、路由、并行、归并、验证、终态 |
一句话区分:Loop 管一个执行者怎么跑,Graph 管一群执行者如何协同。
当工作只有一个真实依赖链时,Graph 可能只是多余的包装;当任务包含多个可独立调查方向、多个文件、多个市场或多个验证通道时,Graph 才开始产生结构性收益。
最重要的“假边测试”
看到 A → B,不要先问“顺序是不是看起来合理”,而要问:
B 是否真正读取 A 的输出,并因其内容而改变行为?
- 如果 B 必须使用 A 生成的接口定义,边是真的。
- 如果 B 只是因为“流程图习惯”而排在 A 后面,边是假的。
- 假边会把本来可以并行的工作串行化,让最慢节点绑架总时延。
二、Graph 的基础语法
1. Node:有边界的工作单元
一个好节点至少有四项契约:
- 明确输入: 文件、问题、状态字段和可用工具;
- 单一职责: 搜索、编码、验证、汇总不要混成一个超级节点;
- 结构化输出: JSON、TypedDict、数据库记录,而不是自由散文;
- 允许失败: 超时、空结果、证据不足必须成为显式状态。
2. Edge:真实的数据或控制依赖
边不是箭头装饰,而是一个约束:目标节点必须等源节点完成。每增加一条边,都在牺牲并行度,因此需要证据证明它确实必要。
3. State:跨节点传递的最小事实集
State 不应成为“把所有上下文都塞进去”的垃圾袋。只保留:
- 任务契约与当前阶段;
- 结构化中间结果;
- 错误、预算与访问次数;
- 可恢复的检查点;
- 验收状态与停止原因。
4. Router、Join 与 Terminal State
- Router: 根据状态选择下一条边,例如通过、返工、升级或终止;
- Join / Reduce: 对并行结果去重、计数、排序并检查完整性;
- Terminal State:
complete、incomplete、escalated、aborted,而不只是“模型停止说话”。
三、四种核心拓扑
Chain:真实顺序依赖
读取规格 → 修改代码 → 运行测试 → 生成变更说明
适合每一步都必须读取上一步产物的任务。缺点是错误和时延都会沿单路径传播。
Diamond:并行展开后再归并
规划 → 多个 Worker 并行 → 确定性去重 → 多路验证 → 综合输出
这是两篇材料最值得保留的核心。它适合行业调研、代码扫描、内容生产和候选方案探索。
Router:让状态选择路径
例如:
- 高风险发现进入人工审批;
- 证据不足进入补充调查;
- 确定性测试失败直接终止;
- 低风险且验证通过进入发布。
Controlled Cycle:受控循环
循环适合“范围事先未知”的发现任务,但必须同时具备:
- 连续两轮没有新发现即停止;
- 固定费用或 Token 预算;
- 节点最大访问次数;
- 对“所有已见结果”去重,而不只是对已确认结果去重。
没有停止条件的 Cycle 不是自治,是失控。
四、一个真实场景:用 Claude 审计 20 个路由文件
任务:检查 src/routes/ 下每个路由是否缺少鉴权。
线性做法是让一个 Claude 从第一个文件读到第二十个文件。它会遇到三个问题:上下文越来越脏、单个慢文件拖累全部任务、前面形成的判断会影响后面的判断。
Graph 做法如下:
执行路径
- Orchestrator 枚举文件,最多取 20 个,给每个 Worker 一份窄任务契约;
- Fan-out 并行启动最多 6 个 Claude 进程,每个只读一个路由及其鉴权依赖;
- Reduce 用普通代码核对
expected / received / failed,任何静默丢失都让任务变成incomplete; - Verify 对候选问题启动全新上下文,重新打开文件核对证据;
- Synthesize 只输出验证通过的发现;
- Terminal 用退出码区分“无问题”“发现问题”“工作流不完整”。
下面是核心代码骨架,完整文件见 claude_route_audit.py:
with ThreadPoolExecutor(max_workers=6) as pool:
future_to_file = {pool.submit(audit_one, path): path for path in files}
for future in as_completed(future_to_file):
try:
findings.append(future.result())
except Exception as exc:
errors.append(f"{future_to_file[future]}: {exc}")
# Join 不是“拼接文本”,而是完整性验收。
if len(findings) + len(errors) != len(files) or errors:
return incomplete(errors)
candidates = [x for x in findings if x.status in {"missing", "unknown"}]
verified = [x for x in candidates if verify_in_fresh_context(x)]
return publish_only(verified)为什么先限制 20 个文件
第一次运行不是追求覆盖全仓库,而是校准单位经济性:
- 每个文件消耗多少 Token 和时间?
- 并行是否真的扩大覆盖,还是只制造重复?
- 验证器抓住了多少 Worker 的误报?
- 哪些环节可以由确定性代码代替模型?
Graph 的第一个生产指标不是“Agent 数量”,而是每个经验证任务结果的成本。
五、验证器:新上下文是起点,不是独立性的终点
原帖强调 Worker 与 Verifier 不共享上下文,这是对的。它能降低路径依赖和“顺着前一个答案找理由”的倾向。但两个 Agent 如果使用同一个模型、同一数据源、同一个错误 Schema,仍可能一起错。
因此,可靠验证应采用异质组合:
| 验证通道 | 例子 | 优点 | 局限 |
|---|---|---|---|
| 确定性规则 | Schema、类型、文件存在、数量对账 | 快、便宜、可重复 | 只能验证已编码规则 |
| 可执行测试 | 单测、集成测试、静态扫描 | 接近真实行为 | 测试规格也可能错 |
| 外部证据 | 原始文件、日志、权威数据源 | 可追溯 | 有延迟或覆盖不全 |
| 新上下文审阅 | 反例搜索、逐条核对引用 | 能发现语义问题 | 仍可能共享模型盲区 |
| 人工审批 | 高风险发布、权限与资金动作 | 持有最终责任 | 注意力有限、成本高 |
真正的证据锚,是优化者无法靠改写答案绕过的东西,例如:
- 真正运行过的测试;
- 已落账的收入;
- 用户是否持续留存;
- 执行者不可修改的权限规则;
- 能回到原文位置的引用。
六、Barrier 与 Pipeline:吞吐量不是“并行了”就结束
parallel() 常常包含一个隐形 Barrier:必须等所有 Worker
完成,才能进入下一步。总时延因此接近最慢节点,而不是平均节点。
当各项目互不依赖时,应使用 Pipeline:一个文件审计完成后立即进入自己的验证节点,不必等待其余 19 个文件。
只有在以下情形才需要 Barrier:
- 全局去重;
- 横向比较全部候选;
- 计算多数意见;
- 确认所有分片都已返回;
- 生成依赖完整集合的综合结论。
优化 Graph 的第一步不是换更快的模型,而是找到 Critical Path:哪些节点真正决定了端到端时延。
七、Graph 最常见的五种失败
原帖总结了上下文坍塌、假独立和静默失败三个高频问题。工程上还应补上循环失控与验证相关失败。
运行时最低护栏
- 每个节点设置超时、重试次数和访问上限;
- 每次 fan-out 都记录预计、成功、失败、超时数量;
- Worker 使用独立 worktree 或命名空间,避免写冲突;
- 写操作幂等,重试不会重复创建或重复扣费;
- 状态有 Schema,缺字段立即失败;
- 保存轨迹和检查点,支持从节点边界恢复;
- 高风险操作的验收权留在外部规则或具名责任人手中。
Graph 的价值不是让系统永不失败,而是让失败的位置、影响范围和恢复动作都可见。
八、什么时候不该使用 Graph
以下任务使用 Graph 往往得不偿失:
- 一个模型一次就能稳定完成的小任务;
- 每一步都真实依赖上一步的紧密顺序任务;
- 目标和验收标准都还不清楚的探索任务;
- 所有 Worker 都必须共享同一份巨大上下文;
- 任务价值不足以覆盖多 Agent 的额外成本。
可以用一个简单判断树:
- 单次 Prompt 能完成吗?能,就停。
- 需要工具、重试和状态吗?需要,先加 Harness 和 Loop。
- 存在三个以上真正独立的工作分支吗?存在,再考虑 Graph。
- 有可执行验收标准和预算上限吗?没有,暂缓自治。
九、把普通 Prompt 改写成 Graph 任务
不要只说:
检查项目里所有路由是否安全。
应写成:
枚举
src/routes/下最多 20 个路由文件。每个文件交给一个隔离上下文的审计节点,输出固定 JSON。普通代码核对返回数量并去重。每个候选问题交给全新验证节点重新打开文件核验;只有通过验证的结果可以进入报告。单节点最多重试一次,总费用超过预算或结果不完整时停止并标记incomplete。不要修改文件。
这个 Prompt 已经包含了一张隐式 Graph:范围、节点、并行、状态、验证、预算和终态都被定义了。
十、结论:从优秀 Prompter 走向系统 Architect
Graph Engineering 的成熟标志,不是能画出更复杂的箭头,而是能回答五个问题:
- 哪些边是真依赖,哪些只是流程习惯?
- 每个节点的输入、输出、失败状态是否可验证?
- 哪些工作可以并行,哪里必须设置 Barrier?
- 谁持有验收权,它和执行者是否共享失败模式?
- 系统何时完成、何时返工、何时升级给人?
因此,两篇文章最值得保留的一句话可以改写为:
Prompter 提出问题;Agent 完成动作;Architect 设计一张能让证据流动、让失败止步、让结果可恢复的图。
来源与事实边界
- rvaniaaa:Graph Engineering with Claude:提供假边测试、钻石拓扑、受控循环、Barrier/Pipeline 和失败模式等主要工程框架。
- imryven:对 Graph Engineering 的二次提炼:强化“从线到图”“验证者使用新上下文”和“证据锚”的表达。
- Anthropic:How we built our multi-agent research system:官方确认 Research 系统的 orchestrator-worker、多 Subagent 并行、性能与成本数据,也明确多 Agent 不适合依赖紧密的任务。
- Anthropic
Claude Code CLI reference:本文示例使用其中的非交互
claude -p、JSON 输出和最大轮次能力。
边界说明: “Graph Engineering”是本文对一类编排实践的工程化概括,并非 Anthropic 官方统一产品名。官方资料支持其 Research 系统采用并行多 Agent 架构,但不足以证明所有 Claude Code 内部工作流都按帖子中的图运行;原帖涉及的个别成本或大规模改写案例也未作为本文事实依据。