Übersicht
Wenn eine Sitzung aktiv eine Interaktion verarbeitet, können eingehende Nachrichten auf eine von zwei Arten über das mode-Feld zugestellt werden:MessageOptions
| Modus | Behavior | Anwendungsfall |
|---|---|---|
"immediate" (Lenkung) | In die aktuelle LLM-Umwandlung eingefügt | "Erstellen Sie diese Datei tatsächlich nicht – verwenden Sie einen anderen Ansatz" |
"enqueue" (Warteschlangen) | In die Warteschlange eingereiht und verarbeitet nach Abschluss des aktuellen Durchgangs | "Danach beheben Sie auch die Tests" |

Lenkung (Sofortiger Modus)
Die Lenkung sendet eine Nachricht, die direkt in den aktuellen Spielzug des Agenten eingespeist wird. Der Agent sieht die Nachricht in Echtzeit und passt seine Antwort entsprechend an – nützlich für die Kurskorrektur, ohne die Drehung abzubrechen.
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();
}
Funktionsweise der Steuerung intern
- Die Nachricht wird zur Warteschlange der Laufzeitumgebung
ImmediatePromptProcessorhinzugefügt. - Vor der nächsten LLM-Anfrage innerhalb des aktuellen Turns fügt der Prozessor die Nachricht in die Konversation ein.
- Der Agent sieht die Lenkungsnachricht als neue Benutzernachricht und passt seine Antwort an.
- Wenn der Abbiegevorgang abgeschlossen ist, bevor die Lenknachricht verarbeitet wird, wird er automatisch für den nächsten Abbiegevorgang in die reguläre Warteschlange verschoben.
Hinweis
Lenkungsmeldungen sind in der aktuellen Drehung am besten geeignet. Wenn sich der Agent bereits für einen Tool-Call verpflichtet hat, wird die Steuerung nach Abschluss dieses Calls wirksam, aber immer noch innerhalb desselben Turns.
Warteschlangen (Enqueue-Modus)
Das Warteschlangenpuffer speichert Nachrichten, die sequenziell verarbeitet werden, nachdem die aktuelle Bearbeitung abgeschlossen ist. Jede in die Warteschlange eingereihte Nachricht startet einen eigenen vollständigen Durchlauf. Dies ist der Standardmodus – wenn Sie weglassen mode, verwendet "enqueue"das SDK .
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
}
Funktionsweise der Warteschlangen intern
- Die Nachricht wird dem
itemQueueder Sitzung alsQueuedItemhinzugefügt. - Wenn der aktuelle Durchlauf abgeschlossen ist und die Sitzung inaktiv wird, wird
processQueuedItems()ausgeführt. - Elemente werden in FIFO-Reihenfolge dequeuiert – jede Nachricht löst eine vollständige agentische Drehung aus.
- Wenn beim Ende der Drehung eine Lenkungsmeldung ausstehend war, wird sie an den Anfang der Warteschlange verschoben.
- Die Verarbeitung wird fortgesetzt, bis die Warteschlange leer ist, und dann gibt die Sitzung ein Leerlaufereignis aus.
Kombination von Steuerung und Warteschlangenverwaltung
Sie können beide Muster in einer einzigen Sitzung verwenden. Die Lenkung wirkt sich auf die aktuelle Drehung aus, während Nachrichten in der Warteschlange auf ihre eigenen Drehungen warten.
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",
)
Auswahl zwischen Lenkung und Warteschlangen
| Szenario | Pattern | Warum? |
|---|---|---|
| Der Agent geht auf den falschen Pfad. | ||
| Lenkung | Leitet den aktuellen Turn um, ohne den Fortschritt zu verlieren. | |
| Sie dachten an etwas, was der Agent auch tun sollte | ||
| Warteschlangenbildung | Stört die aktuelle Arbeit nicht; wird als Nächstes ausgeführt. | |
| Agent ist dabei, einen Fehler zu machen | ||
| Lenkung | Greift ein, bevor der Fehler begangen wird | |
| Sie möchten mehrere Vorgänge verketten | ||
| Warteschlangenbildung | FIFO-Sortierung gewährleistet vorhersehbare Ausführung | |
| Sie möchten der aktuellen Aufgabe Kontext hinzufügen | ||
| Lenkung | Agent integriert es in seine aktuelle Begründung | |
| Sie möchten unabhängige Anforderungen zusammenfassen. | ||
| Warteschlangenbildung | Jeder bekommt seinen eigenen vollständigen Schritt mit klarem Kontext. |
Erstellen einer Benutzeroberfläche mit Steuerung und Warteschlangen
Hier ist ein Muster zum Erstellen einer interaktiven Benutzeroberfläche, die beide Modi unterstützt:
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
}
}
API-Referenz
Nachrichtenoptionen
| Sprache | Feld | Typ | Vorgabe | Description |
|---|---|---|---|---|
| Node.js | mode | "enqueue" | "immediate" | "enqueue" | Nachrichtenübermittlungsmodus |
| Python | mode | Literal["enqueue", "immediate"] | "enqueue" | Nachrichtenübermittlungsmodus |
| Go | Mode | string | "enqueue" | Nachrichtenübermittlungsmodus |
| .NET | Mode | string? | "enqueue" | Nachrichtenübermittlungsmodus |
Liefermodi
| Modus | Auswirkung | Während einer aktiven Drehung | Während des Leerlaufs |
|---|---|---|---|
"enqueue" | Warteschlange für nächsten Schritt | Wartezeiten in der FIFO-Warteschlange | Startet sofort eine neue Drehung. |
"immediate" | In die aktuelle Drehung einfügen | Vor dem nächsten LLM-Aufruf eingefügt | Startet sofort eine neue Drehung. |
Hinweis
Wenn sich die Sitzung im Leerlauf befindet (keine Verarbeitung), verhalten sich beide Modi identisch – die Nachricht startet sofort eine neue Drehung.
Bewährte Methoden
-
Voreinstellung auf Warteschlange setzen – Verwenden Sie
"enqueue"für die meisten Nachrichten (odermodeauslassen). Es ist vorhersagbar und riskiert keine Unterbrechung der laufenden Arbeit. -
Behalten Sie sich die Steuerung für Korrekturen vor – Verwenden Sie
"immediate", wenn der Agent aktiv fehlerhaft handelt und Sie ihn korrigieren müssen, bevor es weitergeht. -
Halten Sie die Lenkungsnachrichten kurz – Der Agent muss die Kurskorrektur schnell verstehen. Lange, komplexe Lenkungsmeldungen können den aktuellen Kontext verwirren.
-
Nicht übersteuern – Mehrere schnelle Lenkmeldungen können die Drehqualität beeinträchtigen. Wenn Sie die Richtung erheblich ändern müssen, sollten Sie die Drehung abbrechen und neu beginnen.
-
Anzeigen des Warteschlangenstatus in der Benutzeroberfläche – Zeigen Sie die Anzahl der in die Warteschlange eingereihten Nachrichten an, damit Benutzer wissen, was aussteht. Lauschen Sie auf Leerlaufereignisse, um die Anzeige zu löschen.
-
Bearbeiten Sie den Fallback vom Steuerungsvorgang zur Warteschlange– Wenn eine Steuerungsnachricht nach dem Abschluss des Steuerungsvorgangs eingeht, wird sie automatisch in die Warteschlange verschoben. Entwerfen Sie Ihre Benutzeroberfläche so, dass sie diesen Übergang widerspiegelt.
Siehe auch
- Erstellen Sie Ihre erste Copilot-gestützte App: Einrichten einer Sitzung und Senden von Nachrichten
- Benutzerdefinierte Agents und Sub-Agent-Orchestrierung: Spezialisierte Agenten mit abgegrenzten Tools definieren
- Sitzungshaken: Reagieren auf Sitzungslebenszyklusereignisse
- Wiederaufnahme und Persistenz der Sitzung: Fortsetzen von Sitzungen über Neustarts hinweg