コンテンツにスキップ

Graph Engineering with Claude — Dynamic Workflows で「線」を「グラフ」にする

作成日: 2026-08-08 出典 / きっかけ: @0xCodez「Graph Engineering with Claude: 14-Step roadmap from 0 to graph architect」(2026-07-20、498万インプレッション) 一次資料: Anthropic 公式ドキュメント / 発表ブログ / Bun 移行事例 関連: loop_engineering_入門 claude_code_並行開発_branch_fork_btw_worktree_整理 cursor_agent_swarm_planner_worker経済性_整理 Fable5_3日間で300万円課金_並列エージェント運用の物理的課題 llm_agent_sandbox_隔離技術 AI支出を横ばいに保つ_デフォルト_ルーティング_キャッシング


0. 要点(3行)

  • 一言で言うと: マルチステップのエージェントを「上から順に並んだ行列」ではなく DAG(ノード=仕事、エッジ=データの流れ) として描き直す話。「A の次に B」ではなく「B は A の出力を読むか?」だけがエッジの有無を決める。読まないなら待つ必要はない。
  • 何が効くか: Claude Code の dynamic workflows(2026-05-28 GA)は、そのグラフを Claude が書いたプレーン JavaScript として実行する。制御フロー(ループ・分岐・fan-out)はコード=決定的、判断はノード=モデル。中間結果はスクリプト変数に留まるので、Claude の context には最終回答しか載らない。
  • 実用上の勘所: 元ツイートは「オーケストレーションはタダ」と強調するが、run 全体は通常セッションより大幅に高い(Bun 移行は API 換算 約 $165,000)。トポロジー(parallel() の barrier か pipeline() か)がレイテンシとコストを直接決める。既定は pipeline()

出典の性格に注意: 元ツイートは @0xCodez(SF 拠点の AI 系コンテンツ発信者、Substack: movez.substack.com)による二次資料であり、内容の実質は Anthropic 公式ドキュメントの再構成である。「14-Step roadmap」は同アカウントの定型フォーマット(Loop engineering 版も同じ型)。語彙の整理としては質が高いが、仕様の細部は公式 docs を正とする(下記 §5 に差分を列挙)。


1. 中核の発想 — 「and then」はエッジではない

元ツイートの一番の芯はここに尽きる。

A node is a unit of work — one agent, one bounded job. An edge is a dependency: this node's output feeds that node's input. The mistake is treating "and then" as an edge.

【あなたが書きがちな線形エージェント(=縮退したグラフ)】
  A ──→ B ──→ C ──→ D
  各ノードは in 1本 / out 1本。C が詰まれば D は永遠に来ない。
  そして矢印の2〜3本は「打った順」でしかなく、データが流れていない。

【問い】各矢印について: 次のノードは前のノードの出力を読むか?
        読まない ⇒ エッジではない ⇒ 待ちは純粋な無駄

【描き直した結果】
        ┌──→ B ──┐
  A ────┼──→ C ──┼──→ E   (B/C/D は独立、E だけが全部を必要とする)
        └──→ D ──┘

「要約して、それから天気を教えて」——この2つの間にエッジは無い。天気は要約を消費しない。線形スクリプトはこれを不必要に鎖に繋いでいる。

判定基準は1つだけ: そのエッジを実際にデータが渡るか。 渡らないなら切る。切ると鎖は自然に「幅」に崩れる。


2. Dynamic Workflows とは何か(公式仕様)

項目 内容 出典
実体 Claude が書く プレーン JavaScript のオーケストレーションスクリプト。ランタイムが会話とは別の隔離環境でバックグラウンド実行 公式 docs
GA 2026-05-28(research preview を経て一般提供) 発表ブログ
要件 Claude Code v2.1.154 以降。全有料プランで利用可(Pro のみ /config の Dynamic workflows 行で明示的に有効化 公式 docs
提供面 CLI / Desktop / IDE 拡張 / web / claude -p / Agent SDK / Anthropic API / Bedrock / Vertex / Microsoft Foundry 公式 docs
中間結果の置き場 スクリプト変数(Claude の context ではない)。だから context を溢れさせずに数百エージェントまでスケールする 公式 docs

位置づけの整理(公式 docs の比較表を要約)。「誰が計画を保持しているか」が違いの本質である。

Subagents Skills Agent teams Workflows
実体 Claude が spawn する worker Claude が従う指示 lead が peer を監督 ランタイムが実行するスクリプト
次に何が走るか決めるのは Claude(ターンごと) Claude lead agent スクリプト
中間結果の在り処 context window context window 共有タスクリスト スクリプト変数
再利用できるもの worker 定義 指示文 チーム定義 オーケストレーションそのもの
規模 1ターンに数個 同左 数体の長寿命 peer 1 run に数十〜数百
中断時 ターンをやり直し 同左 teammate は走り続ける 同一セッション内で resume 可

3. API 早見表(公式 docs + Workflow ツール仕様)

スクリプトの先頭は必ず export const meta = {...}純粋なリテラル。変数・関数呼び出し・スプレッド不可)。本体はトップレベル await 可のプレーン JS。

export const meta = {
  name: 'audit-routes',
  description: 'Audit every route handler for missing auth checks',
  phases: [{ title: 'Discover' }, { title: 'Audit' }],
}

const found = await agent('List every .ts file under src/routes/.', {
  schema: { type: 'object', required: ['files'],
            properties: { files: { type: 'array', items: { type: 'string' } } } },
})

const audits = await pipeline(found.files, file =>
  agent(`Audit ${file} for missing authentication checks.`, { label: file }),
)

return audits.filter(Boolean)   // 停止/APIエラーの agent は null になる
プリミティブ 挙動 勘所
agent(prompt, opts) サブエージェントを1体 spawn。schema 無しなら最終テキスト(文字列)、schema 有りなら StructuredOutput ツール呼び出しを強制し検証済みオブジェクトを返す 検証はツール呼び出し層で走るので、不一致ならモデルがリトライする。自前パース&祈りが要らない
parallel(thunks) thunk 配列を同時実行。barrier(全部待つ) throw した thunk は null に解決され、バッチ全体を落とさない。必ず .filter(Boolean)
pipeline(items, ...stages) 各 item を全ステージに独立して流す。barrier 無し item A がステージ3にいる間に item B はステージ1でよい。壁時計=最遅の1本の鎖
phase(title) / log(msg) 進捗表示のグルーピング / ナレーション行 opts.phase で明示指定すると pipeline 内の race を避けられる
workflow(name\|{scriptPath}, args) 別ワークフローをインラインで子実行 ネストは1段まで。並列上限・エージェント数・予算を親と共有
args Workflow 呼び出し時の入力がそのままグローバルに入る JSON 値で渡す(文字列化した配列を渡すと args.map が落ちる)

opts の主要オプション

オプション 用途 注意
schema 出力を JSON Schema で強制 契約を固定する主要手段
model そのノードだけモデルを差し替え 無指定はセッションモデルを継承(= 大規模 run が丸ごとセッション単価で課金される)
effort lowmax の推論努力 機械的ステージは low、検証・判定だけ上げる
isolation: 'worktree' 専用 git worktree で実行 高コスト(1体あたり 約200〜500ms + ディスク)。並列で書き込むトポロジーだけに使う
agentType カスタムサブエージェント種別 schema と併用可
label 表示ラベル上書き 進捗ビューの可読性

ランタイム制約(公式 docs の "Behavior and limits" + ツール仕様)

  • 同時実行は最大16体(CPU コアが少ないマシンではさらに減る。実装上は min(16, cores-2))。超過分はキューイングされ順次実行されるので、100件渡しても全部完走する
  • 1 run あたり合計 1,000 エージェント(暴走ループの backstop)
  • 1回の parallel()/pipeline() に渡せるのは 最大 4,096 items(超過は明示エラー。黙って切り捨てない)
  • run 中のユーザー入力は不可(ステージ間で人間の sign-off が要るなら、ステージごとに別ワークフローとして走らせる)
  • スクリプトから FS/シェルへの直接アクセス不可。読み書き・コマンド実行は agent の仕事
  • import() を含むスクリプトは起動前に失敗(モジュールロード不可)
  • TypeScript ではない(型注釈・interface・generics はパースエラー)
  • Date.now() / Math.random() / 引数なし new Date() は throw する(resume を壊すため)。時刻は args で渡し、乱数性は index でプロンプトを変える

4. トポロジーの型(ここが実務の本体)

4-1. ダイヤモンド: split → work → merge

                ┌──→ [worker] ──┐
  [split] ──────┼──→ [worker] ──┼──→ [merge] ──→ answer
                └──→ [worker] ──┘
   fan-out          並列に働く        fan-in(barrier)

正準形は fan out → reduce → synthesize。fan-out で幅を稼ぎ、reduce は素の JS コードで圧縮し(flatten / dedupe / filter に agent は不要——ここが「エッジはタダ」の実質)、最後の1体が答えを書く。

「どうすればエージェントにもっと多くのステップを踏ませられるか」ではなく「split はどこで merge はどこか」を問うようになる、という発想の転換が肝。

4-2. parallel()pipeline() か — 一番間違えるところ

【parallel(barrier あり)】       全員が最遅に足を引っ張られる
  stage1: ████ ██████████ ███
                          ↑ ここで全員待つ
  stage2:                 ████ ███ ██████

【pipeline(barrier なし)】       速い item は先に終わる
  item A: ██ ███ ██
  item B: ████ ██████ ███
  item C: ███ ██ ████

既定は pipeline() barrier が正当化されるのは、ステージ N が前ステージ全部の横断的な文脈を必要とするときだけ:

  • 全結果を突き合わせた dedupe / merge
  • 合計ゼロなら以降を丸ごとスキップする early-exit
  • プロンプトが「他の findings と比較して」と参照する場合

逆に正当化しない理由:

  • 「flatten / map / filter したいから」→ それはエッジ。pipeline のステージ内でやればいい
  • 「ステージが概念的に別だから」→ 別であることと同期することは別
  • 「コードが綺麗だから」→ barrier のレイテンシは実在する測定可能な無駄

臭い判定: parallel → transform → parallel と書いていて、真ん中の transform に item 間の依存が無いなら、その barrier は不要。

4-3. 検証をエッジに置く(グラフの本当のレバレッジ)

エージェントを増やすことではなく、その周りに巻ける構造が価値を生む。

パターン 中身 いつ効くか
Adversarial verify finding ごとに N 体の懐疑者を独立 spawn し、反証せよと指示。過半が生き残ったら通す(迷ったら refuted=true に倒す) もっともらしいが誤っている findings を殺す
Perspective-diverse verify 検証者ごとに異なるレンズを与える(correctness / security / 再現するか) 失敗モードが複数ある場合。同一検証 N 回では絶対に捕れない
Judge panel 異なる角度から N 案を生成 → 並列 judge で採点 → 勝者から合成しつつ次点の良い所を接ぐ 解空間が広い設計判断。「1案を反復」より強い
Loop-until-dry K ラウンド連続で新規ゼロになるまで finder を回す サイズ未知の探索(バグ掃討など)
Completeness critic 最後に「何が抜けているか(未実行のモダリティ・未検証の主張・未読の出典)」を問う1体 出てきたものが次ラウンドの仕事になる

loop-until-dry の唯一にして最大の落とし穴(元ツイートが正しく強調している点):

dedupe は「確定した結果」ではなく「これまで見た全部」に対して行う。 confirmed に対して dedupe すると、judge に棄却された findings が毎ラウンド蘇り、ループは永遠に dry にならない。同じ袋小路を再発見し続けるためだけに金を払う機械が完成する。

4-4. 失敗の封じ込め

  • 鎖では C が死ねば D は走らない。グラフでは失敗をノードに閉じ込める: parallel() 内の throw は null に解決される → .filter(Boolean) が封じ込め装置
  • fan-in は「全部揃っている前提」ではなく「欠けていても成立する」ように設計する
  • より厄介なのはノード同士の踏み合い(並列でファイルを書くと衝突する)。対策が isolation: 'worktree'。ただし並列で書き込むトポロジーだけの安全ベルトであり、全 run に課す税ではない(cf. llm_agent_sandbox_隔離技術claude_code_並行開発_branch_fork_btw_worktree_整理

4-5. モデルのティア分け

グラフにすると「どのノードが判断でどのノードが作業か」が可視化される。

  • 退屈なノード(抽出・分類・転記)→ 安いモデル。判断が宿るノード(統合・裁定)→ 高いモデル
  • 既定では全サブエージェントがセッションモデルを継承するので、放っておくと大規模 run が丸ごとセッション単価で請求される
  • 環境変数 CLAUDE_CODE_SUBAGENT_MODEL はスクリプトの model 指定より優先される(公式 docs 明記)
  • 組織の availableModels allowlist がスクリプトの要求モデルを塞いでいる場合は代替モデルに substitute され、/workflows の進捗ビューに要求/代替の両方が警告表示される

cf. AI支出を横ばいに保つ_デフォルト_ルーティング_キャッシング — 「デフォルトを安く、必要な所だけ上げる」は同じ構造の話。 cf. cursor_agent_swarm_planner_worker経済性_整理 — Cursor が「高性能プランナー+安価ワーカー」でコストを 1/8 にした実験。merge/plan ノードだけ上げて fan-out ノードを下げるという、まさに §4-5 の型の実測値。


5. 元ツイート vs 公式仕様 — 差分と補正

「概ね正確だが、7月20日時点の記述であり細部が古い/重要な制約が抜けている」というのが結論。

# ツイートの主張 検証結果 判定
1 「プロンプトに workflow と言えば Claude が書く」 古い。トリガーキーワードは現在 ultracodeworkflow が literal keyword だったのは v2.1.160 より前。自然文("use a workflow")は両バージョンで有効 ⚠️ 要補正
2 parallel() は barrier、throw は null 化 公式 docs / ツール仕様と一致
3 既定は pipeline()、barrier は横断依存があるときだけ 一致(臭い判定まで含めて正確)
4 schema でサブエージェントに構造化出力を強制、ツール層で検証・リトライ 一致
5 「コーディネーション自体はモデルトークンゼロ 実質正しい(スクリプト実行にモデル推論を伴わず、トークンは agent() 単位で発生)が、run 全体は通常セッションより大幅に高いと公式が明記している。この警告がツイートには無い ⚠️ 片面的
6 s を押すと .claude/workflows/ に保存 一致。保存先はプロジェクト .claude/workflows/個人 ~/.claude/workflows/ を Tab で切替。同名ならプロジェクト側が勝つ
7 /deep-research は本番出荷済みのグラフ 一致。ただし v2.1.218 以降はユーザーが起動したときのみ実行(以前は Claude が自発起動できた)。v2.1.196 以降、検証不能だった主張は「反証」ではなく「未検証」として報告される ✅(補足あり)
8 ultracode を on にすると全ての実質的タスクでワークフローを計画 一致。/effort ultracodexhigh 推論努力 + 自動オーケストレーションclaude --effort ultracode で起動時指定可(v2.1.203+)。セッション限りでリセットされる
9 Bun ランタイムの移植を adversarial review 込みで実現 一致(詳細は §6)
10 言及なし: サイズガイドライン(small<5 / medium<15 / large<50、既定 medium、v2.1.219+) 🆕 追記
11 言及なし: Large workflow 警告(25体超 または 予測150万トークン超で進捗行に表示。advisory で run は止まらない。ultracode 中は非表示) 🆕 追記
12 言及なし: resume のリプレイ規則(下記) 🆕 重要

resume の規則 — トポロジー選択の第2の根拠

公式 docs にあってツイートに無い、実務上いちばん効く仕様。

再開時のリプレイはエージェントの起動順に従う。キャッシュ結果は最初に未完了だったエージェントで打ち止めになり、それ以降に起動したエージェントは完了済みでも全部やり直しになる。

起動順: A → B → C → D    (B の実行中に停止)
再開時: A=キャッシュ / B=再実行(未完了だった)/ C=再実行 / D=再実行
                                    ↑ 完了していたのに、B より後に起動したので捨てられる

つまり 「多数の小さいエージェントに fan-out したワークフローの方が、1体の長いエージェントより進捗が残る」。ツイートはトポロジーをレイテンシの話としてしか語っていないが、実は中断耐性の話でもある。なお resume は同一セッション内のみ。Claude Code を終了すると次回セッションでは最初からになる。


6. 実証: Bun の Zig → Rust 移植

元ツイート step 09 が引く「実在の事例」。Anthropic の公式資料でも数値が揺れているので、両方を出典付きで併記する。

項目 発表ブログ 移行事例ブログ
規模 Rust 75万行 100万行(less than two weeks で生成)
期間 11日(first commit → merge) 2週間弱
テスト 既存スイート 99.8% 通過 マージ前に CI で既存スイート 100% 通過、マージ後に 19件のリグレッション(すべて修正済み)
実行者 Jarred Sumner(Bun 共同創業者・Anthropic Member of Technical Staff)
レビュー体制 典型的な失敗モード8種に対応した8体のレビュー用サブエージェント
コスト uncached input 59億トークン + output 6.9億トークン ≒ API 価格で約 $165,000
成果 バイナリ 19% 小型化(Linux/Windows)、性能 2〜5% 高速化

adversarial review の実際の形: 1体の Claude がコードを書き、別の2体には diff だけを渡し「これは壊れていると仮定せよ」と指示する。レビュー側は実装側の推論過程を見ない、出力だけを見る。これで、非同期コールバックが必要とする前に Box が drop されるプロセス生成コードの use-after-free など、マージされていたはずの実バグが捕捉された。

工程は6段階: ①ルールブック・依存マップ・ギャップ目録の作成 → ②サンプルファイルでルールをストレステスト → ③残り全部を翻訳 → ④コンパイル → ⑤スモークテスト → ⑥元実装との挙動一致検証。途中 Rust コンパイラが約16,000件のエラーを報告した局面もあったが、失敗を「実験の破綻」ではなく「キュー」として扱ったのが要点(この数字は二次資料経由なので要確認)。


7. 自分の環境への当てはめ

現状(2026-08-08 実測)

項目 含意
Claude Code v2.1.223 v2.1.154+ なので dynamic workflows は利用可。keyword は ultracode/deep-research は手動起動のみ、サイズガイドライン既定 medium がすべて適用される版
~/.claude/settings.jsoneffortLevel xhigh ultracode ではない = 自動ワークフロー計画は off。ワークフローは「明示的に頼んだときだけ」走る
~/.claude/workflows/ 存在しない 保存済みワークフローはまだゼロ。s で保存した資産が1つも無い状態
サイズガイドライン medium(15体未満) 既定のまま
disableWorkflows 未設定 有効

接続する既存の資産

  • ~/harness-loop-lab — ハーネス/ループエンジニアリングの学習ラボ。「ハーネスは足場、ループは周回、そして仕事の形はグラフ」という三層の語彙が、まさにこのノートで補完される(cf. loop_engineering_入門
  • ~/temporal-workflows / ~/research-orchestrator — 既に Temporal でオーケストレーションしている。Temporal と dynamic workflows は競合ではなくレイヤーが違う: Temporal は「マシンを跨いで永続・再開する常駐ワークフロー」、dynamic workflows は「1セッション内でサブエージェント群を捌く実行時グラフ」。前者の1アクティビティの中身として後者を呼ぶ、が自然な合成
  • ~/.claude/loops/ — launchd に焼き込んだ定期ウォッチャー。ツイートの「Ecosystem scan on a schedule」に対応するが、こちらはクラウド常駐ではなくローカル cron 層で既に実現済み
  • ~/.claude/CLAUDE.md の並列 Task 実行ルール・サブエージェントのモデル指定ルール(機械的タスクは sonnet/haiku を明示)は、§4-5 のティア分けをすでに手作業でやっていることを意味する。ワークフロー化するなら model オプションに移せばいい

すぐ試せる形(元ツイートの「Six graphs」から、自分の資産に合うもの)

  1. PR 差分の adversarial review — 既存の /code-review セルフレビュー運用(rules/common/git-workflow.md)の強化版。diff サイズでルーティングし、大きければ correctness / security / performance の異なるレンズで並列監査 → judge panel で統合
  2. サイズ未知の探索~/ai-engineering-digest / ~/st-japan-lab の巡回は現状 GitHub Actions の直列処理。loop-until-dry 型に置き換える余地がある(ただし既存の cron 層で足りているなら動かさない
  3. リポ横断監査~/.claude の rules/skills/settings の整合性チェックを1ファイル1エージェントで fan-out

注意: 現在のセッション設定では「ワークフローと /deep-research はユーザーが明示的に要求したときだけ使う」方針になっている。この方針はコスト面で妥当(§5 の #5、§6 の $165,000 を参照)。ワークフロー化は「毎回」ではなく「幅が本当に必要な仕事」に絞る。


8. まとめ — いつグラフにするか

状況 推奨アプローチ 理由
ステップが本当に前の出力を読む そのまま線形(ワークフロー不要) エッジが実在する。グラフにしても幅が出ない
同じ処理を N ファイル / N ソースに適用 pipeline() で fan-out barrier 無しで速い item から終わる
全結果を突き合わせる必要がある(dedupe / ランキング / early-exit) parallel() の barrier + reduce は素の JS barrier が正当化される唯一の場面
findings の確度を上げたい adversarial verify(反証させる)/perspective-diverse(レンズを変える) 同一検証 N 回では捕れない失敗モードがある
サイズが分からない探索 loop-until-dry(K ラウンド新規ゼロで停止) 固定回数カウンタは末尾を取りこぼす。dedupe は「見た全部」に対して
並列でファイルを書く isolation: 'worktree' それ以外では高コストな税
大規模 run のコストが気になる 狭いスライスで先に試す + 反復ノードを安いモデルへ + /model を run 前に確認 サイズガイドラインと Large workflow 警告は advisory であって上限ではない
ステージ間に人間の承認を挟みたい ステージごとに別ワークフロー run 中のユーザー入力はランタイムが受け付けない
セッションを跨いで永続・再開したい Temporal 等の常駐層(dynamic workflows ではない) resume は同一セッション内のみ

結論の一文(元ツイートの締め、これは素直に良い):

A prompter asks a question. An architect draws a graph. 線形エージェントは天井ではなく、単に最初の形だった。人が文字を打つ順序と一致しているから、誰もが最初にそこへ手を伸ばすというだけの。


参考リンク

一次資料 - Orchestrate subagents at scale with dynamic workflows — Claude Code Docs(API・制約・resume・サイズガイドライン・保存先の正) - Introducing dynamic workflows in Claude Code — Anthropic(2026-05-28 GA、提供範囲、コスト警告) - How Anthropic runs large-scale code migrations with Claude Code(Bun 移植の工程・adversarial review・トークン実績) - Create custom subagents — Claude Code Docs

元ネタ(二次資料) - @0xCodez「Graph Engineering with Claude: 14-Step roadmap」(2026-07-20) - @0xCodez「Loop engineering: 14-step roadmap from prompter to loop designer」(同じ型の前作)

第三者の解説・検証 - Claude Code Adds Dynamic Workflows for Parallel Agent Coordination — InfoQ - Claude Code Workflows: Deterministic Multi-Agent Orchestration — alexop.dev - Trying Dynamic Workflow in Claude Code — azukiazusa.dev - Rewriting Bun in Rust — Simon Willison - Anthropic launches dynamic workflows for Claude Code — TestingCatalog


作成: 2026-08-08 / 最終更新: 2026-08-08