Workflow とは何か
これまでは「1体の Claude」、あるいは「司令塔の Claude がサブ Agent をその場の判断で呼ぶ」やり方が中心だった。Dynamic Workflow はそこから一歩進んで、JavaScript の台本(スクリプト)で多数の Agent を統率する仕組みだ。誰を・どの順で・何体・どう並べるかをコードに書き、決定論的(deterministic)に処理を進める。
Claude をめぐる仕組みは、3つのレイヤで整理するとわかりやすい。Skill は「知識(いつ・どうやるか)」、Agent は「役割(独立した文脈を持つ専門家)」、そして Workflow は「台本(誰を・どの順で・何回呼ぶか)」だ。Workflow は Agent と Skill を束ねる、一番外側の制御層にあたる。
司令塔 Claude がその都度判断する方法は柔軟だが、ループ・条件分岐・段階的な処理を正確に繰り返すのは苦手だ。Workflow はそこをコードで固定する。
なぜ「Dynamic(動的)」なのか
固定的なパイプラインと違い、実行時の結果に応じて処理の形が変わるからだ。「バグが見つからなくなるまでループ」「予算が尽きるまで深掘り」「見つかった指摘の数だけ検証 Agent を生やす」——こうした、走らせてみて初めて形が決まる制御が書ける。
なぜ使うのか — 3つの動機
Workflow を持ち出す理由は、突き詰めると次の3つに集約される。
- 網羅性(Comprehensive): タスクを分解し、多数の Agent で並列にカバーしきる。移行・監査・広域スイープなど、取りこぼしが許されない全件処理。
- 確信度(Confident): 独立した複数視点や敵対的検証を経てから結論を確定する。もっともらしいが誤った結論が生き残りにくい。
- スケール(Scale): 1つの文脈に収まらない規模を、多数の文脈に分散して処理する。
使う時の前提:Workflow は数十体の Agent を起動し大量のトークンを消費する。そのため「ユーザーが明示的に望んだ時」だけ起動するのが原則だ("workflow" と言及する/明示依頼する等)。普通のタスクは Agent を1〜数体で十分。
スクリプトの基本構造 — meta と本体
Workflow の正体は「meta 宣言+本体スクリプト」の JavaScript だ。台本はまず meta という純粋なリテラル(変数や関数呼び出しを含まない素のオブジェクト)で自己紹介し、その後に本体が続く。
// ① meta:このワークフローの自己紹介(必須・純リテラル)
export const meta = {
name: 'review-changes',
description: '差分を観点別にレビューし、各指摘を検証する',
phases: [ // 進捗表示のグループ
{ title: 'Review' },
{ title: 'Verify' },
],
}
// ② 本体:ここから async 文脈。await を直接書ける
phase('Review')
const dims = [{ key: 'bugs', prompt: '…' }, { key: 'perf', prompt: '…' }]
const results = await parallel(dims.map(d => () =>
agent(d.prompt, { label: `review:${d.key}`, schema: FINDINGS })
))
return { findings: results.filter(Boolean) }
meta.name と description は必須で、許可ダイアログや一覧に表示される自己紹介になる。meta.phases は進捗ツリーのグループ見出しで、本体の phase() 呼び出しと同じ文字列で対応づく。本体はごく普通の JavaScript に、agent() などの特別な関数(フック)を加えて組み立てる。
meta は純リテラル厳守。meta の中で変数・関数呼び出し・計算をしてはいけない。Workflow を実行せずに名前・説明・入力宣言だけを安全に読み取れるようにするためだ。なお台本は TypeScript ではなく素の JavaScript で、Date.now()やMath.random()のように毎回結果が変わる関数は再開(resume)を壊すため使わない。
4つの基本部品(プリミティブ)
Workflow を組み立てる道具はごく少数。これだけ覚えれば書ける。
agent()… Agent を1体起動する。プロンプトを渡し、結果を受け取る。pipeline()… 各アイテムを全ステージに通す。直列・バリアなしが既定。parallel()… 全部同時に走らせて、全部終わるまで待つ(バリアあり)。phase()/log()… 進行の節目を区切る/途中経過を記録する。
// agent: 1体起動。文字列を返す(schema なし)
const text = await agent('認証まわりのコードを探して要点を返して')
// schema を渡すと、検証済みの構造化オブジェクトが返る(最重要機能)
const data = await agent('バグを探して', { schema: BUGS_SCHEMA })
// → data.bugs が型保証された配列で返る。パース不要。
// phase / log: 進捗の可視化
phase('Verify') // 以降の agent をこのグループに表示
log(`${bugs.length}/10 件 発見`) // ユーザーへ進捗メッセージ
agent() の主なオプションは label(表示名)/ phase(グループ指定)/ schema(構造化出力)/ model(モデル指定)/ agentType(Explore 等の専用 Agent)/ isolation:'worktree'(隔離)など。ほかに args(外から渡したパラメータ)、budget(トークン予算)、workflow()(別の Workflow を入れ子で呼ぶ)といった便利なグローバルもある。
pipeline と parallel の違い — バリアの有無
Workflow 設計で最も間違えやすいのがここだ。違いは「バリア(barrier)の有無」、つまり「全員そろうまで待つか待たないか」に尽きる。
- pipeline(バリアなし・既定): 各アイテムが自分のペースで全段を流れる。アイテム A が stage3 にいる間、アイテム B はまだ stage1、が許される。速いアイテムは待たされない。所要時間は最も遅い1本の鎖におよそ等しい。
- parallel(バリアあり): 同段の全員がそろうまで次に進めない。最も遅い1体に全員が引きずられる。所要時間は各段の最遅の合計になりやすい。
バリアが「正しい」のは、ステージ N が「ステージ N-1 の全結果」を必要とする時だけだ。
- 全件を集めてから重複除去・マージする。
- 合計件数が0なら早期終了する(「バグ0件 → 検証フェーズを丸ごとスキップ」)。
- 「他の発見と比較して」のように相互参照が要る。
やりがちな誤り:「いったん flatten / map / filter したいから parallel」——これは理由にならない。その変換は pipeline のステージの中に入れればよい。迷ったら pipeline が合言葉だ。
// 王道パターン:レビュー →(指摘ごとに)検証 を pipeline で繋ぐ
const results = await pipeline(
DIMENSIONS,
d => agent(d.prompt, { phase: 'Review', schema: FINDINGS }),
review => parallel(review.findings.map(f => () =>
agent(`敵対的に検証せよ: ${f.title}`, { phase: 'Verify', schema: VERDICT })
.then(v => ({ ...f, verdict: v }))
))
)
// bugs 観点の指摘を検証している間に、perf 観点はまだレビュー中、が許される
品質を高めるパターン集
Workflow の真価は、単なる並列化ではなく「複数視点で検証し合う構造」をコードで再現できることにある。代表的な型を挙げる。
- 敵対的検証: 1つの発見に対し「反証せよ」と指示した懐疑役を複数立て、過半数が反証したら棄却する。もっともらしいが誤った結論を排除できる。
- 視点を分けた検証: 同じ検証役を並べるのではなく、観点を変える(正しさ・セキュリティ・再現性…)。同質な冗長より失敗モードを多く捕まえられる。
- ジャッジパネル: 異なる切り口で N 個の独立案を生成 → 並列ジャッジで採点 → 勝者を軸に良いとこ取りで統合。解の幅が広い設計タスクに強い。
- 枯れるまでループ: 件数が読めない探索で、K 回連続で新規ゼロになるまで finder を回し続ける。単純な「N件まで」より取りこぼしが減る。
- 多角スイープ: 各 Agent が違う探し方(コンテナ別・内容別・エンティティ別・時系列別)で並列探索する。1つの検索軸では見つからない物を網羅する。
- 完全性クリティック: 最後に「何が漏れているか(未実行のモダリティ・未検証の主張・未読の資料)」だけを問う専任 Agent を置く。その回答が次ラウンドの作業になる。
// 敵対的検証の骨格:3票で反証させ、過半数が「反証せず」なら生存
const votes = await parallel(Array.from({ length: 3 }, () => () =>
agent(`この主張を反証せよ: ${claim}。疑わしければ refuted=true`, { schema: VERDICT })
))
const survives = votes.filter(Boolean).filter(v => !v.refuted).length >= 2
これらは組み合わせられる。「視点分散 → ジャッジパネル」で多観点レビューを集約し、さらに「枯れるまでループ」で仕上げる、といった具合だ。規模は依頼の重さに比例させるのがコツで、「ざっとバグ探して」なら finder 数体+単票検証、「徹底監査して」なら finder を大量+3〜5票の敵対的検証+統合フェーズ、と段数を増やす。
応用機能 — schema / resume / budget ほか
基本部品に加えて、実運用を支える応用機能がある。
- schema(構造化出力・最重要):
agent()に JSON Schema を渡すと、Agent は所定の形で返し、検証はツール層で行われ不一致なら自動でリトライされる。文字列パースの不安定さから解放される。 - resume(再開・ジャーナリング): 各
agent()呼び出しは記録され、台本を編集して再実行すると、変更前までの結果はキャッシュから即座に戻り、変更箇所以降だけが再実行される。試行錯誤のコストを劇的に下げる。 - budget(予算): トークン予算をハード上限として持ち、
budget.remaining()を見て「残りが尽きるまで深掘り」のような動的制御ができる。暴走防止にもなる。 - args(引数): 外から渡す入力値。研究テーマや対象パスを名前付き Workflow に渡せる。
- concurrency(同時実行数): 同時に走る
agent()には上限があり、超過分はキュー待ちになる。100件渡しても全件は完了するが、一度に走るのは一部だけ。具体的な数値は環境やバージョンに依存する実装詳細だ。 - workflow() / isolation: 別の Workflow を入れ子で呼べる(浅く保つのが推奨)。
isolation:'worktree'で並列書き換え時の衝突を避ける。
// schema で構造化出力 + 自動リトライ
const review = await agent('この差分をレビューして', {
schema: {
type: 'object',
properties: {
issues: { type: 'array' },
verdict: { type: 'string' },
},
},
})
// review.issues / review.verdict が安全に使える
Workflow はバックグラウンドで走り、完了時に通知が届く。途中経過は /workflows でライブに確認できる。
使いどころの最終整理:Workflow は「網羅・確信・スケール」が要るときの重装備だ。コードを書く手間も実行コストも高いので、軽い仕事には使わない。明示依頼を原則とし、その価値があるかを必ず見極める。Skill(知識)・Agent(役割)・Workflow(台本)の3層を、仕事の重さに応じて使い分けてほしい。
理解度チェック
この記事の内容を確認しましょう。選ぶとすぐ採点・解説が出ます。
-
Dynamic Workflow を最もよく言い表しているのはどれか。
Workflow は「台本」に相当する制御層で、誰を・どの順で・何体呼ぶかをコードで固定し決定論的に進める。知識は Skill、役割は Agent、JSON 形式は schema の話。
-
pipeline と parallel の使い分けの「既定」はどちらで、parallel はいつ使うか。
原則は pipeline(バリアなし)。parallel は「全員そろうまで待つ」バリアを持ち、全件の重複除去や合計0件での早期終了など、全結果が要るときだけ使う。flatten 等は理由にならない。
-
スクリプト先頭の meta について正しいのはどれか。
meta は純リテラル厳守。Workflow を実行せずに名前・説明などを安全に読み取れるようにするため、変数や計算は使わない。name と description は必須。
-
schema を指定して agent() を呼ぶと得られる利点はどれか。
schema は構造化出力+自動リトライで後段の処理を安定させる最重要機能。上限での停止は budget、続きからの再開は resume、同時数の制限は concurrency の役目。
-
Workflow を使うべきでない(過剰な)ケースはどれか。
Workflow はコード記述・実行コストが高い重装備。網羅・確信・スケールが要るときに、明示依頼を原則として使う。軽い仕事には Agent を1〜数体で十分。