Overview
Quando uma sessão está processando ativamente uma vez, as mensagens de entrada podem ser entregues em um dos dois modos por meio do mode campo no MessageOptions:
| Modo | Behavior | Caso de uso |
|---|---|---|
"immediate" (direção) | Injetado na atual etapa do LLM | "Na verdade, não crie esse arquivo — use uma abordagem diferente" |
"enqueue" (enfileiramento) | Enfileirado e processado após a conclusão do turno atual | "Depois disso, corrija também os testes" |

Direção (modo imediato)
O controle envia uma mensagem que é injetada diretamente no turno atual do agente. O agente vê a mensagem em tempo real e ajusta sua resposta adequadamente, sendo útil para correção de curso sem anular o turno.
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approve-once" }),
});
// Start a long-running task
const msgId = await session.send({
prompt: "Refactor the authentication module to use sessions",
});
// While the agent is working, steer it
await session.send({
prompt: "Actually, use JWT tokens instead of sessions",
mode: "immediate",
});
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-4.1",
)
# Start a long-running task
msg_id = await session.send(
"Refactor the authentication module to use sessions",
)
# While the agent is working, steer it
await session.send(
"Actually, use JWT tokens instead of sessions",
mode="immediate",
)
await client.stop()
package main
import (
"context"
"log"
copilot "github.com/github/copilot-sdk/go"
"github.com/github/copilot-sdk/go/rpc"
)
func main() {
ctx := context.Background()
client := copilot.NewClient(nil)
if err := client.Start(ctx); err != nil {
log.Fatal(err)
}
defer client.Stop()
session, err := client.CreateSession(ctx, &copilot.SessionConfig{
Model: "gpt-4.1",
OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
return &rpc.PermissionDecisionApproveOnce{}, nil
},
})
if err != nil {
log.Fatal(err)
}
// Start a long-running task
_, err = session.Send(ctx, copilot.MessageOptions{
Prompt: "Refactor the authentication module to use sessions",
})
if err != nil {
log.Fatal(err)
}
// While the agent is working, steer it
_, err = session.Send(ctx, copilot.MessageOptions{
Prompt: "Actually, use JWT tokens instead of sessions",
Mode: "immediate",
})
if err != nil {
log.Fatal(err)
}
}
using GitHub.Copilot;
using GitHub.Copilot.Rpc;
await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
Model = "gpt-4.1",
OnPermissionRequest = (req, inv) =>
Task.FromResult(PermissionDecision.ApproveOnce()),
});
// Start a long-running task
var msgId = await session.SendAsync(new MessageOptions
{
Prompt = "Refactor the authentication module to use sessions"
});
// While the agent is working, steer it
await session.SendAsync(new MessageOptions
{
Prompt = "Actually, use JWT tokens instead of sessions",
Mode = "immediate"
});
import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;
try (var client = new CopilotClient()) {
client.start().get();
var session = client.createSession(
new SessionConfig()
.setModel("gpt-4.1")
.setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
).get();
// Start a long-running task
session.send(new MessageOptions()
.setPrompt("Refactor the authentication module to use sessions")
).get();
// While the agent is working, steer it
session.send(new MessageOptions()
.setPrompt("Actually, use JWT tokens instead of sessions")
.setMode("immediate")
).get();
}
Como a direção funciona internamente
- A mensagem é adicionada à fila do
ImmediatePromptProcessorruntime - Antes da próxima solicitação ao LLM durante o turno atual, o processador injeta a mensagem na conversa
- O agente vê a mensagem de direção como uma nova mensagem de usuário e ajusta sua resposta
- Se a curva for concluída antes que a mensagem de direção seja processada, ela será movida automaticamente para a fila regular para a próxima curva
Observação
As mensagens de direção são o melhor esforço na curva atual. Se o agente já tiver se comprometido com uma chamada da ferramenta, a orientação entrará em vigor após a conclusão dessa chamada, mas ainda dentro da mesma etapa.
Fila (modo de enfileiramento)
O enfileiramento armazena em buffer as mensagens para serem processadas sequencialmente após a conclusão do turno atual. Cada mensagem enfileirada inicia seu próprio turno completo. Esse é o modo padrão, se você omitir mode, o SDK usará "enqueue".
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approve-once" }),
});
// Send an initial task
await session.send({ prompt: "Set up the project structure" });
// Queue follow-up tasks while the agent is busy
await session.send({
prompt: "Add unit tests for the auth module",
mode: "enqueue",
});
await session.send({
prompt: "Update the README with setup instructions",
mode: "enqueue",
});
// Messages are processed in FIFO order after each turn completes
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-4.1",
)
# Send an initial task
await session.send("Set up the project structure")
# Queue follow-up tasks while the agent is busy
await session.send(
"Add unit tests for the auth module",
mode="enqueue",
)
await session.send(
"Update the README with setup instructions",
mode="enqueue",
)
# Messages are processed in FIFO order after each turn completes
await client.stop()
package main
import (
"context"
copilot "github.com/github/copilot-sdk/go"
"github.com/github/copilot-sdk/go/rpc"
)
func main() {
ctx := context.Background()
client := copilot.NewClient(nil)
client.Start(ctx)
session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
Model: "gpt-4.1",
OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
return &rpc.PermissionDecisionApproveOnce{}, nil
},
})
session.Send(ctx, copilot.MessageOptions{
Prompt: "Set up the project structure",
})
session.Send(ctx, copilot.MessageOptions{
Prompt: "Add unit tests for the auth module",
Mode: "enqueue",
})
session.Send(ctx, copilot.MessageOptions{
Prompt: "Update the README with setup instructions",
Mode: "enqueue",
})
}
// Send an initial task
session.Send(ctx, copilot.MessageOptions{
Prompt: "Set up the project structure",
})
// Queue follow-up tasks while the agent is busy
session.Send(ctx, copilot.MessageOptions{
Prompt: "Add unit tests for the auth module",
Mode: "enqueue",
})
session.Send(ctx, copilot.MessageOptions{
Prompt: "Update the README with setup instructions",
Mode: "enqueue",
})
// Messages are processed in FIFO order after each turn completes
using GitHub.Copilot;
using GitHub.Copilot.Rpc;
public static class QueueingExample
{
public static async Task Main()
{
await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
Model = "gpt-4.1",
OnPermissionRequest = (req, inv) =>
Task.FromResult(PermissionDecision.ApproveOnce()),
});
await session.SendAsync(new MessageOptions
{
Prompt = "Set up the project structure"
});
await session.SendAsync(new MessageOptions
{
Prompt = "Add unit tests for the auth module",
Mode = "enqueue"
});
await session.SendAsync(new MessageOptions
{
Prompt = "Update the README with setup instructions",
Mode = "enqueue"
});
}
}
// Send an initial task
await session.SendAsync(new MessageOptions
{
Prompt = "Set up the project structure"
});
// Queue follow-up tasks while the agent is busy
await session.SendAsync(new MessageOptions
{
Prompt = "Add unit tests for the auth module",
Mode = "enqueue"
});
await session.SendAsync(new MessageOptions
{
Prompt = "Update the README with setup instructions",
Mode = "enqueue"
});
// Messages are processed in FIFO order after each turn completes
import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;
try (var client = new CopilotClient()) {
client.start().get();
var session = client.createSession(
new SessionConfig()
.setModel("gpt-4.1")
.setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
).get();
// Send an initial task
session.send(new MessageOptions().setPrompt("Set up the project structure")).get();
// Queue follow-up tasks while the agent is busy
session.send(new MessageOptions()
.setPrompt("Add unit tests for the auth module")
.setMode("enqueue")
).get();
session.send(new MessageOptions()
.setPrompt("Update the README with setup instructions")
.setMode("enqueue")
).get();
// Messages are processed in FIFO order after each turn completes
}
Como a fila funciona internamente
- A mensagem é adicionada ao
itemQueueda sessão como umQueuedItem - Quando o turno atual terminar e a sessão ficar ociosa,
processQueuedItems()será executado - Os itens são retirados da fila na ordem FIFO—cada mensagem dispara uma interação agêntica completa
- Se uma mensagem de direção estava pendente quando a curva terminou, ela é movida para a frente da fila
- O processamento continua até que a fila esteja vazia e, em seguida, a sessão emitirá um evento ocioso
Combinando direção e fila
Você pode usar os dois padrões juntos em uma única sessão. O controle de direção afeta o movimento atual enquanto as mensagens enfileiradas esperam sua vez.
const session = await client.createSession({
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approve-once" }),
});
// Start a task
await session.send({ prompt: "Refactor the database layer" });
// Steer the current work
await session.send({
prompt: "Make sure to keep backwards compatibility with the v1 API",
mode: "immediate",
});
// Queue a follow-up for after this turn
await session.send({
prompt: "Now add migration scripts for the schema changes",
mode: "enqueue",
});
session = await client.create_session(
on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
model="gpt-4.1",
)
# Start a task
await session.send("Refactor the database layer")
# Steer the current work
await session.send(
"Make sure to keep backwards compatibility with the v1 API",
mode="immediate",
)
# Queue a follow-up for after this turn
await session.send(
"Now add migration scripts for the schema changes",
mode="enqueue",
)
Escolhendo entre direção e fila
| Scenario | Pattern | Por que |
|---|---|---|
| O agente está indo pelo caminho errado | ||
| Direcção | Redireciona a curva atual sem perder o progresso | |
| Você pensou em algo que o agente também deveria fazer | ||
| Enfileiramento | Não interrompe o trabalho atual; executa em seguida | |
| O agente está prestes a cometer um erro | ||
| Direcção | Intervém antes que o erro seja cometido | |
| Você deseja encadear várias tarefas | ||
| Enfileiramento | A ordenação FIFO garante uma execução previsível | |
| Você deseja adicionar contexto à tarefa atual | ||
| Direcção | O Agente incorpora-o ao seu raciocínio atual | |
| Você deseja enviar em lote solicitações não relacionadas | ||
| Enfileiramento | Cada um obtém seu próprio turno completo com contexto limpo |
Criando uma interface do usuário com direção e fila
Aqui está um padrão para criar uma interface do usuário interativa que dá suporte a ambos os modos:
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;
}
// Session is busy — let the user choose how to deliver
// Your UI would present this choice (e.g., buttons, keyboard shortcuts)
}
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 = [];
// Update UI to show session is ready for new input
}
private renderMessage(event: unknown): void {
// Render assistant message in your UI
}
}
Referência de API
Opções de Mensagem
| Linguagem | Campo | Tipo | Default | Description |
|---|---|---|---|---|
| Node.js | mode | "enqueue" | "immediate" | "enqueue" | Modo de entrega de mensagens |
| Python | mode | Literal["enqueue", "immediate"] | "enqueue" | Modo de entrega de mensagens |
| Go | Mode | string | "enqueue" | Modo de entrega de mensagens |
| .NET | Mode | string? | "enqueue" | Modo de entrega de mensagens |
Modos de entrega
| Modo | Efeito | Durante o turno ativo | Durante a inatividade |
|---|---|---|---|
"enqueue" | Fila para a próxima curva | Esperas na fila FIFO | Inicia uma nova curva imediatamente |
"immediate" | Injetar no turno atual | Injetado antes da próxima chamada LLM | Inicia uma nova curva imediatamente |
Observação
Quando a sessão está ociosa (não processando), ambos os modos se comportam de forma idêntica– a mensagem inicia um novo turno imediatamente.
Práticas recomendadas
-
Definir como padrão o enfileiramento — Usar
"enqueue"(ou omitirmode) para a maioria das mensagens. É previsível e não corre o risco de interromper o trabalho em andamento. -
Reserve o direcionamento exclusivamente para correções — use
"immediate"quando o agente estiver fazendo algo errado ativamente e for necessário redirecioná-lo antes que ele avance ainda mais. -
Mantenha as mensagens de direção concisas: o agente precisa entender rapidamente a correção do curso. Mensagens de direção longas e complexas podem confundir o contexto atual.
-
Não direcione demais— várias mensagens de direção rápidas podem prejudicar a qualidade da curva. Se você precisar alterar significativamente a direção, considere anular a curva e iniciar novamente.
-
Mostrar o estado da fila na interface do usuário — exiba o número de mensagens enfileiradas para que os usuários saibam o que está pendente. Monitore eventos de inatividade para limpar a tela.
-
Manipular o fallback de direção para fila — se uma mensagem de direção chegar após a conclusão da curva, ela será movida automaticamente para a fila. Crie sua interface do usuário para refletir essa transição.
Consulte também
- Crie seu primeiro aplicativo com tecnologia do Copilot: Configurar uma sessão e enviar mensagens
- Agentes personalizados e orquestração de subagentes: Defina agentes especializados com ferramentas de escopo definido
- Ganchos de sessão: Reagir a eventos do ciclo de vida da sessão
- Retomada e persistência da sessão: Retomar sessões entre reinicializações