GitHub Copilot SDK转向与队列:控制消息传递策略的深度解析
GitHub Copilot SDK转向与队列:控制消息传递策略的深度解析
GitHub Copilot SDK 是一款多平台软件开发工具包,专为将 GitHub Copilot Agent 集成到各类应用和服务中而设计。其中,转向(Steering)与队列(Queueing)机制是控制消息传递策略的核心功能,能帮助开发者更灵活地与 Copilot Agent 交互,提升工作效率。
一、转向与队列:两种核心交互模式
当会话正在积极处理一个任务时,新传入的消息可以通过 MessageOptions 中的 mode 字段以两种模式传递:
| 模式 | 行为 | 适用场景 |
|---|---|---|
"immediate"(转向) |
注入当前 LLM 对话轮次 | “实际上,不要创建那个文件——使用不同的方法” |
"enqueue"(队列) |
缓冲并在当前轮次完成后顺序处理 | “完成这个之后,还要修复测试” |
下面通过一个序列图直观展示两种模式的工作流程:
二、转向(Immediate Mode):实时调整当前任务
转向功能会将消息直接注入代理的当前对话轮次。代理会实时看到消息并相应地调整其响应,非常适合在不中止当前轮次的情况下进行 course-correcting。
核心实现代码(以 Node.js / TypeScript 为例)
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-5.4",
onPermissionRequest: async () => ({ kind: "approve-once" }),
});
// 启动一个长时间运行的任务
const msgId = await session.send({
prompt: "Refactor the authentication module to use sessions",
});
// 在代理工作时,对其进行转向
await session.send({
prompt: "Actually, use JWT tokens instead of sessions",
mode: "immediate",
});
转向的内部工作原理
- 消息被添加到运行时的
ImmediatePromptProcessor队列中 - 在当前轮次中的下一个 LLM 请求之前,处理器将消息注入对话
- 代理将转向消息视为新的用户消息并调整其响应
- 如果在转向消息处理之前轮次已完成,它会自动移至下一轮次的常规队列
[!NOTE] 转向消息在当前轮次中是尽力而为的。如果代理已经提交了工具调用,转向将在该调用完成后但仍在同一轮次中生效。
三、队列(Enqueue Mode):顺序处理后续任务
队列功能会缓冲消息,以便在当前轮次完成后按顺序处理。每个排队的消息都会启动自己完整的轮次。这是默认模式——如果省略 mode,SDK 将使用 "enqueue"。
核心实现代码(以 Python 为例)
from copilot import CopilotClient, PermissionDecisionApproveOnce
async def main():
client = CopilotClient()
await client.start()
session = await client.create_session(
on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
model="gpt-5.4",
)
# 发送初始任务
await session.send("Set up the project structure")
# 在代理忙碌时排队后续任务
await session.send(
"Add unit tests for the auth module",
mode="enqueue",
)
await session.send(
"Update the README with setup instructions",
mode="enqueue",
)
# 消息在每个轮次完成后按 FIFO 顺序处理
await client.stop()
队列的内部工作原理
- 消息作为
QueuedItem添加到会话的itemQueue中 - 当前轮次完成且会话变为空闲时,
processQueuedItems()运行 - 项目按 FIFO 顺序出队——每条消息触发一个完整的代理轮次
- 如果轮次结束时有待处理的转向消息,它会移至队列前端
- 处理持续到队列为空,然后会话发出空闲事件
四、转向与队列的组合使用
您可以在单个会话中同时使用这两种模式。转向影响当前轮次,而排队的消息则等待各自的轮次:
const session = await client.createSession({
model: "gpt-5.4",
onPermissionRequest: async () => ({ kind: "approve-once" }),
});
// 启动任务
await session.send({ prompt: "Refactor the database layer" });
// 转向当前工作
await session.send({
prompt: "Make sure to keep backwards compatibility with the v1 API",
mode: "immediate",
});
// 为本轮次后排队后续操作
await session.send({
prompt: "Now add migration scripts for the schema changes",
mode: "enqueue",
});
五、如何选择转向与队列
| 场景 | 模式 | 原因 |
|---|---|---|
| 代理走错了路 | 转向 | 重定向当前轮次而不会丢失进度 |
| 您想到了代理也应该做的事情 | 队列 | 不干扰当前工作;下一步运行 |
| 代理即将犯错 | 转向 | 在错误提交前进行干预 |
| 您想链接多个任务 | 队列 | FIFO 排序确保可预测的执行 |
| 您想为当前任务添加上下文 | 转向 | 代理将其纳入当前推理 |
| 您想批量处理不相关的请求 | 队列 | 每个请求都有自己完整的轮次和清晰的上下文 |
六、构建支持转向和队列的 UI
以下是构建支持两种模式的交互式 UI 的模式:
import { CopilotClient, CopilotSession } from "@github/copilot-sdk";
interface PendingMessage {
prompt: string;
mode: "immediate" | "enqueue";
sentAt: Date;
}
class InteractiveChat {
private session: CopilotSession;
private isProcessing = false;
private pendingMessages: PendingMessage[] = [];
constructor(session: CopilotSession) {
this.session = session;
session.on((event) => {
if (event.type === "session.idle") {
this.isProcessing = false;
this.onIdle();
}
if (event.type === "assistant.message") {
this.renderMessage(event);
}
});
}
async sendMessage(prompt: string): Promise<void> {
if (!this.isProcessing) {
this.isProcessing = true;
await this.session.send({ prompt });
return;
}
// 会话正忙 — 让用户选择如何传递
// 您的 UI 会呈现此选择(例如,按钮、键盘快捷键)
}
async steer(prompt: string): Promise<void> {
this.pendingMessages.push({
prompt,
mode: "immediate",
sentAt: new Date(),
});
await this.session.send({ prompt, mode: "immediate" });
}
async enqueue(prompt: string): Promise<void> {
this.pendingMessages.push({
prompt,
mode: "enqueue",
sentAt: new Date(),
});
await this.session.send({ prompt, mode: "enqueue" });
}
private onIdle(): void {
this.pendingMessages = [];
// 更新 UI 以显示会话已准备好接受新输入
}
private renderMessage(event: unknown): void {
// 在您的 UI 中呈现助手消息
}
}
七、API 参考
MessageOptions
| 语言 | 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|---|
| Node.js | mode |
"enqueue" \| "immediate" |
"enqueue" |
消息传递模式 |
| Python | mode |
Literal["enqueue", "immediate"] |
"enqueue" |
消息传递模式 |
| Go | Mode |
string |
"enqueue" |
消息传递模式 |
| .NET | Mode |
string? |
"enqueue" |
消息传递模式 |
传递模式
| 模式 | 效果 | 活动轮次期间 | 空闲期间 |
|---|---|---|---|
"enqueue" |
排队等待下一轮次 | 在 FIFO 队列中等待 | 立即开始新轮次 |
"immediate" |
注入当前轮次 | 在下一个 LLM 调用之前注入 | 立即开始新轮次 |
[!NOTE] 当会话处于空闲状态(未处理)时,两种模式的行为相同——消息立即开始新轮次。
八、最佳实践
-
默认使用队列——对于大多数消息,使用
"enqueue"(或省略mode)。它是可预测的,不会有中断正在进行的工作的风险。 -
保留转向用于更正——当代理正在积极做错误的事情,并且您需要在它进一步发展之前重定向它时,使用
"immediate"。 -
保持转向消息简洁——代理需要快速理解课程修正。冗长、复杂的转向消息可能会混淆当前上下文。
-
不要过度转向——多个快速转向消息可能会降低轮次质量。如果您需要显著改变方向,考虑中止轮次并重新开始。
-
在 UI 中显示队列状态——显示排队消息的数量,让用户知道有什么待处理。监听空闲事件以清除显示。
-
处理转向到队列的回退——如果转向消息在轮次完成后到达,它会自动移至队列。设计您的 UI 以反映这种过渡。
九、相关参考
- Getting Started: 设置会话并发送消息
- Custom Agents: 定义具有范围工具的专用代理
- Session Hooks: 响应会话生命周期事件
- Session Persistence: 跨重启恢复会话
通过掌握 GitHub Copilot SDK 的转向与队列机制,开发者可以更有效地与 Copilot Agent 协作,提高工作效率,实现更复杂的任务流程。无论是实时调整当前任务,还是规划后续操作,这两种模式都能为您的应用提供强大的消息控制能力。
更多推荐


所有评论(0)