24 ページをAIに読ませて、最後に結果をまとめる。最後のまとめ方だけ変えたいときに、全ページを読み直されるのは、もったいないです。

Claude Code の Workflow で試すと、読み取り結果を残したまま、最後の統合だけやり直せました。初回は 724,279 トークン、やり直しは 27,056 トークン。モデルの使い分けも試しましたが、手元では、この読み直しを省けるところが特によかったです。

参考にしたのは 0xMovez AI さんの「Graph Engineering with Claude: 14-Step roadmap from 0 to graph architect」(2026-07-25 公開、2026-07-30 取得)。エージェントの仕事を処理単位に分け、依存関係に沿ってつなぐ設計を紹介しています。処理単位を節点、データを渡す経路を辺として、グラフで表す考え方です。

まずは9件を、3組に分けて分類する

元記事の Step 12 では、単純な仕事には安いモデルを使い、判断が必要な仕事に高性能なモデルを使うよう勧めています。Step 14 は、うまくいった Workflow を .claude/workflows/ に保存して再実行する話でした。具体的なモデル名や検証結果は載っていなかったので、自分の環境で試しました。

最初の題材は、以前の記事で扱った MCP 仕様 2026-07-28 の major change 9 件です。サーバ運用者への影響が大きいかどうかを分類させます。

3 件ずつを別の担当に渡し、最後の担当が結果を統合する、計 4 担当の構成です。分類側は reasoning effort を low に指定しました。これはモデルが考える深さの設定です。

phase('Classify')
const classified = await parallel(GROUPS.map((g, i) => () =>
  agent(`次の MCP 仕様 2026-07-28 の変更項目それぞれについて、リモート MCP サーバを
運用する側への影響度(high/medium/low)を判定し、理由を一行で述べよ。
変更項目: ${JSON.stringify(g)}`,
    { label: `classify:${i + 1}`, effort: 'low', schema: SCHEMA })))

phase('Merge')
const all = classified.filter(Boolean).flatMap(r => r.items)
const merged = await agent(`次の分類結果(MCP 2026-07-28 の変更のサーバ運用者影響)を
統合し、high のものから順に並べ、全体を3行で総括せよ: ${JSON.stringify(all)}`,
  { label: 'merge' })
return { count: all.length, items: all, summary: merged }

スキーマ定義と入力データは省略しています。agent() が担当を起動し、parallel() が並行実行します。schema は返り値の JSON を検査するための指定です。このスクリプトを、セッション内の Workflow ツールに渡して実行しました。

変更 9 件 分類 1 3 件 出力 478 分類 2 3 件 出力 592 分類 3 3 件 出力 686 統合 出力 935 トークン
分類側の effort は low。図の出力数には入力トークンを含まない。

完了時に返った usage は次のとおりです。

agent_count: 4, duration_ms: 29314, subagent_tokens: 100564

subagent_tokens は入力を含む全担当の消費量です。9 件の分類が返り、統合結果は影響度が高いもの 5 件、中程度 3 件、低いもの 1 件でした。セッションや GET ストリームの削除が高い側に入り、内容を読んでも妥当だと思いました。

自分で再開する保存と、チームに渡す保存

Workflow を実行すると、スクリプトの控えが自動で作られました。保存先は実行結果に出ています。

~/.claude/projects/<プロジェクト名>/<セッションID>/workflows/scripts/<名前>-<実行ID>.js

これはホームディレクトリ内のセッション記録です。リポジトリの外にあるので git では共有されませんが、自分で同じ実行を再開するために使えます。ファイル名には実行ごとの ID が入っていました。

チームで共有する保存は別の操作です。対話画面で /workflows を開き、対象の Workflow を選んで s を押しました。

Dynamic workflow saved to <リポジトリ>/.claude/workflows/pattern-map-control.js.
Invoke as /pattern-map-control or Workflow({name: "pattern-map-control"}) in future sessions.

こちらはリポジトリ内なのでコミットでき、次回から /pattern-map-control という名前で起動できます。元記事が紹介していたのは、この保存方法でした。

同じ実行を再開すると、追加トークンは 0

自動保存されたスクリプトのパスと、実行 ID を resumeFromRunId に指定して再実行しました。

agent_count: 4, duration_ms: 7, subagent_tokens: 0

初回の 29,314 ミリ秒・100,564 トークンに対して、7 ミリ秒・追加トークン 0。分類と総括も同じ結果でした。全担当の結果がキャッシュから返り、モデルは新たに実行されていません。

最初の実験ではモデルは同じだった

担当ごとの出力トークンは、実行ログから確認できます。

$ jq -c 'select(.message.usage != null) |
    {model: .message.model, out: .message.usage.output_tokens}' agent-*.jsonl | tail -1

分類側が 478 / 592 / 686、統合側が 935 トークンで、モデルはすべて claude-fable-5 でした。ここまでで変えたのは effort だけなので、モデルを使い分ける実験は次に行いました。

読む担当を Haiku にしたら、トークンは減り、時間は増えた

次は手元のパターンカタログ 24 ページを使います。1 ページにつき 1 担当で、パターン名、中心となる主張、役立つ局面を抽出させました。局面は実行前・実行中・実行後の 3 種類です。最後に 1 担当が分類と総括を行うので、合計 25 担当になります。

const extracted = await parallel(SLUGS.map(s => () =>
  agent(`ファイル ${DIR}${s}.md を Read で読み、次を抽出せよ: …`,
    { label: `extract:${s}`, model: 'haiku', schema: SCHEMA })))

プロンプト後半と SCHEMA、SLUGS の定義は省略しています。抽出する 24 担当に model: 'haiku' を付けた場合と、その指定を外して既定の claude-fable-5 を使った場合を比べました。統合側はどちらも既定のモデルです。

階層化あり: agent_count: 25, duration_ms: 67604, subagent_tokens: 724279
対照:       agent_count: 25, duration_ms: 43354, subagent_tokens: 870967

各ログでモデル名も確認しました。

$ for f in wf_051b2590-*/agent-*.jsonl; do
    jq -r 'select(.message.model != null) | .message.model' "$f" | tail -1
  done | sort | uniq -c
   2 claude-fable-5
  24 claude-haiku-4-5-20251001

claude-fable-5 が 2 件あるのは、統合担当を後述の再実行でもう一度動かしたためです。比較用の実行では、25 担当すべてが claude-fable-5 でした。

抽出を Haiku にした場合 全担当が Fable の場合
総トークン数 724,279 870,967
時間 67.6 秒 43.4 秒
スキーマに従った抽出 24 件すべて成功 24 件すべて成功
パターン名の取り違え 0 件 0 件

トークン数は 2 割弱減りましたが、時間は Haiku を使ったほうがかかりました。モデルを替えれば全部よくなる、という結果ではありません。各 1 回なので並列実行の待ち時間などでも変わりますし、モデルごとの単価を使った料金比較はしていません。

抽出内容を読むと、Fable の主張文は長めで、原文の「ただし〜」といった留保まで拾っていました。役立つ局面の判定は 24 件中 4 件で違っています。たとえば「読み捨ての隔離」は Haiku が実行中、Fable が実行前。どちらとも取れる部分なので、正誤だけでは比べにくい結果です。品質の比較は私の目視で、点数を付けた評価はしていません。

困ったのは、統合担当がどちらも件数の集計でつまずいたことです。片方は途中で数え直し、もう片方は本文の件数と内訳がずれたままでした。モデルをどう使い分けるか考えていましたが、この件数は配列をコードで数えれば済む話でした。

統合だけを書き換えて再実行する

Haiku で抽出した実行の、統合担当への指示だけを変えました。総括を 5 行から「3 行と件数」にし、同じ実行 ID で再開します。

agent_count: 25, duration_ms: 18778, subagent_tokens: 27056

抽出 24 担当は前の結果を使い、統合担当だけが動きました。初回の 724,279 トークンに対し、やり直しは 27,056 トークン。読み直しを省けた分が大きいです。

今回の実験はどれも 1 回ずつで、Claude Code の Workflow だけを使っています。他の実行環境でも同じように使えるかは確認していません。

今回のようにまとめ方だけ変えるなら、読む作業までやり直す必要はありませんでした。次は件数をコードで数えてから統合担当に渡します。モデルに残したいのは、数え上げた結果をどう読むかのほうです。