Visión general
Cuando una sesión procesa activamente un turno, los mensajes entrantes se pueden entregar en uno de los dos modos a través del mode campo en MessageOptions:
| Modo | Comportamiento | Caso de uso |
|---|---|---|
"immediate" (dirección) | Insertado en el turno LLM actual | De hecho, no cree ese archivo, sino que use un enfoque diferente. |
"enqueue" (puesta en cola) | Puesto en cola y procesado después de que finalice el turno actual | "Después de esto, también corrija las pruebas" |

Dirección (modo inmediato)
El sistema de control envía un mensaje que se inserta directamente en el turno actual del agente. El agente ve el mensaje en tiempo real y ajusta su respuesta en consecuencia, útil para corregir el curso sin anular el 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();
}
Funcionamiento interno del sistema de dirección
- El mensaje se agrega a la cola de
ImmediatePromptProcessortiempo de ejecución. - Antes de la siguiente solicitud LLM dentro del turno actual, el procesador inserta el mensaje en la conversación.
- El agente ve el mensaje de dirección como un nuevo mensaje de usuario y ajusta su respuesta.
- Si el turno se completa antes de que se procese el mensaje de control, se mueve automáticamente a la cola habitual para el siguiente turno.
Nota:
Los mensajes de dirección son el mejor esfuerzo dentro del turno actual. Si el agente ya se ha comprometido con una llamada de herramienta, el control surte efecto después de que se complete esa llamada, pero aún dentro del mismo turno.
Puesta en cola (modo de puesta en cola)
Poner en cola los mensajes que se van a procesar secuencialmente después de que finalice el turno actual. Cada mensaje en cola inicia su propio turno completo. Este es el modo predeterminado: si omite mode, el SDK usa "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
}
Funcionamiento interno del sistema de colas
- El mensaje se agrega a la sesión
itemQueuecomoQueuedItem - Cuando se completa el turno actual y la sesión deja de estar inactiva,
processQueuedItems()se ejecuta - Los elementos se extraen en orden FIFO—cada mensaje desencadena una iteración agéntica completa.
- Si un mensaje de dirección estaba pendiente cuando finalizó el turno, se mueve al frente de la cola.
- El procesamiento continúa hasta que la cola está vacía y la sesión emite un evento inactivo.
Combinación de encaminamiento y gestión de colas
Puede usar ambos patrones juntos en una sola sesión. La dirección afecta al turno actual mientras los mensajes en cola esperan sus propios turnos:
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",
)
Elección entre la dirección y la cola
| Escenario | Pattern | Por qué |
|---|---|---|
| El agente va por la ruta incorrecta | ||
| Dirección | Redirige el turno actual sin perder el progreso. | |
| Pensaste en algo que el agente también debería hacer | ||
| Puesta en cola | No interrumpe el trabajo actual; se ejecuta a continuación | |
| El agente está a punto de cometer un error | ||
| Dirección | Interviene antes de cometer el error | |
| Quiere encadenar varias tareas | ||
| Puesta en cola | La ordenación de FIFO garantiza una ejecución predecible | |
| Quiere agregar contexto a la tarea actual. | ||
| Dirección | El agente lo incorpora en su razonamiento actual | |
| Usted quiere agrupar solicitudes no relacionadas por lotes | ||
| Puesta en cola | Cada uno obtiene su propio ciclo completo con contexto claro |
Creación de una interfaz de usuario con control y gestión de colas
Este es un patrón para crear una interfaz de usuario interactiva que admita ambos 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
}
}
Referencia de las API
Opciones de Mensaje
| Language | Campo | Tipo | Predeterminado | Description |
|---|---|---|---|---|
| Node.js | mode | "enqueue" | "immediate" | "enqueue" | Modo de entrega de mensajes |
| Python | mode | Literal["enqueue", "immediate"] | "enqueue" | Modo de entrega de mensajes |
| Ir | Mode | string | "enqueue" | Modo de entrega de mensajes |
| .NET | Mode | string? | "enqueue" | Modo de entrega de mensajes |
Modos de entrega
| Modo | Efecto | Durante el turno activo | Durante el tiempo de inactividad |
|---|---|---|---|
"enqueue" | Cola para el próximo turno | Espera en la cola FIFO | Inicia un nuevo turno inmediatamente |
"immediate" | Insertar en el turno actual | Insertado antes de la siguiente llamada LLM | Inicia un nuevo turno inmediatamente |
Nota:
Cuando la sesión está inactiva (no se procesa), ambos modos se comportan de forma idéntica: el mensaje inicia un nuevo turno inmediatamente.
procedimientos recomendados
-
Valor predeterminado para poner en cola: use
"enqueue"(o omitamode) para la mayoría de los mensajes. Es predecible y no corre el riesgo de interrumpir el trabajo en curso. -
Reserva la dirección para correcciones: Use
"immediate"cuando el agente esté haciendo activamente lo incorrecto y usted necesite redirigirlo antes de que vaya más allá. -
Mantener los mensajes de dirección concisos: el agente debe comprender rápidamente la corrección del curso. Los mensajes de dirección complejos largos pueden confundir el contexto actual.
-
No sobregire—varios mensajes rápidos de dirección pueden degradar la calidad del giro. Si necesita cambiar significativamente la dirección, considere la posibilidad de anular el turno e iniciarlo de nuevo.
-
Mostrar el estado de la cola en la interfaz de usuario: muestra el número de mensajes en cola para que los usuarios sepan lo que está pendiente. Monitoree los eventos inactivos para limpiar la pantalla.
-
Manejar el mecanismo de encaminamiento a cola: si llega un mensaje de encaminamiento después de que el turno se complete, se mueve automáticamente a la cola. Diseñe la interfaz de usuario para reflejar esta transición.
Consulte también
- Crea tu primera aplicación con tecnología Copilot: Configuración de una sesión y envío de mensajes
- Agentes personalizados y orquestación de subagentes: Definir agentes especializados con herramientas de alcance definido
- Session hooks: Reaccionar a eventos del ciclo de vida de la sesión
- Reanudación y persistencia de sesión: Reanudar sesiones entre reinicios