何时使用机群模式
当可以在执行前分解工作,并且每个单元可以在不等待其他人的情况下运行时,机群模式非常有用。
适合的对象包括:
- 多文件重构,其中每个工作单元负责一个文件、一个包或一种语言的 SDK。
- 批量审查中,每位工作人员分别检查单独的差异、模块或告警组。
- 跨独立存储库、服务或功能区域的并行研究。
- 文档更新中,每位工作人员各自负责一个页面或主题。
- 迁移任务,其中每个工作进程都可以验证各自负责的部分并反馈结果。
以下情况避免使用车队模式:
- 步骤 2 需要步骤 1 的具体输出结果的按顺序执行的任务。
- 紧耦合的编辑方式,协作者会争用同一文件。
- 一个同步子代理或父代理可以快速完成的小任务。
- 需要持续共享推理而不是明确所有权的任务。
当父会话能够创建清晰的工作单元、为每个单元指定一名负责人,并明确每个工作方需要返回的内容时,机群模式的效果最佳。
正在启动舰队模式
SDK 通过会话 RPC 命名空间以多种语言公开机群模式。 该绑定在生成的 RPC 接口中仍属实验性功能;如果你的应用程序依赖它,请将 SDK 和 Copilot CLI 运行时都固定到特定版本。
在会话中
接线方式为 session.fleet.start。 可选的 prompt 与运行时的设备群编排指令结合。
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");
}
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")
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")
}
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");
}
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
子代理应:
- 通过设置
status = 'in_progress'声明完全相同的待办事项。 - 仅处理该待办事项范围内的内容。
- 将其结果存储在对话或相关任务输出中。
- 完成后设置
status = 'done'。 - 在无法继续时设置
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 的更新日志指出,preToolUse、postToolUse、subagentStart 和 subagentStop 都会针对子代理工具调用正确触发。
在此分支的公开 SDK 接口中,未找到针对 subagentStart 或 subagentStop 的专用 SDK 钩子回调。 SDK 用户可以通过通用会话事件流观察子代理活动,其中包括诸如 subagent.started、subagent.completed、subagent.failed、subagent.selected 和 subagent.deselected 等事件。
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}`);
}
});
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 使用者的稳定扩展性协定仍然是一个悬而未决的问题。
subagentStart和subagentStop是运行时钩子名称;该分支通过通用会话事件流(而非专用钩子回调)向 SDK 使用者暴露子代理的生命周期。- 插件子代理注册是通过
--plugin-dir运行时层配置的;在此分支上未验证 SDK 级插件注册帮助程序。 - 在此分支的 Java SDK 源代码中未找到
session.fleet.start的 Java 原生类型绑定。 - 机队模式不会消除父代理评审的需要。 并行工作器可能会产生不一致的假设,而这需要由协调器进行调和。