GitHub Copilot サブエージェントによるオーケストレーター パターンの実践

に公開

GitHub Copilot の runSubagent は、エージェントから別のエージェントを呼び出すためのツールです。以前の記事で、サブエージェントの作成方法やコンテキスト分離の効果に関する検証を行いました。

今回はそれを活かして、開発ワークフロー全体を自動化するオーケストレーターシステムを構築してみます。

この記事で作成するオーケストレーター(エージェント)は、Issue の作成から Plan、Implementation、Review を経て PR 生成まで、各フェーズをサブエージェントに委譲しながらソフトウェアの開発プロセスを実行するフローを実現します。

1. 完成イメージ

ディレクトリ構成

.github/
└── agents/
    ├── orchestrator.agent.md  # オーケストレーター
    ├── issue.agent.md         # Issue 作成/管理
    ├── plan.agent.md          # 実装計画の策定
    ├── impl.agent.md          # TDD に基づく実装
    ├── review.agent.md        # コードレビュー
    └── pr.agent.md            # PR 作成

ワークフロー

このフロー図が示すように、オーケストレーターはすべてのフェーズの「指揮者」です。各フェーズの詳細な処理はサブエージェントに委譲され、オーケストレーター自身は高レベルのワークフローを管理するだけです。

結果として、オーケストレーターの定義がシンプルになり、各エージェントは単体でも利用可能な設計になっています。

2. 設計の考え方

責任境界を明確にする

このオーケストレーターシステムの根底にあるのは「責任分離」という考え方です。実は、これはエージェント設計も組織設計も同じです。

各エージェントに明確な責任(Job Responsibilities)と評価基準(KPI)を与えることが重要です。以下はこのシステムにおける責任分離の例です。

エージェント 責任 対象外
Orchestrator ワークフロー全体の進行管理、タスク割り当て 実装、コード生成、技術的判断
Issue Agent ユーザー要望の解釈、Issue の作成/管理 実装計画、コード
Plan Agent リポジトリ分析、実装計画の策定 コード生成、実装実行
Impl Agent TDD に従ったコード実装 計画策定、レビュー
Review Agent コードレビュー、品質判定 実装、修正
PR Agent PR の作成と管理 コード生成、マージ判定

重要なのは、各エージェントが自分の責任範囲を超えて勝手に判断しないことです。

実際の運用で出てきた課題が「オーケストレーターが Issue エージェントの役割まで担おうとする」ということでした。ユーザー要望の曖昧さを自分で補おうとするのは良い意図ですが、このシステムでは Issue エージェントにその責任があります。オーケストレーターは「わかりませんでした」と Issue エージェントに返して、再度依頼するくらいの気構えで十分です。

モジュール化のメリット

各エージェント定義を外部ファイルに分離(.github/agents/ に配置)することで、次のメリットが得られます。

  1. 単体利用が可能: 人間が VS Code から直接 Issue Agent を呼び出すことができる
  2. 定義の変更が容易: 特定のエージェントの動作を改善する際、そのファイルだけを編集すればよい
  3. オーケストレーターが簡潔: 定義本体は .github/agents/ にあるため、オーケストレーターは「呼び出し指示」だけに専念できる
  4. チーム共有が容易: リポジトリに .github/agents/ があれば、チーム全員が同じエージェント群を利用できる

これはオーケストレーション・パターンとしての「モジュール化」です。

コスト効率の観点

GitHub Copilot のプレミアムリクエスト(Premium Requests)は、通常「メッセージ単位」で消費されます。

人間が手動で Issue 作成、計画、実装、レビュー、PR 作成を行うと、最低でも 5 回のリクエストを消費します。しかし、オーケストレーターを使えば、ユーザーからの指示は 1 回で済みます。

内部でサブエージェントが何度呼び出されても、ユーザー起点のリクエストとしては 1 回とカウントされるため、回数制限のあるプラン(Copilot Pro など)ではリクエスト枠の節約になります。

ただし、バックエンドでのトークン消費量は減らない(むしろ増える)ため、レスポンス待ち時間は長くなる点に注意してください。

3. Issue エージェントを作る

では実際に作ってみましょう。最初のサブエージェント「Issue Agent」を例に、詳しく解説します。

役割の定義

Issue Agent の役割は次の通りです。

  • ユーザーが入力した要望を理解する
  • 既存の GitHub Issues を確認する
  • 必要に応じて新しい Issue を作成するか、既存 Issue を更新するか判定する
  • 創造的に批判的レビューを行い、Issue の品質を高める

エージェント定義ファイルの構造

.github/agents/issue.agent.md を作成します。

---
name: issue
description: Assist the user in reporting issues or requesting features by refining requirements and specifications.
tools:
  [
    "runCommands",
    "search",
    "todos",
    "problems",
    "changes",
    "fetch",
    "ms-vscode.vscode-websearchforcopilot/websearch",
  ]
---

あなたは、ユーザーが入力する要望 (issue, bug report, feature request など) をもとに、イシューを管理するエージェントです。以下のステップに基づき、要件と仕様の解像度を高めながら、イシューを管理してください。

## 手順

下記を #tool:todos で管理する。

1. 現状/要件の把握
1. 必要に応じリモートと同期する
1. 現在のレポジトリ状況を確認する
1. 現在の GitHub Issues を確認する
1. #tool:ms-vscode.vscode-websearchforcopilot/websearch でウェブ検索を行い、情報を収集する
1. 必要に応じて Issue を作成/更新する
1. 批判レビュー
1. 作成されたイシューに対して批判的にレビューを行う
1. 必要に応じてイシューを修正する
1. ユーザーへの報告

## ツール

- #tool:ms-vscode.vscode-websearchforcopilot/websearch: ウェブ検索
- #tool:runCommands:
  - `gh`: GitHub リポジトリの操作
- #tool:search:
  - `docs/`
  - `README.md`
  - `CONTRIBUTING.md`

重要なポイント

1. ツール選択

Issue Agent が必要なツールを列挙しています。

  • runCommands: GitHub CLI (gh) で Issue を作成・更新
  • search: ドキュメントやコードの検索
  • todos: 実行ステップの進捗管理
  • fetch: ドキュメント取得
  • ms-vscode.vscode-websearchforcopilot/websearch: 外部情報の検索

不要なツール(edit など)は明示的に除外することで、エージェントの焦点を絞ります。

2. 手順の明示性

「何をするのか」を箇条書きで明確に示します。これにより、エージェントが目的を見失わなくなります。

3. ユースケースの多様性

バグレポート、機能リクエスト、改善提案など、複数のユースケースに対応できるように記述されています。

人間が直接使う場合

このエージェント定義は、オーケストレーターを経由せず人間が直接 VS Code から呼び出すこともできます。

Issue エージェント: "このライブラリの使い方がわかりません。ドキュメント化してほしいです。"

オーケストレーター経由で呼び出す場合と異なり、人間のインタラクションが可能なため、より柔軟な対応ができます。

4. オーケストレーターを作る

次に、すべてのサブエージェントを統合するオーケストレーターを作成します。

---
name: orchestrator
description: Orchestrate the implementation of features and bug fixes based on user requests by refining requirements and specifications.
argument-hint: Describe the issue you would like to report or the feature you would like to request.
tools:
  [
    "runCommands",
    "edit",
    "search",
    "todos",
    "runSubagent",
    "usages",
    "problems",
    "changes",
    "fetch",
    "ms-vscode.vscode-websearchforcopilot/websearch",
  ]
---

あなたはソフトウェア開発のオーケストレーターエージェントです。ユーザーが入力する要望をもとに機能やバグ修正を実装することを目的として、全体のフローを見ながら作業を別エージェントに指示します。あなたが直接コードを書いたりドキュメントを修正することはありません。

## 手順 (#tool:todos)

1. #tool:runSubagent で issue エージェントを呼び出し、イシューを作成する
2. #tool:runSubagent で plan エージェントを呼び出し、実装計画を立てる
3. #tool:runSubagent で impl エージェントを呼び出し、実装を行う
4. #tool:runSubagent で review エージェントを呼び出し、コードレビューと修正を行う
5. 必要に応じてステップ 3 と 4 を繰り返す
6. #tool:runSubagent で pr エージェントを呼び出し、プルリクエストを作成する
7. 実装内容とプルリクエストのリンクをユーザーに通知する

## 注意事項

- あなたがユーザー意図を理解する必要はありません。意図がわからない場合でも、イシューエージェントに依頼すれば、意図理解と説明を行ってくれます。
- **サブエージェントの定義**: エージェント定義に独自の解釈を加えてはいけません。絶対にエージェント定義ファイルに忠実なサブエージェントを作成します。例外的に、下記の点は注意事項として加えてください。
  - "これはオートメーション フローの一部であるため、ユーザーからのインタラクションを求めないでください。"
  - "/dev/null を使用するとオートメーションがストップするので、使用を避けてください"
- **サブエージェントへの入力**: 前のステップの出力を次のステップの入力とします。

オーケストレーターの重要なポイント

1. 直接コード処理をしない

edit ツールが tools リストにありますが、オーケストレーター自身は使いません。これは「サブエージェントへの指示」に限定されます。

オーケストレーターは「舞台監督」であり「役者」ではありません。

2. 責任境界を明確にする注記

- あなたがユーザー意図を理解する必要はありません。

この一文が、ハマりポイント対策です。実装当初、オーケストレーターは曖昧な要望を勝手に補完しようとしていました。この注記により、その行動を抑止できます。

3. サブエージェント定義の一貫性

- エージェント定義に独自の解釈を加えてはいけません。

オーケストレーターが各サブエージェント(Issue、Plan など)を呼び出す際、サブエージェント定義ファイルに書かれた指示を尊重する必要があります。独自解釈で変更するとシステム全体の一貫性が崩れます。

4. /dev/null 問題への対策

- "/dev/null を使用するとオートメーションがストップするので、使用を避けてください"

エージェントがシェルコマンドで /dev/null に出力をリダイレクトしようとすると、「許可されたディレクトリの外へのアクセス」として確認プロンプトが表示されます。これは不具合ではなく仕様なのですが、現時点では設定で無効化できず、完全オートメーションの妨げになっています

回避策として、エージェント定義内で「/dev/null を使わないでください」と指示しています。

5. 残りのサブエージェント

ここまでで、設計思想とオーケストレーターの作り方を理解できました。残りの 4 つのサブエージェント(Plan、Impl、Review、PR)は、同じ原則に従って定義されています。

参考までに、定義全文をアコーディオンで掲載します。

Plan Agent の定義
---
name: plan
description: Orchestrate the implementation plan for a given issue by analyzing the repository and gathering necessary information.
tools:
  [
    "runCommands",
    "search",
    "todos",
    "problems",
    "changes",
    "fetch",
    "ms-vscode.vscode-websearchforcopilot/websearch",
  ]
---

与えられたイシューの実装計画を立ててください。

## 手順

1. 現在のレポジトリ状況を確認し、リモートとの同期を行う
2. 指定されたイシューの内容を確認する。イシューが存在しない場合は、処理を中止しユーザーに通知する。
3. レポジトリ (コード、ドキュメント) を確認する
4. ウェブ検索で情報を収集する
5. 実装計画をユーザーに提示する

## ツール

- #tool:ms-vscode.vscode-websearchforcopilot/websearch: ウェブ検索
- #tool:runCommands:
  - `gh`: GitHub リポジトリの操作
- #tool:search:
  - `docs/`
  - `README.md`
  - `CONTRIBUTING.md`

## ブランチ戦略

- 新しいタスクごとにブランチを作成し、GitHub Issue 番号を含める (例: `feature/issue-123-description`)
- 定期的に `main` ブランチからリベースまたはマージして最新状態を保つ
- `main` ブランチに直接コミットすることは許可されない
Implementation Agent の定義
---
name: impl
description: Execute the implementation according to the given plan, following TDD principles.
tools:
  [
    "runCommands",
    "edit",
    "search",
    "todos",
    "problems",
    "changes",
    "fetch",
    "ms-vscode.vscode-websearchforcopilot/websearch",
  ]
---

与えられた実行計画に従って、実装を行ってください。TDD に倣って、以下のステップで実施します (#tool:todos):

1. 作業用ブランチに切り替える
2. テストコードを作成する
3. `CONTRIBUTING.md``docs/` の開発ポリシーに従って実装する
4. テストを実行し、成功を確認する
5. 成功したらリファクタリングを行う
6. リファクタリング後もテストが成功することを確認する
7. 必要に応じてドキュメント (`docs/`, `README.md`, `CONTRIBUTING.md` など) を更新する
8. 実装内容を説明する
Review Agent の定義
---
name: review
description: Execute the implementation according to the given plan, following TDD principles.
tools:
  [
    "runCommands",
    "search",
    "todos",
    "problems",
    "changes",
    "fetch",
    "ms-vscode.vscode-websearchforcopilot/websearch",
  ]
---

実装内容をレビューしてください。批判的に評価を行い、発言についての中立的なレビューを提供してください。新たな情報を検索、分析することを推奨します。あくまでレビューの提供までがあなたの役割です。

## 手順 (#tool:todos)

1. 網羅的に情報を収集する

- レポジトリの分析
- ドキュメント群の分析
- ウェブ検索 (#tool:ms-vscode.vscode-websearchforcopilot/websearch) によるベストプラクティス、pitfalls、代替案の調査

2. 収集した情報をもとに、実装内容を批判的に評価する (正確性、完全性、一貫性、正当性、妥当性、関連性、明確性、客観性、バイアスの有無、可読性、保守性などの観点)
3. 改善点や懸念点があれば指摘し、アクションプランを示す

## 活用できるリソース

- #tool:ms-vscode.vscode-websearchforcopilot/websearch: ウェブ検索
- #tool:runCommands:
  - `gh`: GitHub リポジトリの操作
- #tool:search:
  - `docs/`
  - `README.md`
  - `CONTRIBUTING.md`
PR Agent の定義
---
name: pr
description: Create a pull request for the given issue and implementation.
tools:
  [
    "runCommands",
    "search",
    "todos",
    "problems",
    "changes",
    "fetch",
    "ms-vscode.vscode-websearchforcopilot/websearch",
  ]
---

与えられたイシューと実装に対する、プルリクエストを作成してください。

## 手順 (#tool:todos)

1. PR が作成できる状態にあるのか確認する

- ドキュメント更新の忘れがないか
- 未コミットの変更がないか
- テスト (CI) が通過するか

2. 作成にふさわしくない状況だと判断される場合、修正案を示して終了します。そうでなければ PR を作成します。
3. 作成された PR の内容とリンクをユーザーに通知します。

## Notes

- 関連する Issue がある場合、その Issue 番号を含めてください (e.g., `Closes #<number>`)
- GitHub Issue に追加のコメントが必要であれば、コメントを残しておいてください。

## 活用できるリソース

- #tool:ms-vscode.vscode-websearchforcopilot/websearch: ウェブ検索
- #tool:runCommands:
  - `gh`: GitHub リポジトリの操作
- #tool:search:
  - `docs/`
  - `README.md`
  - `CONTRIBUTING.md`

6. オーケストレーターを使う

オーケストレーターは VS Code の GitHub Copilot Chat から直接呼び出せます。

  1. VS Code を開き、Copilot Chat を起動
  2. エージェントドロップダウンから「orchestrator」を選択
  3. 要望を入力

例:

"ユーザー認証機能を JWT で実装してほしい。デーベースは PostgreSQL を使っています。"

オーケストレーターが以下の処理を自動で実行します。

  1. Issue Agent が要望を Issue に変換
  2. Plan Agent が実装計画を立案
  3. Impl Agent が TDD に従って実装
  4. Review Agent がコードレビュー
  5. PR Agent が PR を作成

複雑なフローがシンプルな一度の入力で実現できます。

7. ハマりポイントと学び

実際に作って試してみた結果、いくつか気づきが得られました。

エージェント定義の一貫性を守る

オーケストレーターがサブエージェントを呼び出す際、サブエージェントの指示を「改善」しようとして独自解釈を加えてしまうことがありました。親切心からなのでしょうが、これをやるとシステム全体の一貫性が崩れます。

エージェント間の信頼関係を維持するには、定義ファイルへの忠実さが極めて重要です。オーケストレーターの定義に「エージェント定義に独自の解釈を加えてはいけません」と明記することで、この問題を抑止できました。

責任境界を教える

もうひとつ厄介だったのが、オーケストレーターが曖昧なユーザー要望に対して自分で解釈を埋めようとする行動です。ユーザーの意図を汲み取ろうとするのは良い意図なのですが、このシステムでは Issue エージェントがその責任を担っています。

「あなたがユーザー意図を理解する必要はありません」と明記することで、その行動を抑止できました。これは人間の組織教育と同じで、「あなたの責任ではない」と教えることが大事ですね。

8. 実運用に向けた考慮事項

本記事では基本的な構成を紹介しましたが、実運用ではさらにいくつかの点を考慮する必要があります。

並列実行に関する制約

現在の runSubagent は、複数のエージェントを同時に呼び出す並列実行(Parallel Execution)をサポートしていません。
例えば、「Plan Agent が計画を立てている間に、Issue Agent がドキュメントを整理する」といった動きはできず、すべて直列(Sequential)に実行されます。

プロジェクト構成への適応

本記事のエージェント定義には、いくつかの前提が埋め込まれています。

  • ドキュメントが docs/README.mdCONTRIBUTING.md にあること
  • GitHub CLI (gh) でリポジトリを操作すること
  • TDD でテストを先に書くこと

これらはあくまで筆者のプロジェクト構成に合わせた例です。皆さんのプロジェクトでは、ドキュメントが documentation/ にあったり、GitLab を使っていたり、テスト駆動ではなく実装先行だったりするかもしれません。エージェント定義は、それぞれのプロジェクトの慣習やツールチェーンに合わせて調整してください。

エラーハンドリングとリカバリー

紹介したフローは「ハッピーパス(すべてがうまくいくケース)」を基本的に前提とした簡易的なフローです。

しかし実運用では、例えば「Impl Agent がビルドエラーを解消できない」「Review Agent が承認しない」といったケースが発生します。現在のシンプルなオーケストレーターでは、エラー時にループして再試行させるロジック(必要に応じてステップ 3 と 4 を繰り返す)を入れていますが、無限ループに陥るリスクもあります。

より堅牢なシステムにするには、条件に応じて人間に判断を仰ぐような「エスケープハッチ」をプロンプトに組み込むことが重要です。

9. まとめ

このオーケストレーターシステムは、runSubagent をコンテキスト分離だけでなく「責任分離」のツールとして活用した例です。

設計のコツ:

  • 各エージェントの責任を明確に
  • ファイルモジュール化で、単体利用とオートメーション両対応
  • エージェント定義への忠実さを保つ

今後への期待:

  • 複数エージェントの並列実行(現在は runSubagent の仕様上、直列実行のみ)
  • より複雑なワークフロー(分岐、ループなど)
  • 人間のインタラクションポイントの明示的な挿入

オーケストレーターシステムは、まだ発展途上の領域です。しかし、責任分離という原則に基づく設計は、システムが複雑になっても通用するアプローチだと思います。

10. 参考リンク

Discussion