この記事で学べる事
- Kiro の新機能 Workflow は、マルチエージェントのオーケストレーションを JSON の定義ファイルで宣言的に書ける仕組みです。
- 本記事では、実際に動かした FizzBuzz の2エージェント連携(実装 → レビュー)のログをもとに、4つの JSON ファイルの中身を1つずつ解説します。
- そのうえで、単なる入門では終わらせず、「そもそもエージェントを分けるべきか」を見極める3つの判断軸(責務の衝突/プロンプトの単純化と過程の記録/人による承認ゲート)を提示します。
はじめに
Kiro のアップデートで、Workflow(ワークフロー)という機能が加わりました。複数のエージェントを「どの順で」「どう連携させるか」を定義ファイルで記述し、オーケストレーター(統括役)がそれを実行する仕組みです。
マルチエージェントの入門記事は「とりあえず動かす」で終わりがちです。しかし実務で効くのは、動かし方そのものより 「いつエージェントを分けるべきで、いつ分けるべきでないか」 の判断です。
そこでこの記事は、次の2本立てで進めます。
- 実装編:実際に動かした最小デモ(FizzBuzz を作って、別エージェントがレビューする)のログを、定義ファイルと実行状態ファイルから読み解きます。
- 設計編:マルチエージェント化を検討するときの 3つの判断軸 を提示します。
この記事は、筆者が実際に Kiro の Workflow を動かした作業ログ(生成された JSON ファイル群)を元に執筆しています。設計編の「判断軸」は筆者の分析・意見であり、その旨を明記しています。
動作環境
| 種別 | バージョン |
|---|---|
| OS | Windows 11 Home(build 26200) |
| Kiro | 1.2.4 |
| シェル | PowerShell 7.6.6 |
| Python | デモの実行対象(python コマンドで実行) |
Kiro Workflow とは何か
一言でいうと
Kiro Workflow は、複数のエージェントによる作業手順を JSON の定義ファイルで表し、それを順番に実行させる仕組みです。
各ステップには「どのエージェントが」「何をするか(プロンプト)」が割り当てられます。あるステップの成果物を次のステップへ受け渡すこともできます。
ユーザーが用意するもの ── JSON の手書きは不要
ここが最初に押さえたいところです。この定義ファイルを、ユーザーが手で書く必要はありません。
今回のデモで筆者が出した指示は、次の自然文1つだけです。
コード作成とレビューの2エージェントのワークフローを書いて
この指示を受けて、Kiro 側が workflow-definition.json を生成しました。ユーザーが用意するのは「やりたいことの説明」であって、JSON そのものではありません。
後述する workflow-definition.json の中身(steps や prompt)は、すべて Kiro が自然文の指示から組み立てたものです。本記事では「生成された定義ファイルを読み解く」という立場で解説します。手書きすることもできますが、まずは自然文で任せるのが入り口になります。
ファイルはどこに置かれるか
ワークフローを実行すると、定義ファイルと実行記録は、実行したセッションの作業フォルダ配下に置かれます。
<セッションのフォルダ>/workflows/<ワークフローID>/
├── workflow-definition.json
├── workflow-state.json
├── sessions.json
└── checkpoint-cleanup.json
今回のデモの <ワークフローID> は wf_b6a5f05169609022 でした。ユーザーがこのパスを指定するわけではなく、実行時に Kiro が決めて書き出します。
従来の「会話ベースの委譲」との違い
Kiro では、これまでもチャットの中で「このファイルを調べて」「次はこれを実装して」と、1つのエージェントに逐次指示を出せました。これを本記事では 会話ベースの手動委譲 と呼びます。
Workflow が持ち込むのは、この手順を 定義ファイルに固定する という発想です。両者の違いを整理します。
| 観点 | 会話ベースの手動委譲 | Workflow(定義ファイル) |
|---|---|---|
| 手順の記述 | その場の会話で逐次指示 | 定義ファイルに事前宣言(Kiro が生成) |
| 再現性 | 低い(毎回指示が変わる) | 高い(同じ定義を再実行できる) |
| エージェント分離 | 1セッションに文脈が混ざる | ステップごとに別セッション |
| 成果物の受け渡し | 口頭で指示 |
{{artifacts.xxx}} で明示的に参照 |
| 実行の記録 | チャット履歴のみ | 状態ファイルに構造化して残る |
重要なのは、ステップごとに別セッションで動き、役割ごとにプロンプトが分かれる点です。実装は実装の指示だけ、レビューはレビューの観点だけを受け取ります。この「役割を1つに絞れる」構造が、後述する判断軸の前提になります。
実装編:FizzBuzz を2エージェントで動かす
デモの題材
今回動かしたのは、次の2ステップのワークフローです。
-
implement(担当:
wf-coder):FizzBuzz(1〜100 を出力し、3の倍数でFizz、5の倍数でBuzz、15の倍数でFizzBuzz)の Python スクリプトを作る -
review(担当:
semantic_reviewer):できたスクリプトを別のエージェントがレビューし、判定を Markdown に書き出す
wf-coder と semantic_reviewer は、ステップに割り当てたエージェントの名前です。それぞれ別の役割(実装役・レビュー役)として動きます。
あえて単純な題材にしたのは、「2エージェントが連携して動く」という仕組みそのものを観察するためです。
実行結果
まず、できあがったものを見ます。実装エージェントが生成した fizzbuzz.py はこうなりました。
def fizzbuzz(n):
if n % 15 == 0:
return "FizzBuzz"
if n % 3 == 0:
return "Fizz"
if n % 5 == 0:
return "Buzz"
return str(n)
if __name__ == "__main__":
for i in range(1, 101):
print(fizzbuzz(i))
fizzbuzz(n) は 15 の倍数を最初に判定し、Fizz / Buzz に先取りされる誤りを避けています。if __name__ == "__main__": ガードを付けたことで、import 時に 100 行の出力が走りません。
実行すると、先頭15行は期待どおりでした。
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
次に、レビュー担当のエージェントが出した review.md の冒頭です。
# コードレビュー: fizzbuzz.py
**総合判定: APPROVED**
FizzBuzz の実装は正しく、関数分割・`__main__` ガード・可読性のいずれも良好。
実装エージェントと別のレビューエージェントが、15の倍数の判定順序や __main__ ガードの有無をチェックし、APPROVED を出しました。2エージェントの連携が成立しています。
定義ファイルの読み方:4つの JSON を解説
前述の workflows/<ワークフローID>/ には4つの JSON が置かれます。いずれもユーザーが手で書くものではなく、definition は自然文の指示から Kiro が生成し、残りは実行時に Kiro が書き出します。
役割と、実行の前後でどう変わるかを一覧にします。
| ファイル | 役割 | 実行前 | 実行後 |
|---|---|---|---|
workflow-definition.json |
設計図(何をするか) |
steps / agent / prompt / artifacts が確定 |
変わらない |
workflow-state.json |
実行記録(どう動いたか) | 各ノードが未実行 |
status: "completed"、各ノードに sessionId・startedAt/endedAt・capturedOutput が埋まる |
sessions.json |
ステップ↔サブセッションの対応表 | 空 | 各ステップとサブセッションIDの対応が並ぶ |
checkpoint-cleanup.json |
実行の整合性管理 | まだ無い |
phase: "settled"・stateDigest が書かれる |
ポイントは、「何をするか(definition)」は実行しても不変で、「どう動いたか(state ほか)」だけが後から埋まるという分離です。これが、同じ定義を何度でも再実行できる土台になっています。以下、4つを順に見ます。
1. workflow-definition.json ── マルチエージェントの定義ファイル
ワークフローの「設計図」です。どのエージェントが、どの順で、何をするかが宣言されています。これは Kiro が自然文の指示から生成したもので、以下が今回のデモの定義です。
{
"name": "workflow-demo-fizzbuzz",
"description": "Demo: implement a FizzBuzz Python script, then semantically review it.",
"inputs": {},
"steps": [
{
"type": "step",
"id": "implement",
"agent": "wf-coder",
"prompt": "FizzBuzz を出力する Python スクリプトを新規作成する。...(仕様と検証手順)",
"artifacts": {
"script": "...\\fizzbuzz.py"
}
},
{
"type": "step",
"id": "review",
"agent": "semantic_reviewer",
"prompt": "ステップ1で作成された Python スクリプトをレビューする。\nレビュー対象の絶対パス: {{artifacts.script}} ...",
"artifacts": {
"review": "...\\review.md"
}
}
],
"planRevision": 0
}
要素ごとに意味を見ます。
| キー | 意味 |
|---|---|
name / description
|
ワークフローの名前と説明 |
inputs |
実行時に外から渡す値(今回は空) |
steps |
実行するステップの配列。この順に実行される |
steps[].id |
ステップの識別子(implement / review) |
steps[].agent |
担当エージェント名(wf-coder / semantic_reviewer) |
steps[].prompt |
そのエージェントへの実プロンプト(具体的な指示) |
steps[].artifacts |
そのステップが生む成果物の論理名とパス |
注目すべきは、2つめのステップのプロンプトにある {{artifacts.script}} です。
"prompt": "... レビュー対象の絶対パス: {{artifacts.script}} ..."
これは、1つめのステップが宣言した成果物 script(= fizzbuzz.py のパス)を、2つめのステップが変数として受け取る書き方です。ステップ間のデータ受け渡しが、口頭ではなく定義ファイル上で明示されています。これが「宣言的オーケストレーション」の真価だといえます。
各ステップの prompt は、そのまま担当エージェントに渡される指示文です。今回のデモの implement プロンプトには、仕様(15の倍数を先に判定)・検証手順(先頭15行が期待値と一致するか)・最終メッセージの書式まで書き込まれていました。ここが薄いとステップは期待どおりに動きません。定義ファイルで一番手をかけるべきは、この prompt です。
2. workflow-state.json ── 実行の記録
「設計図」が definition なら、こちらは 実際にどう動いたか の記録です。抜粋します。
{
"workflowId": "wf_b6a5f05169609022",
"workflowName": "workflow-demo-fizzbuzz",
"status": "completed",
"artifacts": {
"script": "...\\fizzbuzz.py",
"review": "...\\review.md"
},
"root": {
"type": "sequence",
"status": "completed",
"children": [
{
"nodeId": "implement",
"type": "step",
"status": "completed",
"agentName": "wf-coder",
"sessionId": "sess_537079c2-...",
"completionSignal": "success",
"completionSignalSource": "send_message",
"startedAt": "2026-10-10T13:47:19.183Z",
"endedAt": "2026-10-10T13:47:35.954Z"
},
{
"nodeId": "review",
"type": "step",
"status": "completed",
"agentName": "semantic_reviewer",
"sessionId": "sess_2cc32925-...",
"completionSignal": "success",
"startedAt": "2026-10-10T13:47:35.956Z",
"endedAt": "2026-10-10T13:48:08.485Z"
}
]
}
}
ここから読み取れる事をピックアップします。
-
root.typeがsequence:2ステップが「順次実行」として管理されています。 -
各ノードが別
sessionId:implementとreviewは別々のサブセッションで動いています。文脈が分離されている証拠です。 -
時刻の連続性:
implementが13:47:35.954に終わり、reviewが13:47:35.956に始まっています。前段の完了を待って後段が動く、という順序が守られています。 -
completionSignal: success/completionSignalSource: send_message:各ステップはsend_messageで完了を通知し、それが成功シグナルになっています。
状態ファイルには capturedOutputs も記録され、各ステップの最終メッセージ(実装エージェントの「先頭15行の出力」など)がまるごと残ります。後から「何が起きたか」を再構成できるのが、この状態ファイルの価値です。
3. sessions.json ── ステップとサブセッションの対応表
どのステップを、どのサブセッションが実行したかの対応表です。
{
"workflowId": "wf_b6a5f05169609022",
"sessions": [
{ "nodeId": "implement", "sessionId": "sess_537079c2-..." },
{ "nodeId": "review", "sessionId": "sess_2cc32925-..." }
]
}
短いファイルですが、ステップ = 独立したサブセッションという設計がここに表れています。各サブセッションは自分の仕事だけを知っていて、他ステップの文脈を持ちません。
4. checkpoint-cleanup.json ── チェックポイント管理
実行の中断・再開やクリーンアップのための管理ファイルです。
{
"version": 1,
"workflowId": "wf_b6a5f05169609022",
"cleanup": {
"operationId": "1f472b3e-...",
"owner": { "pid": 31456, "instanceId": "848caae1-..." },
"phase": "settled",
"stateDigest": "e45a055d8588e26d19a26b645f4bf55c4..."
}
}
phase: settled は後始末が完了した状態を示し、stateDigest は状態のハッシュです。日常的に中身を気にするファイルではありませんが、実行がトランザクション的に管理されていることがうかがえます。
設計編:マルチエージェント化の3つの判断軸
ここからは筆者の分析・意見であり、仕様ではありません。
Workflow を使えば簡単にエージェントを分けられます。だからこそ、分けるべきかを先に考えたい。筆者は次の3つの軸で判断しています。
判断軸1:責務が衝突しているか
1つのエージェントに「実装」と「レビュー」を同時にやらせると、自分の書いたコードを自分で甘く評価するという利益相反が起きがちです。
今回のデモで実装とレビューを分けたのは、この衝突を避けるためです。レビュー担当には「15の倍数の判定順序」「関数分割」「__main__ ガード」「可読性」という観点だけを渡し、実装セッションの中身は渡していません。結果として APPROVED を出しつつ、「型ヒントを付けるとよい」「docstring があるとよい」という、仕様に書いていない改善点まで指摘してきました。作る側とは別の目で見た指摘です。
判断の目安:1つのエージェントに持たせる役割が、互いに利益相反する(作る側と検証する側など)なら、分ける価値があります。
判断軸2:プロンプトをシンプルに保ち、過程を記録として残したいか
1つのエージェントに実装とレビューを両方やらせる場合、そのエージェントのプロンプトには「作る指示」と「レビューの観点」を両方書き込むことになります。プロンプトが長く複雑になるほど、エージェントの出力は毎回ブレやすくなります。ブレが良い方向に出ればよいのですが、悪い方向に倒れることもあります。実装とレビューでステップを分ければ、それぞれのプロンプトは1つの役割に絞られ、挙動を抑えやすくなります。
もう1つ大きいのが、過程の記録です。1つのエージェントで実装とレビューを同時に回すと、最初に出力されたコードに対してどんなレビューが入り、どう修正されて最終形になったのかが、エージェントの内部で完結してしまいます。人間から見ると過程がブラックボックスです。
マルチエージェント化すると、ここが分解されます。実装エージェントはコードを出力し、レビューエージェントはそのコードへのレビュー結果を Markdown ファイルとして残します。今回のデモでも、レビュー結果は review.md に書き出されました。
# コードレビュー: fizzbuzz.py
**総合判定: APPROVED**
...
### 1. FizzBuzz ロジックの正しさ(特に 15 の倍数の判定順序)
問題なし。`n % 15 == 0` を最初に判定しており...
このファイルがあれば、後から人間が「どの観点でレビューし、どこを問題と見て、どう判断したか」をたどれます。レビューの過程が、消えずに記録として残ります。
判断の目安:1エージェントに役割を詰め込んで挙動がブレるのが困る、あるいはレビューや修正の過程を後から追える記録として残したいなら、ステップを分ける価値があります。
判断軸3:人による承認ゲートを挟みたいか
一連の作業の途中に「ここで人が内容を確認し、承認してから次へ進めたい」というポイントがあるなら、そこでステップを区切る意味があります。
たとえば「実装 → 人が確認して承認 → 公開」のように、人の判断を手順の中に組み込みたい場合です。会話ベースだと承認の確認を飛ばしてしまうことが起きますが、ステップとして区切っておけば、そこで必ず立ち止まれます。
今回のデモは実装 → レビューの2ステップで、人による承認ゲートは挟んでいません。ただし、レビュー結果(APPROVED / CHANGES_REQUESTED)を人が受け取って公開可否を判断する、といった運用に自然に拡張できます。
判断の目安:公開や本番反映など、人の承認なしに先へ進めたくない工程があるなら、そこをステップの境目にする価値があります。
逆に、分けないほうがよい場合
3軸のいずれにも当てはまらないなら、分けないほうが速くて確実です。
- 役割が1つで利益相反がない
- プロンプトが単純で、過程を記録として残す必要もない
- 途中に挟みたい人による承認ゲートがない
このような単純作業は、1エージェントの会話ベースで十分です。エージェントを分けること自体にコスト(定義ファイルの設計、セッション間の受け渡し設計)がかかるため、分ける理由がないなら分けないのが筆者の基本方針です。
再現性と保守性のトレードオフ
最後に、定義ファイル化そのものの損得を整理します。これも筆者の見解です。
メリット
-
再現性:同じ
definitionを再実行すれば、同じ手順が走ります。state だけが新しく生まれます。 - 可読性:手順が JSON として残るので、「このワークフローは何をするのか」が後から読めます。
- 工程の強制:レビューや承認のステップを飛ばせません。
デメリット
- 設計のオーバーヘッド:ステップ分割、プロンプト、成果物の受け渡しを事前に設計する必要があります。
- 変更の重さ:手順を変えるには定義ファイルを編集する必要があり、会話のその場の柔軟さは失われます。
つまり、何度も繰り返す定型作業や、レビュー・承認を飛ばしたくない作業には定義ファイル化が効き、一度きりの探索的な作業には会話ベースのほうが向きます。
まとめ
- Kiro Workflow は、マルチエージェントの手順を JSON 定義ファイルで宣言し、ステップごとに別セッションで実行する仕組みです。
- 実行後は definition / state / sessions / checkpoint-cleanup の4ファイルが残り、「設計」と「実行記録」が分離されています。
- マルチエージェント化は、責務の衝突・プロンプトの単純化と過程の記録・人による承認ゲートの要否という3軸で判断するのがおすすめです。どれにも当てはまらないなら、分けないほうが速くて確実です。
「分けられるから分ける」ではなく、「分ける理由があるから分ける」。Workflow を使うときも、この順番は変わりません。
FAQ
本文で触れなかった点を補足します。根拠は公式ブログ「Introducing Kiro workflows」で確認できます。同ページは1枚ものの長文なので、該当箇所をあわせて示します(ブラウザのページ内検索で引用語を探すとたどれます)。
Q. ステップは3つ以上に増やせますか?
増やせます。公式ブログの中盤、チームの使い方を説明した段落に「典型的なワークフローは5〜10ステップで動く」という記述があります(原文 "a typical workflow runs five to ten steps" で検索)。同じく後半の feature-pipeline の例は「要件 → 設計 → 計画 → 実装 → 並列レビュー」の多段構成です。今回のデモの2ステップは最小構成にあたります。
Q. ステップにはどんなエージェントを割り当てられますか?
ステップごとに、カスタムエージェント・使用モデル・思考の深さ(effort)を指定できます。公式ブログ後半の feature-pipeline のツリー図(各 Node に Agent / Model / Thinking effort が併記されている箇所)で、設計役・実装役・レビュー役に別々のエージェントを割り当て、レビューを2モデルで並列に回す例が示されています。今回のデモで wf-coder と semantic_reviewer を分けたのも、この仕組みに沿っています。
Q. ループが承認に達しなかったらどうなりますか?
ループ(repeat)には停止条件と最大反復回数を設定できます。公式ブログ後半の feature-pipeline の説明に「設計ループ・コードループは、承認に達するまで最大3回試み、達しなければ run を停止する」とあります(原文 "up to three attempts to reach approval" で検索)。今回のデモはループ無しの2ステップなので、この挙動は使っていません。
Q. ワークフローは保存して再利用できますか?
できます。公式ブログ序盤に「Kiro が生成したワークフローはレシピとして保存し、再利用できる」とあり(原文 "save it as a recipe" で検索)、生成形式は JSON、YAML もサポートと明記されています("YAML is also supported")。末尾には「Kiro Web のクラウド設定に保存すれば、プロジェクトや端末をまたいで使い回せる」とあります。
Q. ワークフロー機能が見当たりません。どう有効化しますか?
Workflows は opt-in で、設定での有効化が必要です。公式ブログ末尾の有効化手順(原文 "opt-in" で検索)に、ワークスペース設定の Workflows を有効化し、新しいチャットを開き直す流れが示されています。設定キーは kiroAgent.workflows.enabled、この項目自体が無い場合はアカウントでまだ利用できない状態、とされています。
参考リンク
- Introducing Kiro workflows(公式ブログ)
- Workflows(公式ドキュメント)
- Author workflows(公式ドキュメント)
- Run and manage workflows(公式ドキュメント)
- Workflow examples(公式ドキュメント)
※本記事のデモ部分(FizzBuzz の2エージェント連携)は、筆者が実際に実行して生成された定義・状態ファイル(workflow-definition.json ほか)を一次情報としています。