这篇写什么

Graph Engineering 的完整落地通常是:Python + LangGraph 当指挥官,Claude Code 当执行者,pytest 一类命令当 quality gate。有时不想额外起一个 Python 主控进程,只想在 Claude Code 里把一段有依赖关系的多阶段任务当图来管。

本文只写这条路径:控制流、节点隔离、跨节点状态都尽量落在 Claude Code 自带能力或手工骨架上,不接 LangGraph。图工程「为什么需要」以及三层分工的完整论述见母文;这里默认读者已经接受「用有向图拆专职节点、把控制流从 Prompt 里抽出来」这一目标。

能落地到两种深度,选哪种取决于要不要付节点隔离和显式状态的成本。

轻量方案:任务队列当 DAG

DAG(Directed Acyclic Graph,有向无环图)说的是:节点之间有方向(A 依赖完成后才能做 B),但不能成环(不能出现 A → B → A,否则永远等不到起点)。任务列表里的「阻塞 / 被阻塞」关系正好就是这种结构——依赖边把阶段串成可调度的顺序,而不是随便挑一个未完成任务开干。

Claude Code 自带的任务系统(创建 / 更新 / 列出任务)可以把每个阶段建成一个节点,用「阻塞 / 被阻塞」关系显式建边,状态走 pending → in_progress → completed;某个节点的依赖没完成前,它不会出现在「可执行」列表里,相当于用依赖门控替代了「下一步该做什么」的临时判断。

执行仍然发生在同一个会话、同一段上下文里:Agent 顺着依赖关系挑下一个已解锁的节点,直接实现,完成后回写状态,再挑下一个。没有节点隔离,也没有单独的图执行器在跑——图的推进是模型手动读状态、手动调用更新接口完成的,不是由代码在每一步自动求值条件边。跨节点的「状态」也不是一个结构化的 state 对象,只是任务列表里的标题 / 描述 / 状态字段,加上还留在同一段对话历史里的实现细节。

适合依赖关系不复杂、能在一次会话内跑完、不需要严格隔离上下文的多阶段任务——比如按一份规格文档的实现顺序逐节点推进。

示意如下:

  Claude Code 单会话
  +------------------------------------------+
  |  Task list (DAG)                         |
  |  A ──► B ──► C                           |
  |  pending / in_progress / completed       |
  +------------------------------------------+
           |
           | 同一对话上下文里依次执行
           v
      实现 → 回写任务状态 → 挑下一个已解锁节点

重量方案:子代理 + 独立工作树 + 显式状态文件

如果需要的是真正的节点隔离,通常要在 Claude Code 里手工搭三件东西:

  • 节点执行:每个节点起一个独立的子代理,用隔离的 git worktree / branch 承接改动,产出通过 diff 或 PR 交回,而不是共享一段越写越长的对话
  • 跨节点状态:一份显式的状态文件(如 JSON),记录每个节点的状态、依赖、产出路径与关键决策;节点重新启动时从这份文件重建输入,而不是依赖聊天记录里的上文
  • 图的推进:由主会话(或另一个专职的编排 Agent)读状态文件,判断哪些节点已解锁,拉起对应子代理,合并产出后回写状态——这一步基本是手工实现 LangGraph 里「边」的职责

代价是搭建和维护这套骨架本身的成本:状态 schema 要自己设计,合并逻辑、失败重试路由都要自己写,没有现成的可视化和 checkpoint / resume。

示意如下:

  主会话 / 编排 Agent
           |
           | 读/写 state.json
           v
  +------------------+
  |  state.json      |   节点状态、依赖、产出路径
  +------------------+
           |
     +-----+-----+
     v           v
  子代理 A     子代理 B
  (worktree)   (worktree)
     |           |
     +-----┬-----+
           v
      diff / PR 交回 → 合并 → 回写状态

什么情况下才需要重量方案

轻量方案够用的边界,大致在「单会话内跑得完、依赖简单、不用跨会话恢复」。往重量方案切换,通常是撞上下面几种需求之一:

  • 需要跨会话恢复:任务跨越多次对话,随时可能中断,重新打开会话时要能直接从状态文件继续,而不是重新读代码、重新推断做到哪了
  • 需要真正的上下文隔离:某个节点的实现细节(比如后端调试的大段报错)不该污染另一个节点的上下文,必须物理隔离而不是「尽量不提」
  • 需要并行执行:多个已解锁的节点要真的同时跑,而不是排队等一个会话依次处理
  • 需要独立评审:每个节点的改动要单独出 diff / PR,由人或另一个 Agent 分别 review,不是一次性的大改动
  • 图本身复杂:有条件分支、失败重试路由,需要写成可审查的确定性规则,而不是靠模型「记得住上一步失败了要怎么办」

这些条件都不成立时,轻量方案换来的「图状进度追踪 + 依赖门控」通常已经够用;额外的隔离和状态骨架换来的可靠性,在小规模任务上往往抵不过它的搭建成本。

和 LangGraph 主控路径怎么选

维度 纯 Claude Code Python + LangGraph 主控
额外进程 不需要 需要 Python 主控
控制流 任务依赖 / 手工状态机 代码里的边与条件,可静态审查
节点隔离 轻量无;重量靠子代理 + worktree 每个执行者进程天然隔离
状态 任务字段或自管 JSON 图 state + checkpoint
适用 中小规模、偏会话内编排 多角色、长流程、要可预期停机

图工程的目标不变:控制流离开 Prompt,长对话拆成专职短任务,通过与否尽量交给确定性检查。差别只在「边」写在哪里——写在 Claude Code 的任务依赖 / 状态文件里,还是写在 LangGraph 的 Python 条件里。需要后者时,回到 Graph Engineering:Python + LangGraph + Claude Code。