プロジェクト 08. ワークフローをグラフとして描く
関連講義: 第14回 単一ループからグラフエンジニアリングへ
何をするか
これは「Loop」から「Graph」への躍進プロジェクトです。前回の講義ではmaker-checker loopを構築しました——実装、検証、フィードバック、再実装、すべての決定が同じエージェントのコンテキストウィンドウの中で起こっています。今回の講義でやることは、ループの中に隠れた構造を明示的に描き出すことです:ノード、エッジ、共有状態、ルーティングルールを、一言一言丹念に書き出します。
3つの発展的な実験を行います:まずP07のmaker-checker loopを一枚の明示的なグラフに描き、次にグラフに並列のfan-out/fan-inノードを追加し、最後に条件付きフォールバックエッジと人間による承認ノードを追加します。終わると、あなたは身をもって一つのことを実感します:グラフは新しい発明ではなく、あなたのループが一定の複雑さに達したとき、それが自然に変わる姿です。
使うツール
- Claude Code または Codex
- Git
- P07で構築したmaker-checker loop(または繰り返し実行できるエージェントワークフロー)
- テキストエディタまたはドローイングツール(図を描くのは見た目を良くするためではなく、構造を明快に書き出すためです;
mermaidでも手書きのgraph.mdでも構いません)
具体的なステップ
準備
- P07完了後のリポジトリから始めるか、現在実行中のエージェントワークフローをそのまま使います。
- 3つのブランチを作成します:
p08-explicit-graph、p08-parallel、p08-human-in-the-loop。 state.mdを共有状態ファイルとして用意します:要件、進捗、検証結果をすべてここに書きます。これがグラフの「公共の作業台」です。
実験1:Loopを明示的なグラフに描く
p08-explicit-graph ブランチに切り替えます。
- すべてのノードを列挙する:P07のmaker-checker loopの各ステップを1つのノードとして書き出します。各ノードに書き出すもの:その責務、その入力、その出力、それがエージェントか決定論的コードか。
- すべてのエッジを描く:ノード間の各エッジを列挙します。2つの特別なエッジに重点を置いて印を付けます:
- 条件エッジ:検証の合格/不合格、どちらへ進むか
- フォールバックエッジ:失敗がどのノードに戻るか
- 共有状態を書く:状態にどのフィールドがあるか(要件、コード、テスト結果、レビュー結論)、誰が読み誰が書くかを明確に列挙します。
- ルーティングルールを書く:最も簡単なif-thenの言葉で「次にどこへ行くか」のルールを書きます。例:
if 検証合格 → マージノード if 検証失敗 → 実装ノード if 実装ノード情報不足 → 研究ノード graph.mdに書く:上記の内容を1つのドキュメントにまとめます。mermaidで図を描き、ノード表とルーティングルールを添えます。- この問いに答える:描き終わったら、もともと暗黙的だったエッジを少なくとも1つ見つけます——以前はエージェントのコンテキストの中に隠れていて、あなた自身も存在を知らなかった決定経路です。
実験2:並列の Fan-out / Fan-in ノードを追加する
p08-parallel ブランチに切り替えます。
- 並列にできる箇所を選ぶ:タスクの中で2つの独立した部分に分割できる場所を見つけます。例:
- 実装を2つの独立したモジュールに分割し、2つのエージェントが並列で書く
- 検証を2つの独立したレビューに分割:1つはテストとlintを実行し、もう1つはコードレビューを行う(異なる指示、異なる注目点)
- 研究を2つの方向に分割し、2つのエージェントがそれぞれ1ルートずつ調べる
- fan-outルールを書く:共有状態に「このタスクがN個の並列サブタスクに分割された」ことを記録し、各サブタスクは独立したコンテキスト、独立したノードを持ちます。
- fan-inルールを書く:すべてのサブタスクが完了した後、誰が結果をマージするのか?マージの基準は何か(例:両方のレビューが通ってからマージするのか、それとも1つ通ればよいのか)?
- worktreeで隔離する:各並列サブタスクを独立したgit worktreeで実行し、物理的にファイルの衝突を避けます(前回の講義のWorktreeプリミティブを振り返ってください)。
- 一度実行して記録する:並列前後のwall-clock時間、token消費、結果の品質を記録します。並列は本当に速くなったのか?それとも調整のオーバーヘッドが節約した時間を食い潰したのか?
実験3:フォールバックエッジと人間による承認ノードを追加する
p08-human-in-the-loop ブランチに切り替えます。
これは3つの実験の中で最も重要なもの。グラフに2種類のノードを追加します:
- 条件付きフォールバックエッジ:検証ノードに「部分合格」の経路を追加します——全体を実装ノードに打ち返すのではなく、具体的なフィードバックを添えて問題を生んだそのノードに戻します。例:テストは全部通ったが、コードレビューで要件の理解に誤りがあると判明した場合、実装ノードではなく研究ノードに戻します。これには、共有状態に「問題がどのレイヤーで起きたか」を記録する必要があります。
- 人間による承認ノード(Human-in-the-loop):マージノードの前に人間ノードを追加します。ここまで来たら、グラフは停止して、あなたが
state.mdに「承認」または「打ち返し」を書くのを待ちます。承認ノードにはタイムアウトルールを持たせられます:N時間後に応答がなければ、自動的に打ち返すか自動的にエスカレーションします。 - interruptのフォーマットを書く:承認リクエストをどう明確に書くか——何が起きたか、何を変更したか、なぜ人間が必要か、承認/打ち返しの結果はそれぞれ何か。
- 完全なフローを少なくとも2ラウンド実行する:各ラウンドで人間による承認ノードまで進み、あなた自身が1回承認または打ち返しを行います。記録:あなたの承認判断は検証ノードの判断と一致したか?承認ノードが、検証ノードが止められなかった何かを止めたか?
結果の測り方
| 指標 | 実験1(明示グラフ) | 実験2(並列) | 実験3(人間と機械の協働) |
|---|---|---|---|
| 構造の可視性 | 暗黙のエッジを何本見つけられたか? | 共有状態が並列サブタスクを支えられるか? | フォールバックエッジが問題のレイヤーを正確に特定できるか? |
| 失敗の特定 | 失敗したとき、どのエッジが間違っているかを直接指し示せるか? | 並列サブタスクが失敗したとき、どれかを特定できるか? | 承認が打ち返されたとき、どのレイヤーの問題かを指せるか? |
| 協働のオーバーヘッド | 図を描くのにどれだけかかったか? | 並列で節約した時間 vs 調整のオーバーヘッド | 承認の待ち時間 vs 止められた問題の価値 |
| 観測可能性 | 各ステップで何が起きたか、今は見えるか? | 各並列サブタスクの状態は見えるか? | 承認リクエストは十分に明確に書けたか? |
| 信頼性 | グラフの記述と実際の実行は一致するか? | fan-inのマージ基準は信頼できるか? | タイムアウト/エスカレーションのルールは本当に発動するか? |
提出物
graph.md(実験1の完全なグラフ記述:mermaid図 + ノード表 + エッジ表 + 共有状態フィールド + ルーティングルール)- 実験1で発見した暗黙のエッジのリスト(少なくとも1本)
- 実験2のfan-out/fan-inルールと一回の並列実行記録(時間/コスト/品質の比較)
- 実験3のフォールバックエッジのルール、承認ノードのフォーマット、2ラウンドの人間と機械の協働記録
- 最終的な振り返り:loopからgraphへ、あなたの働き方はどう変わったか?どのタスクが図を描く価値があり、どのタスクが価値がないのか?
対応する講義
- Lecture 14 — 単一ループからグラフエンジニアリングへ
- Lecture 13 — 手動プロンプトから自律ループへ(あなたのloopはグラフの中の一つのノード;このプロジェクトはノードの内部構造を広げるもの)
- Lecture 09 — エージェントが早すぎる完了宣言をする理由(検証ノードがなぜ実装ノードから独立していなければならないのか、グラフでは構造の問題)
- Lecture 11 — 観測可能性がハーネスの一部である理由(グラフが複雑になるほど、各ノードが何をしているかを見る必要がある)