# フリート モード

フリートモードは、独立したサブエージェントに分割して割り当てられる作業向けの、Copilot の並列オーケストレーションパターンです。 ランタイムの研究ノートでは、フリートモードは 「task ツールを介して複数のサブエージェントを並行してディスパッチするためのランタイムに搭載されたパターンで、SQL タスクを共有の調整状態として用いるもの」と説明されています。 1 つの親セッションで複数のワーカーを調整し、その結果を収集し、結合されたコンテキストで会話を続行する必要がある場合に使用します。

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

## フリートモードを使用するタイミング

フリート モードは、実行前に作業を分解でき、各ユニットが他のユニットを待たずに実行できる場合に便利です。

適切な適合は次のとおりです。

* 複数ファイルのリファクタリング。各ワーカーがファイル、パッケージ、または言語 SDK を所有しています。
* バッチ レビューでは、各ワーカーが個別の差分、モジュール、またはアラート グループを確認します。
* 独立したリポジトリ、サービス、または機能領域にまたがる並列調査。
* ドキュメントは、各ワーカーがページまたはトピックを所有している場所を更新します。
* 各ワーカーがそれぞれの担当部分を検証し、結果を報告できる移行タスク。

次の場合は、フリート モードを使用しないでください。

* ステップ 2 でステップ 1 の具体的な出力が必要なシーケンシャル タスク。
* 複数のワーカーが同じファイルで競合する、密結合な編集。
* 1 つの同期サブエージェントまたは親エージェントが迅速に完了できる小さなタスク。
* 所有権を明確にするのではなく、継続的な共有推論を必要とするタスク。

フリート モードは、親セッションで明確な作業単位を作成し、ユニットごとに 1 人の所有者を割り当て、各ワーカーが返す必要がある内容を定義できる場合に最適です。

## フリートモードを起動しています

SDK は、セッション RPC 名前空間を介して複数の言語でフリート モードを公開します。 このバインディングは、生成された RPC サーフェスで試験的です。アプリケーションが依存している場合は、SDK と Copilot CLI ランタイムの両方をピン留めします。

### セッション内から

ワイヤ方式は `session.fleet.start`。 オプションの `prompt` は、ランタイムのフリートオーケストレーション指示と結合されます。

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
const result = await session.rpc.fleet.start({
    prompt: "Refactor each SDK package independently, then summarize the changes.",
});

if (result.started) {
    console.log("Fleet mode started");
}
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
from copilot.rpc import FleetStartRequest

result = await session.rpc.fleet.start(
    FleetStartRequest(
        prompt="Review each service independently, then summarize the risks."
    )
)

if result.started:
    print("Fleet mode started")
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
prompt := "Update each package independently, then report validation results."
result, err := session.RPC.Fleet.Start(ctx, &rpc.FleetStartRequest{
    Prompt: &prompt,
})
if err != nil {
    return err
}
if result.Started {
    fmt.Println("Fleet mode started")
}
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
var result = await session.Rpc.Fleet.StartAsync(
    "Audit each project independently, then summarize the findings.");

if (result.Started)
{
    Console.WriteLine("Fleet mode started");
}
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
use github_copilot_sdk::rpc::FleetStartRequest;

let result = session
    .rpc()
    .fleet()
    .start(FleetStartRequest {
        prompt: Some("Research each crate independently, then summarize the plan.".into()),
    })
    .await?;

if result.started {
    println!("Fleet mode started");
}
```

</div>

</div>

フリート モードのネイティブ型指定バインドは、Node.js/TypeScript、Python、Go、.NET、Rust で確認されました。 このブランチの `java/src/main/java` でJava バインドが見つからなかったため、Java例は、そのサーフェスが使用可能になるまで省略されます。

### プラン モードから

プラン モードの UI は、`autopilot_fleet`x 終了アクションを返すことで、フリートの展開を開始できます。 生成されたセッション イベントの種類では、次のように記述されます。

```typescript
type ExitPlanModeAction =
  | "exit_only"
  | "interactive"
  | "autopilot"
  /** Exit plan mode and continue with parallel autonomous workers. */
  | "autopilot_fleet";
```

これは、独立した作業項目が既に含まれているプランをユーザーが承認するときに使用します。 単一の自律ワーカーに対して `autopilot` を使用し、ユーザーがループに留まる必要があるときに `interactive` します。

## サブエージェントの調整方法

フリート モードは、暗黙的な共有メモリではなく、明示的な調整状態に依存します。 親エージェントは作業を todo に分解し、各サブエージェントは 1 つの todo を所有し、オーケストレーターは依存関係が既に完了しているワーカーをディスパッチします。

正規スキーマは次のとおりです。

```sql
CREATE TABLE todos (
    id TEXT PRIMARY KEY,
    title TEXT NOT NULL,
    description TEXT,
    status TEXT DEFAULT 'pending'
);

CREATE TABLE todo_deps (
    todo_id TEXT,
    depends_on TEXT,
    PRIMARY KEY (todo_id, depends_on)
);
```

各 todo は、小さなステート マシン内を移動します。

```text
pending -> in_progress -> done
                       \-> blocked
```

サブエージェントは次の手順を実行する必要があります。

1. `status = 'in_progress'` を設定することで、完了済みの ToDo を確実に 1 つ選択します。
2. そのToDoの範囲内でのみ作業してください。
3. その結果を会話または関連するタスクの出力に格納します。
4. 完了したら `status = 'done'` を設定します。
5. 続行できない場合 `status = 'blocked'` 設定し、理由を含めます。

オーケストレーターは、依存関係が次のようなクエリに満足している作業を見つけることができます。

```sql
SELECT t.*
FROM todos t
WHERE t.status = 'pending'
  AND NOT EXISTS (
      SELECT 1
      FROM todo_deps td
      JOIN todos dep ON td.depends_on = dep.id
      WHERE td.todo_id = t.id
        AND dep.status != 'done'
  );
```

このパターンにより、各ワーカーに明確な担当者が割り当てられ、親セッションは何が準備完了で、何が実行中で、何が完了しており、何がブロックされているかを把握できます。

## ライフサイクル フック

フリート モードでは、ランタイムのタスク メカニズムを介してサブエージェントが呼び出されます。 ランタイムは、サブエージェントのツール呼び出しに対するフックアクティビティを発行します。ランタイム 1.0.52 の変更ログには、サブエージェントのツール呼び出しに対して `preToolUse`、`postToolUse`、`subagentStart`、および `subagentStop` が正しく発火することが記されています。

`subagentStart`または`subagentStop`専用の SDK フック コールバックが、このブランチのパブリック SDK サーフェイスに見つかりませんでした。 SDK コンシューマーは、 `subagent.started`、 `subagent.completed`、 `subagent.failed`、 `subagent.selected`、 `subagent.deselected`などのイベントを含む汎用セッション イベント ストリームを介してサブエージェント アクティビティを監視できます。

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
session.on((event) => {
    if (event.type === "subagent.started") {
        console.log(`Started ${event.data.agentDisplayName}`);
    }

    if (event.type === "subagent.completed") {
        console.log(`Completed ${event.data.agentDisplayName}`);
    }
});
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
def handle_event(event):
    if event.type == "subagent.started":
        print(f"Started {event.data.agent_display_name}")
    elif event.type == "subagent.completed":
        print(f"Completed {event.data.agent_display_name}")

unsubscribe = session.on(handle_event)
```

</div>

</div>

SDK レイヤーで既に公開されているフック構成については、 [フックを使った作業](/ja/copilot/how-tos/copilot-sdk/features/hooks) を参照してください。 サブエージェントイベントペイロードについては、 [カスタム エージェントとサブエージェント オーケストレーション](/ja/copilot/how-tos/copilot-sdk/features/custom-agents) を参照してください。

## プラグイン サブエージェント

ランタイムは、 `--plugin-dir`を使用してプラグインを読み込むことができます。 この方法で読み込まれたプラグインは、プロンプト モードで利用可能な`task(agent_type=...)`サブエージェント型として、自身のエージェントを登録できます。つまり、フリート モードは、それらのプラグインが提供するワーカー型にディスパッチできます。

これは現在、文書化された SDK レベルの登録 API ではなく、ランタイム レベルの構成パターンです。 プラグイン ディレクトリを使用して Copilot CLI ランタイムを構成し、SDK クライアントをそのランタイムに接続します。 プラグインのサブエージェントの種類を登録するためのネイティブ SDK ヘルパーは、今後追加される可能性があります。

概念上、フリート プロンプトで特定のワーカータイプを指定することができます:

```text
Use task(agent_type="security-review") for each independent package.
Run the workers in parallel and summarize only high-confidence findings.
```

オーケストレーターがそれらを確実に選択できるように、プラグインで提供されるサブエージェントの種類を狭くわかりやすいものにしてください。

## ベスト プラクティス

* フリート モードを開始する前に、作業を独立した単位に分解します。
* todos 間の依存関係を最小限に抑えます。依存関係は並列処理を減らします。
* 各 todo に永続的な ID、明確なタイトル、完全な説明を付けます。
* 各サブエージェントが一度に 1 つの todo を所有するようにします。
* バックグラウンド サブエージェントを使用して、真の並列作業を行います。
* シリアル化されたステップまたは検証ゲートには、同期サブエージェント呼び出しを使用します。
* 各サブエージェントに完全なコンテキストを提供します。サブエージェントは、呼び出し全体でステートレスです。
* 各ワーカー プロンプトに、ファイル パス、コマンド、予期される出力、制約を含めます。
* 1 つのバックグラウンド サブエージェントをディスパッチしないでください。は、同期呼び出しを優先するか、複数のワーカーを並列でバッチ処理します。
* 親エージェントが競合を明示的に調整しない限り、重複するファイルを別のワーカーに割り当てないでください。
* すべてのワーカーに、変更内容、変更の検証方法、およびブロックされたままの内容を報告する必要があります。
* 作業者が処理を完了した後、親エージェントに統合結果を確認させます。

## 制限事項と未解決の質問

* フリート モードは、生成されたセッション RPC バインドを通じて公開され、いくつかの SDK で試験段階としてマークされます。
* SQL todos パターンはランタイム ガイダンスの正規の調整モデルですが、SDK コンシューマーにとって安定した拡張性コントラクトであるかどうかは、依然として未解決の問題です。
* `subagentStart`
  `subagentStop`はランタイム フック名です。このブランチは、専用のフック コールバックではなく、汎用セッション イベント ストリームを介して SDK コンシューマーにサブエージェント のライフサイクルを公開します。
* プラグイン サブエージェントの登録は、 `--plugin-dir`を介してランタイム レイヤーで構成されます。このブランチで SDK レベルのプラグイン登録ヘルパーは検証されませんでした。
* このブランチの Java SDK ソース内では、`session.fleet.start` 用の Java ネイティブの型付きバインディングは見つかりませんでした。
* フリートモードでも、親エージェントによるレビューの必要性はなくなりません。 並列ワーカーは、オーケストレーターが調整する必要がある一貫性のない前提を生成できます。

## 参照

* [カスタム エージェントとサブエージェント オーケストレーション](/ja/copilot/how-tos/copilot-sdk/features/custom-agents)
* [フックを使った作業](/ja/copilot/how-tos/copilot-sdk/features/hooks)