Skip to main content

机队模式

使用集群模式将工作拆分给多个子代理,并在同一个父会话中汇总结果。

何时使用机群模式

当可以在执行前分解工作,并且每个单元可以在不等待其他人的情况下运行时,机群模式非常有用。

适合的对象包括:

  • 多文件重构,其中每个工作单元负责一个文件、一个包或一种语言的 SDK。
  • 批量审查中,每位工作人员分别检查单独的差异、模块或告警组。
  • 跨独立存储库、服务或功能区域的并行研究。
  • 文档更新中,每位工作人员各自负责一个页面或主题。
  • 迁移任务,其中每个工作进程都可以验证各自负责的部分并反馈结果。

以下情况避免使用车队模式:

  • 步骤 2 需要步骤 1 的具体输出结果的按顺序执行的任务。
  • 紧耦合的编辑方式,协作者会争用同一文件。
  • 一个同步子代理或父代理可以快速完成的小任务。
  • 需要持续共享推理而不是明确所有权的任务。

当父会话能够创建清晰的工作单元、为每个单元指定一名负责人,并明确每个工作方需要返回的内容时,机群模式的效果最佳。

正在启动舰队模式

SDK 通过会话 RPC 命名空间以多种语言公开机群模式。 该绑定在生成的 RPC 接口中仍属实验性功能;如果你的应用程序依赖它,请将 SDK 和 Copilot CLI 运行时都固定到特定版本。

在会话中

接线方式为 session.fleet.start。 可选的 prompt 与运行时的设备群编排指令结合。

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");
}
Python
from copilot.generated.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")
Go
package main

import (
    "context"
    "fmt"

    copilot "github.com/github/copilot-sdk/go"
    "github.com/github/copilot-sdk/go/rpc"
)

func main() {
    ctx := context.Background()
    client := copilot.NewClient(nil)
    session, err := client.CreateSession(ctx, &copilot.SessionConfig{})
    if err != nil {
        return
    }

    prompt := "Update each package independently, then report validation results."
    result, err := session.RPC.Fleet.Start(ctx, &rpc.FleetStartRequest{
        Prompt: &prompt,
    })
    if err != nil {
        return
    }
    if result.Started {
        fmt.Println("Fleet mode started")
    }
}
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")
}
.NET
using GitHub.Copilot;

await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig());

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

if (result.Started)
{
    Console.WriteLine("Fleet mode started");
}
var result = await session.Rpc.Fleet.StartAsync(
    "Audit each project independently, then summarize the findings.");

if (result.Started)
{
    Console.WriteLine("Fleet mode started");
}
Rust
use github_copilot_sdk::generated::api_types::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");
}

机群模式的原生类型绑定已在 Node.js/TypeScript、Python、Go、.NET 和 Rust 中得到验证。 此分支上的 java/src/main/java 中找不到Java绑定,因此在该图面可用之前,将省略Java示例。

从计划模式

计划模式界面可以通过返回 autopilot_fleet 退出操作来启动集群部署。 生成的会话事件类型将其描述为:

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

当用户批准已包含独立工作项的计划时,请使用此功能。 对于单个自主工作单元,使用 autopilot;当需要用户参与其中时,使用 interactive

子代理如何协调

机群模式依赖于显式协调状态,而不是隐式共享内存。 父代理将工作分解为 todos,每个子代理拥有一个待办事项,业务流程协调程序会调度其依赖项已经完成的辅助角色。

规范架构为:

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)
);

每个待办事项都通过小型状态机移动:

pending -> in_progress -> done
                       \-> blocked

子代理应:

  1. 通过设置 status = 'in_progress'声明完全相同的待办事项。
  2. 仅处理该待办事项范围内的内容。
  3. 将其结果存储在对话或相关任务输出中。
  4. 完成后设置 status = 'done'
  5. 在无法继续时设置 status = 'blocked' ,并包括原因。

协调器可以通过如下查询找到其依赖项已满足的任务:

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'
  );

这种模式为每个工作单元明确指定了负责人,并使父会话能够判断哪些处于就绪、运行中、已完成或被阻塞状态。

生命周期挂钩

机群模式通过运行时的任务机制调用子代理。 运行时会针对子代理工具调用发出 hook 活动:运行时 1.0.52 的更新日志指出,preToolUsepostToolUsesubagentStartsubagentStop 都会针对子代理工具调用正确触发。

在此分支的公开 SDK 接口中,未找到针对 subagentStartsubagentStop 的专用 SDK 钩子回调。 SDK 用户可以通过通用会话事件流观察子代理活动,其中包括诸如 subagent.startedsubagent.completedsubagent.failedsubagent.selectedsubagent.deselected 等事件。

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}`);
    }
});
Python
import asyncio
from copilot import CopilotClient
from copilot.session import PermissionHandler

async def main():
    client = CopilotClient()
    await client.start()
    session = await client.create_session(
        on_permission_request=PermissionHandler.approve_all,
    )

    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)

asyncio.run(main())
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)

有关已在 SDK 层公开的挂钩配置,请参阅 使用挂钩。 有关子代理事件负载,请参阅 自定义代理和子代理编排

插件子代理

运行时可以通过 --plugin-dir 加载插件。 以这种方式加载的插件可以在提示词模式下将其代理注册为可用的task(agent_type=...)子代理类型,这意味着集群模式可以将任务分派给这些插件提供的工作器类型。

这目前是一种运行时层面的配置方式,而不是有文档说明的 SDK 层面的注册 API。 使用插件目录配置 Copilot CLI 运行时,然后将 SDK 客户端连接到该运行时。 将来可能会添加用于注册插件子代理类型的本机 SDK 帮助程序。

在概念层面上,这样一来,fleet 提示词便可以请求特定的工作器类型:

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

使插件提供的子代理类型保持窄和描述性,以便业务流程协调程序能够可靠地选择它们。

最佳做法

  • 在启动机群模式之前,将工作分解为独立单位。
  • 尽量减少待办事项之间的依赖关系;依赖关系会降低并行性。
  • 为每个待办事项设置持久标识符、清晰的标题和完整的描述。
  • 让每个子代理在同一时间只负责一个待办事项。
  • 使用后台子代理实现真正的并行处理。
  • 对序列化的步骤或验证入口使用同步子代理调用。
  • 为每个子代理提供完整的上下文;子代理在调用之间不保留状态。
  • 在每个工作代理提示中包含文件路径、命令、预期输出和约束。
  • 不要派发单个后台子代理;应优先使用同步调用,或并行批量调度多个工作器。
  • 除非父代理会明确解决冲突,否则应避免将相互重叠的文件分配给不同的工作代理。
  • 要求每个工作者报告其更改了哪些内容、如何验证这些更改,以及哪些事项仍然受阻。
  • 让父代理在工作代理完成后对合并后的结果进行验证。

限制和开放问题

  • 机群模式通过生成的会话 RPC 绑定公开,并在多个 SDK 中标记为实验性。
  • SQL todos 模式是运行时指南中的规范协调模型,但它是否是 SDK 使用者的稳定扩展性协定仍然是一个悬而未决的问题。
  • subagentStartsubagentStop 是运行时钩子名称;该分支通过通用会话事件流(而非专用钩子回调)向 SDK 使用者暴露子代理的生命周期。
  • 插件子代理注册是通过 --plugin-dir运行时层配置的;在此分支上未验证 SDK 级插件注册帮助程序。
  • 在此分支的 Java SDK 源代码中未找到 session.fleet.start 的 Java 原生类型绑定。
  • 机队模式不会消除父代理评审的需要。 并行工作器可能会产生不一致的假设,而这需要由协调器进行调和。

另请参阅