Skip to main content
Skip to content

Wiederaufnahme und Persistenz der Sitzung

Dieses Handbuch führt Sie durch die Sitzungspersistenzfunktionen des SDK – wie Sie die Arbeit anhalten, später fortsetzen und Sitzungen in Produktionsumgebungen verwalten können.

Funktionsweise von Sitzungen

Wenn Sie eine Sitzung erstellen, speichert die Copilot CLI den Konversationsverlauf, den Status der Tools und den Planungskontext. Dieser Zustand befindet sich standardmäßig im Arbeitsspeicher und verschwindet, wenn die Sitzung endet. Mit aktivierter Persistenz können Sie Sitzungen über Neustarts, Containermigrationen oder sogar unterschiedliche Clientinstanzen hinweg fortsetzen.

Diagramm: Flussdiagramm mit dem beschriebenen Prozess.

StateWas ist los
Erstellensession_id Zugewiesen
AktivSenden von Eingabeaufforderungen, Toolanrufen, Antworten
PausiertAuf dem Datenträger gespeicherter Zustand
ResumeVom Datenträger geladener Zustand

Schnellstart: Erstellen einer reaktivierbaren Sitzung

Der Schlüssel zu wiederaufnehmbaren Sitzungen ist, dass Sie Ihre eigene session_id bereitstellen. Ohne eine generiert das SDK eine zufällige ID, und die Sitzung kann später nicht fortgesetzt werden.

Typescript

import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();

// Create a session with a meaningful ID
const session = await client.createSession({
  sessionId: "user-123-task-456",
  model: "gpt-5.2-codex",
});

// Do some work...
await session.sendAndWait({ prompt: "Analyze my codebase" });

// Session state is automatically persisted
// You can safely close the client

Python

from copilot import CopilotClient
from copilot.session import PermissionHandler

client = CopilotClient()
await client.start()

# Create a session with a meaningful ID
session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-5.2-codex", session_id="user-123-task-456")

# Do some work...
await session.send_and_wait("Analyze my codebase")

# Session state is automatically persisted

Go

ctx := context.Background()
client := copilot.NewClient(nil)

// Create a session with a meaningful ID
session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
    SessionID: "user-123-task-456",
    Model:     "gpt-5.2-codex",
})

// Do some work...
session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Analyze my codebase"})

// Session state is automatically persisted

C# (.NET)

using GitHub.Copilot;

var client = new CopilotClient();

// Create a session with a meaningful ID
var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = "user-123-task-456",
    Model = "gpt-5.2-codex",
});

// Do some work...
await session.SendAndWaitAsync(new MessageOptions { Prompt = "Analyze my codebase" });

// Session state is automatically persisted

Fortsetzen einer Sitzung

Später – Minuten, Stunden oder sogar Tage – können Sie die Sitzung fortsetzen, von wo Sie aufgehört haben.

Gemerkte Berechtigungen mit einem Sitzungsdateisystem

Wenn Sie einen benutzerdefinierten sessionFs Anbieter konfigurieren, verwenden dauerhafte, von der Laufzeit verwaltete Berechtigungsoptionen den Anbieterspeicher anstelle der Konfiguration des Laufzeithosts. Die Dateien befinden sich unter dem sessionStatePath des Anbieters und behalten ihre vorhandenen Formate bei:

  • permissions.json: Eine Zuordnung auf oberster Ebene locations , die die vorhandenen tool_approvals Felder und allowed_directories Felder beibehält
  • settings.json: Oberste Ebene allowedUrls für approve-permanently URL-Genehmigungen und sandbox für gespeicherte Sandkasteneinstellungen
  • config.json: Oberste Ebene trustedFolders für Vertrauen für gemerkte Ordner und sandboxOnboardingShown für die Sandbox-Meldung beim ersten Aktivieren

Standortschlüssel sind normalisierte Anbieterverzeichnispfade, wie z. B. /workspace, ohne hinzugefügtes Präfix. Die Laufzeit löst sie lexikalisch mithilfe von Anbieterpfadkonventionen auf, ohne das Hostdateisystem zu prüfen oder Host-Git-Repositorys zu ermitteln. Eine gespeicherte /workspace Genehmigung wird nicht automatisch ausgewählt, wenn das Arbeitsverzeichnis /workspace/sub ist.

Anbietergestütztes Ordnervertrauen verwendet ebenfalls lexikalische Pfade: Ein vertrauenswürdiger Ordner umfasst sich selbst und seine untergeordneten Ordner, nicht verknüpfte Git-Worktrees an anderen Pfaden. Vertrauen Sie diesen Worktree-Pfaden explizit.

Es gibt keine zusätzliche Sitzungs-ID-Partition innerhalb dieser Dateien. Sitzungen, die auf die gleichen zugrunde liegenden Dateien zugreifen, teilen sich gespeicherte Auswahlmöglichkeiten. Verwenden Sie separate Anbieternamespaces, wenn Sitzungen oder Mandanten keine Berechtigungen gemeinsam nutzen dürfen. Bei einem Namespace pro Sitzung überdauern permanente Auswahlmöglichkeiten die Fortsetzungen dieser Sitzung, werden aber nicht automatisch auf neue Sitzungen übertragen. Um die beibehaltenen Auswahlmöglichkeiten einer Sitzung beim Fortsetzen wiederherzustellen, verbinden Sie sie erneut mit demselben Namespace.

Zustimmungsupdates werden pro Anbieterendpunkt und Datei innerhalb eines Laufzeitprozesses serialisiert. Getrennte Endpunkte blockieren sich nicht gegenseitig. Wenn unterschiedliche Anbieterendpunkte oder Laufzeitprozesse zugrunde liegende Dateien gemeinsam nutzen, muss die Anwendung gleichzeitige Updates koordinieren. Die Laufzeit kann nicht ableiten, dass diese Dateien gemeinsam genutzt werden.

Diese Vorgänge importieren, aktualisieren oder auf die permissions-config.json, settings.json oder config.json des Hosts zurückfallen nie, auch wenn Lese- oder Schreibvorgänge des Anbieters fehlschlagen. Dateien im vorhandenen Format, die über den Anbieter bereitgestellt werden, werden direkt gelesen.

Wie bei der Hostkonfiguration werden URL-Genehmigungen nur aus settings.json gelesen. Ein Legacyfeld allowedUrls in config.json wird ignoriert; config.json bleibt die globale Zustandsdatei für gespeichertes Ordnervertrauen und die Sandkasten-Onboarding-Markierung.

Das Speicherrouting ändert nicht die Gültigkeitsdauern von Berechtigungen, die Priorität von URL-Ablehnungen oder das Sitzungsrichtlinienverhalten. „Einmal genehmigen“ und „Für Sitzung genehmigen“ werden nicht zu dauerhaften Berechtigungen.

Gespeicherte Sandbox-Einstellungen werden beim Erstellen und Fortsetzen wiederhergestellt. Später können explizite SDK-Aufrufe options.update die Live-Sandkastenkonfiguration ändern, ohne die gespeicherte Einstellung neu zu schreiben.

Ohne sessionFs, SDK-Anwendungen in beiden empty Und copilot-cli Modi behalten vorhandene hostgestützte Persistenz bei. Dies schließt das vorhandene Verhalten ein, bei dem die dauerhafte Zustimmung zur URL Hosteinstellungen speichert und in der Livesitzung Zugriff gewährt, aber eine neue SDK-Sitzung lädt die Host-URL-Zulassungsliste nicht automatisch.

Siehe Mandantenfähigkeit und Serverbereitstellungen für Verantwortlichkeiten bei der Anbieterisolation.

Transkriptwiederherstellung

Die Option „Fortsetzen“ allowTranscriptRecovery steuert die Wiederherstellung, wenn die Runtime ein Transkript aus dem Speicher lädt. Standardmäßig ist in allen Modi true eingestellt. Mit false schlägt ein Ladevorgang, der beschädigte Datensätze verwerfen oder session.start verschieben würde, mit dem JSON-RPC-Fehler -32075 fehl, ohne das Transkript umzuschreiben. Ein intakter endgültiger Datensatz ohne Zeilenumbruch wird akzeptiert.

Datensätze, die für die Vorwärtskompatibilität übersprungen wurden, zählen bei der Überprüfung der dauerhaften Reihenfolge weiterhin. Wenn solche Datensätze vor session.start stehen, muss die Wiederherstellung den Startdatensatz vor sie verschieben. Ein Transkript, das nur übersprungene Datensätze enthält, ist nicht leer und kann nicht ohne gültige session.start wiederhergestellt werden.

Wenn die Wiederherstellung zulässig ist, stellt die zurückgegebene Sitzung transcriptRecovery bereit, einschließlich der ungültigen Zeilennummern, ob session.start verschoben wurde und eines geplanten bytegenauen Sicherungspfads. Das Laden allein schreibt diese Sicherung nicht; der nächste dauerhafte Append-Vorgang führt die Reparatur durch und schreibt diese Sicherung.

Hinweis

Diese Option gilt für das Laden eines neuen Transkripts, nicht für die Lebensdauer einer Sitzung. Durch erneutes Herstellen einer Verbindung zu einer Sitzung, die bereits in der Laufzeit ansässig ist, wird der Liveverlauf wiederverwendet, ohne den Speicher erneut zu überprüfen oder die Wiederherstellung abzulehnen, die von einer früheren Wiederaufnahme autorisiert wurde. Der Wiederherstellungsbericht beschreibt die Last, die die Wiederherstellung durchgeführt hat, nicht jede nachfolgende erneute Verbindung.

Diagramm: Flussdiagramm mit dem beschriebenen Prozess.

Typescript

// Resume from a different client instance (or after restart)
const session = await client.resumeSession("user-123-task-456");

// Continue where you left off
await session.sendAndWait({ prompt: "What did we discuss earlier?" });

Python

# Resume from a different client instance (or after restart)
session = await client.resume_session("user-123-task-456", on_permission_request=PermissionHandler.approve_all)

# Continue where you left off
await session.send_and_wait("What did we discuss earlier?")

Go

ctx := context.Background()

// Resume from a different client instance (or after restart)
session, _ := client.ResumeSession(ctx, "user-123-task-456", nil)

// Continue where you left off
session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "What did we discuss earlier?"})

C# (.NET)

// Resume from a different client instance (or after restart)
var session = await client.ResumeSessionAsync("user-123-task-456");

// Continue where you left off
await session.SendAndWaitAsync(new MessageOptions { Prompt = "What did we discuss earlier?" });

Optionen für "Fortsetzen"

Beim Fortsetzen einer Sitzung können Sie optional viele Einstellungen neu konfigurieren. Dies ist nützlich, wenn Sie das Modell ändern, Toolkonfigurationen aktualisieren oder das Verhalten ändern müssen.

AuswahlDescription
modelÄndern des Modells für die fortgesetzte Sitzung
systemMessageÜberschreiben oder Erweitern der Systemaufforderung
availableToolsEinschränken der verfügbaren Tools
excludedToolsDeaktivieren bestimmter Tools
providerErneutes Bereitstellen von BYOK-Anmeldeinformationen (erforderlich für BYOK-Sitzungen)
capi.autoTierDie gespeicherte Auto-Routing-Einstellung überschreiben
capi.enableWebSocketResponsesAuswählen des Antwort-API-Transports für die fortgesetzte Sitzung
reasoningEffortAnpassen der Aufwandsstufe für die Begründung
streamingAktivieren oder Deaktivieren von Streaming-Antworten
workingDirectoryÄndern des Arbeitsverzeichnisses
configDirKonfigurationsverzeichnis außer Kraft setzen
mcpServersMCP-Server konfigurieren
customAgentsKonfigurieren von benutzerdefinierten Agents
agentVorauswahl eines benutzerdefinierten Agents anhand des Namens
skillDirectoriesVerzeichnisse, aus denen Fähigkeiten geladen werden
disabledSkillsZu deaktivierende Fähigkeiten
infiniteSessionsKonfigurieren des unendlichen Sitzungsverhaltens

Persistenz der automatischen Stufe

Mit model: "auto" wählt die optionale Einstellung capi.autoTier eine Präferenz für automatisches Routing aus: efficiency, balance, intelligence oder fast. Verwenden Sie capi={"auto_tier": "balance"}in Python . Diese Einstellung gilt für das automatische V2-Routing; V1 Autoanforderungen sind unverändert.

Wenn die standardmäßig deaktivierte Funktion DYNAMIC_AUTO_TIERS der Laufzeit aktiviert ist, gibt das RPC der Sitzung model.list auch optionale auto-Metadaten vom Endpunkt des Anbieters /meta zurück. Verwenden Sie die aktivierten Deskriptoren mit type: "auto", um zusätzliche unterstützte Ebenenbezeichner, deren Anzeigenamen, Beschreibungen und Sortierung zu entdecken. Die vorhandenen Auswahlmethoden und JSON-Felder akzeptieren diese Bezeichner. Ein Fehler bei der Ermittlung greift nicht auf /models zurück, und eine erfolgreiche Antwort ohne auto-Metadaten stellt keine auswählbaren automatischen Stufen bereit.

Wenn Sie eine Modellauswahl befüllen möchten, bevor eine Sitzung vorhanden ist, aktivieren Sie DYNAMIC_AUTO_TIERS in der Umgebung der Laufzeit (z. B. die env-Clientoption). Der RPC auf Serverebene models.list (client.rpc.models.list() in Node.js) gibt dann dieselben auto Metadaten aus derselben /meta Antwort zurück, wobei dasselbe No-Fallback-Verhalten erfolgt. Die Auflistung auf Serverebene liest das Flag, das beim Start von der Laufzeit aufgelöst wurde, nicht sitzungsspezifische Feature-Flags oder Experimentzuweisungen, also legen Sie das Flag dort fest, wo Sie die Laufzeit starten. Wenn das Flag deaktiviert ist, bleibt models.list unverändert und lässt auto weg.

Behandeln Sie Ebenenbezeichner als erweiterbare Werte und nicht als geschlossene Enumeration. Vorhandene benannte Werte bleiben verfügbar; für zusätzliche Bezeichner verwenden Sie Zeichenfolgen in Node.js und Python, AutoTier("premium-v2") in Go, new AutoTier("premium-v2") in .NET, AutoTier::Custom in Rust oder AutoTier.fromValue in Java. Die Dokumentation des Anbieters defaultTier beschreibt sein Standardrouting, ohne eine zugesicherte SDK-Einstellung zu erstellen.

Wenn eine beibehaltene Stufe entfernt oder deaktiviert wird, behält Resume die explizite Einstellung bei, anstatt sie durch die Standardeinstellung des Anbieters zu ersetzen. Wählen Sie einen verfügbaren Ersatz aus, bevor Sie das automatische Routing aktivieren.

Die CLI behält auch aus Einstellungen abgeleitete Präferenzen während des Starts bei, auch wenn eine Ebene nicht verfügbar ist oder die dynamische Ermittlung deaktiviert ist. Anschließend können Sie in der Modellauswahl eine Alternative auswählen. Explizite SDK-Erstellungs- und Fortsetzungseinstellungen werden noch überprüft, bevor der Vorgang erfolgreich abgeschlossen wird, und die automatische Aktivierung überprüft immer die Verfügbarkeit anhand des aufgelösten Erkennungsmodus.

Wenn eine Erstellungs- oder Fortsetzungsanforderung expAssignments enthält, installiert die Laufzeit diese Zuweisungen, bevor eine explizite Auto-Einstellung überprüft wird. Validierung, Erkennung und Aktivierung verwenden dieselbe aufgelöste Featureentscheidung.

fast ist eine Latenzvoreinstellung nur für Integratoren, keine Produktpräferenz von GitHub Copilot selbst. „Fast“ wird beim Konfigurieren einer Sitzung nicht anhand des /meta-Ebenenkatalogs überprüft. Das SDK entscheidet nicht über die Fast-Eignung, prüft nicht die Client-Identität, legt Fast nicht als Standard fest und fällt nicht auf eine andere Stufe zurück, wenn eine Laufzeit Fast nicht unterstützt – eine ältere Laufzeit gibt ihren nativen Fehler unverändert zurück.

Die Laufzeit behält die ausgewählte Ebene bei, sodass Anwendungen sie bei jedem Lebenslauf nicht erneut senden müssen:

  • Wenn Sie die Stufe beim Erstellen einer Sitzung weglassen, wird das Standardroutingverhalten der Laufzeit verwendet.
  • Bei einer „kalten“ Wiederaufnahme wird die gespeicherte Stufe wiederhergestellt. Die Angabe einer expliziten Stufe überschreibt den wiederhergestellten Wert für die neue Aktivierung.
  • Wenn eine Sitzung fortgesetzt wird, die sich bereits in der Laufzeit befindet, behält das Auslassen der Leiste die aktuelle Auswahl bei und die Bereitstellung derselben Ebene ist eine no-op. Die Angabe einer anderen Stufe fordert einen sicheren Wechsel an, den die Laufzeitumgebung nach erfolgreicher Wiederaufnahme anwendet; ein bereits laufender Durchgang kann nicht geändert werden.
  • Ältere Sitzungen ohne beibehaltene Ebene behalten das Standardroutingverhalten bei.

Die Stufenauswahl ist kein Live-Modellwechsel. Das SDK leitet die Einstellung weiter; die Laufzeit ist für die Persistenz und Validierung zuständig.

Die Ereignisse session.start und session.resume geben das ausgewählte Tier in ihrem optionalen data.autoTier-Feld (data.auto_tier in Python) an. Wenn keine Stufe ausgewählt ist, wird das Feld ausgelassen.

Ändern der Auto-Stufe während einer Sitzung

Rufen Sie setAutoTier auf, um die Routingeinstellung in einer Livesitzung zu ändern, ohne das ausgewählte Modell zu ändern. Übergeben Sie null (Python None, Go nil), um zum Standard-Auto-Routing des Anbieters zurückzukehren.

const result = await session.setAutoTier("intelligence");
if (result.status === "pending") {
  // Accepted, but not yet in effect.
}

Die Laufzeit wendet die Präferenz nicht sofort an. Sie protokolliert die Anforderung und übernimmt sie erst dann, wenn ein späterer Benutzerschritt unter Verwendung des Modells auto erfolgreich ein nutzbares Modell vom Anbieter erhält. Ein pending Status bestätigt daher, dass die Anforderung angenommen wurde, nicht, dass sie wirksam wurde. Nur die neueste Anforderung bleibt bestehen: Eine neue Anforderung ersetzt jede frühere Anforderung, die noch von keinem Durchgang beansprucht wurde.

Wenn eine ältere Anfrage immer noch überprüft wird, wenn eine neuere Einstellungsanfrage oder eine Rücksetzanfrage eingeht, schlägt der ältere Aufruf mit einem Fehler wegen ersetzter Anfrage fehl, anstatt die neuere Anfrage zu ersetzen.

Verfolgen Sie das Ergebnis bei diesen Veranstaltungen:

  • session.model_change wenn die Einstellung übernommen wird.
  • session.auto_tier_switch_failed wenn dies nicht der Fall ist. Dieses Ereignis ist kurzlebig, sodass die Laufzeit beim Fortsetzen nie beibehalten oder wiedergegeben wird. Das reason Feld ist eines von policy_rejected, request_failed, setup_failed oder unsupported, und die zuvor wirksame Präferenz bleibt aktiv.

Sie können den autoritativen Zustand auch jederzeit über die RPC-Methode model.getCurrent der Sitzung lesen, die den festgeschriebenen autoTier, alle nicht beanspruchten pendingAutoTier und die activatingAutoTier meldet, die derzeit von einer laufenden Aktivierung beansprucht werden.

SDKEbene ändernZurück zum Anbieterstandardrouting
Node.jssession.setAutoTier("balance")session.setAutoTier(null)
Pythonsession.set_auto_tier("balance")session.set_auto_tier(None)
Gosession.SetAutoTier(ctx, &tier)session.SetAutoTier(ctx, nil)
.NETsession.SetAutoTierAsync(AutoTier.Balance)session.SetAutoTierAsync(null)
Rustsession.set_auto_tier(Some(AutoTier::Balance))session.set_auto_tier(None)
Javasession.setAutoTier(AutoTier.BALANCE)session.setAutoTier(null)

Um das auto-Modell und seine Routingpräferenz in einem einzigen Aufruf auszuwählen, legen Sie stattdessen die Stufe im Modellwechsel fest. Die Laufzeit lehnt diese Option ab, wenn das Modell nicht auto ist.

SDKBereitstellen einer Stufe mit dem WechselAuf Anbieterstandardrouting zurücksetzen
Node.jssetModel("auto", { autoTier: "balance" })setModel("auto", { autoTier: null })
Pythonset_model("auto", auto_tier="balance")set_model("auto", auto_tier=None)
GoSetModelOptions{AutoTier: &tier}SetModelOptions{ResetAutoTier: true}
.NETnew SetModelOptions { AutoTier = AutoTier.Balance }new SetModelOptions { ResetAutoTier = true }
RustSetModelOptions::default().with_auto_tier(AutoTier::Balance)SetModelOptions::default().with_reset_auto_tier()
Javanew SetModelOptions().setModel("auto").setAutoTier(AutoTier.BALANCE)new SetModelOptions().setModel("auto").setResetAutoTier(true)

Node.js, Python und Rust ausdrücken alle drei Zustände in einem einzelnen Wert: Node.js und Python, da null/None von einem ausgelassenen Argument unterschieden werden kann, und Rust, weil es sich um AutoTierPreference::Reset eine unterschiedliche Variante derselben Option handelt. Go, .NET und Java haben keine Möglichkeit, „zurückgesetzt“ von „nicht gesetzt“ anhand eines Werts zu unterscheiden, daher führen sie ein separates Reset-Flag. Das Weglassen beider bedeutet immer „die aktuelle Einstellung unverändert zu lassen“.

Antworten werden beim Fortsetzen übertragen

Die optionale capi.enableWebSocketResponses Einstellung wählt den Transport für die CAPI-Antwort-API aus. Standardmäßig ist true festgelegt, sodass der WebSocket-Transport verwendet wird, wenn das ausgewählte Modell den Endpunkt ws:/responses unterstützt. Wenn dies auf false festgelegt wird, wird auf den HTTP-Transport zurückgegriffen. Verwenden Sie capi={"enable_web_socket_responses": False}in Python .

Geben Sie sie beim Resume-Aufruf an, wenn Sie sie benötigen. Diese Einstellung ist sinnvoll, wenn WebSocket-Verbindungen hinter einem Proxy fehlschlagen und wenn eine wiederaufgenommene Sitzung 400 input item ID does not belong to this connection meldet, was für den WebSocket-Transport spezifisch ist.

const session = await client.resumeSession("user-123-task-456", {
  capi: { enableWebSocketResponses: false },
});

false Diese Einstellung entspricht der COPILOT_CLI_DISABLE_WEBSOCKET_RESPONSES Umgebungsvariablen, die die entgegengesetzte Polarität aufweist.

Beispiel: Ändern des Modells bei der Wiederaufnahme

// Resume with a different model
const session = await client.resumeSession("user-123-task-456", {
  model: "claude-sonnet-4",  // Switch to a different model
  reasoningEffort: "high",   // Increase reasoning effort
});

Verwendung von BYOK (bring your own key) mit wiederaufgenommenen Sitzungen

Wenn Sie Ihre eigenen API-Schlüssel verwenden, müssen Sie die Anbieterkonfiguration beim Fortsetzen erneut bereitstellen. API-Schlüssel werden aus Sicherheitsgründen niemals auf dem Datenträger beibehalten.

// Original session with BYOK
const session = await client.createSession({
  sessionId: "user-123-task-456",
  model: "gpt-5.2-codex",
  provider: {
    type: "azure",
    endpoint: "https://my-resource.openai.azure.com",
    apiKey: process.env.AZURE_OPENAI_KEY,
    deploymentId: "my-gpt-deployment",
  },
});

// When resuming, you MUST re-provide the provider config
const resumed = await client.resumeSession("user-123-task-456", {
  provider: {
    type: "azure",
    endpoint: "https://my-resource.openai.azure.com",
    apiKey: process.env.AZURE_OPENAI_KEY,  // Required again
    deploymentId: "my-gpt-deployment",
  },
});

Was wird persistiert?

Der Sitzungsstatus wird gespeichert in ~/.copilot/session-state/{sessionId}/:

~/.copilot/session-state/
└── user-123-task-456/
    ├── checkpoints/           # Conversation history snapshots
    │   ├── 001.json          # Initial state
    │   ├── 002.json          # After first interaction
    │   └── ...               # Incremental checkpoints
    ├── plan.md               # Agent's planning state (if any)
    └── files/                # Session artifacts
        ├── analysis.md       # Files the agent created
        └── notes.txt         # Working documents
DatenPersistiert?Hinweise
Aufgezeichnete Unterhaltungen
✅ JaVollständiger Nachrichtenthread
Ergebnisse des Toolaufrufs
✅ JaIm Cache gespeichert für Kontext
Planungsstatus des Agenten
✅ Ja
plan.md-Datei
Sitzungsartefakte
✅ JaIm files/ Verzeichnis
Anbieter-/API-Schlüssel
❌ NeinSicherheit: muss erneut bereitgestellt werden
Status des Arbeitsspeicher-Tools
❌ NeinTools sollten zustandslos sein

Bewährte Methoden für Sitzungs-ID

Wählen Sie Sitzungs-IDs aus, die Besitz und Zweck codieren. Dies erleichtert die Überwachung und Bereinigung.

PatternExampleAnwendungsfall
❌abc123Zufällige IDsSchwer zu überwachen, keine Besitzinformationen
✅user-{userId}-{taskId}user-alice-pr-review-42Apps mit mehreren Benutzern
✅tenant-{tenantId}-{workflow}tenant-acme-onboardingMehrinstanzenfähige SaaS
✅{userId}-{taskId}-{timestamp}alice-deploy-1706932800Zeitbasierte Bereinigung

Vorteile strukturierter IDs:

  • Einfach zu überwachen: "Alle Sitzungen für Benutzer alice anzeigen"
  • Einfach zu bereinigen: "Alle Sitzungen löschen, die älter als X sind"
  • Natürliche Zugriffskontrolle: Parsen der Benutzer-ID aus der Sitzungs-ID

Beispiel: Generieren von Sitzungs-IDs

function createSessionId(userId: string, taskType: string): string {
  const timestamp = Date.now();
  return `${userId}-${taskType}-${timestamp}`;
}

const sessionId = createSessionId("alice", "code-review");
// → "alice-code-review-1706932800000"
import time

def create_session_id(user_id: str, task_type: str) -> str:
    timestamp = int(time.time())
    return f"{user_id}-{task_type}-{timestamp}"

session_id = create_session_id("alice", "code-review")
# → "alice-code-review-1706932800"

Verwalten des Sitzungslebenszyklus

Auflisten aktiver Sitzungen

// List all sessions
const sessions = await client.listSessions();
console.log(`Found ${sessions.length} sessions`);

for (const session of sessions) {
  console.log(`- ${session.sessionId} (created: ${session.createdAt})`);
}

// Filter sessions by repository
const repoSessions = await client.listSessions({ repository: "owner/repo" });

Bereinigen von alten Sitzungen

async function cleanupExpiredSessions(maxAgeMs: number) {
  const sessions = await client.listSessions();
  const now = Date.now();
  
  for (const session of sessions) {
    const age = now - new Date(session.createdAt).getTime();
    if (age > maxAgeMs) {
      await client.deleteSession(session.sessionId);
      console.log(`Deleted expired session: ${session.sessionId}`);
    }
  }
}

// Clean up sessions older than 24 hours
await cleanupExpiredSessions(24 * 60 * 60 * 1000);

Getrennt von einer Sitzung (disconnect)

Wenn eine Aufgabe abgeschlossen ist, trennen Sie die Verbindung mit der Sitzung explizit, anstatt auf Timeouts zu warten. Dadurch werden Speicherressourcen freigegeben, sitzungsdaten jedoch auf dem Datenträger beibehalten, sodass die Sitzung später noch fortgesetzt werden kann:

try {
  // Do work...
  await session.sendAndWait({ prompt: "Complete the task" });
  
  // Task complete — release in-memory resources (session can be resumed later)
  await session.disconnect();
} catch (error) {
  // Clean up even on error
  await session.disconnect();
  throw error;
}

Jedes SDK stellt außerdem idiomatische automatische Bereinigungsmuster bereit:

SprachePatternExample
TypeScriptSymbol.asyncDisposeawait using session = await client.createSession(config);
Pythonasync with Kontext-Managerasync with await client.create_session(on_permission_request=handler) as session:
C#IAsyncDisposableawait using var session = await client.CreateSessionAsync(config);
Godeferdefer session.Disconnect()

Hinweis

destroy() wird zugunsten von disconnect() eingestellt. Bestehender Code, der destroy() verwendet, funktioniert weiterhin, sollte aber migriert werden.

Dauerhaftes Löschen einer Sitzung (deleteSession)

Um eine Sitzung und alle zugehörigen Daten dauerhaft vom Datenträger zu entfernen (Aufgezeichnete Unterhaltungen, Planungszustand, Artefakte), verwenden Sie deleteSession. Dies ist unumkehrbar – die Sitzung kann nach dem Löschen nicht fortgesetzt werden:

// Permanently remove session data
await client.deleteSession("user-123-task-456");

disconnect() vs deleteSession():disconnect() veröffentlicht Speicherressourcen, behält jedoch Sitzungsdaten auf dem Datenträger für die spätere Wiederaufnahme bei. deleteSession() Entfernt dauerhaft alles, einschließlich Dateien auf dem Datenträger.

Automatische Bereinigung: Idle Timeout

Standardmäßig haben Sitzungen kein Leerlauftimeout und bleiben unbegrenzt bestehen, bis sie explizit getrennt oder gelöscht werden. Optional können Sie über CopilotClientOptions.sessionIdleTimeoutSeconds ein serverweites Leerlauf-Timeout konfigurieren:

const client = new CopilotClient({
  sessionIdleTimeoutSeconds: 30 * 60, // 30 minutes
});

Wenn ein Timeout konfiguriert ist, werden Sitzungen ohne Aktivität für diese Dauer automatisch bereinigt. Auf 0 setzen oder weglassen, um die Funktion zu deaktivieren.

Hinweis

Diese Option gilt nur dann, wenn das SDK den Laufzeitprozess startet. Beim Herstellen einer Verbindung mit einem vorhandenen Server über cliUrlgilt die eigene Timeoutkonfiguration des Servers.

Diagramm: Flussdiagramm mit dem beschriebenen Prozess.

Sitzungen mit aktiven Prozessen (laufende Befehle, Hintergrund-Agenten) werden unabhängig von der Timeouteinstellung immer vor einer Bereinigung aufgrund von Inaktivität geschützt.

Lauschen Sie auf Leerlaufereignisse, um auf Sitzungsinaktivität zu reagieren:

session.on("session.idle", (event) => {
  console.log(`Session idle for ${event.idleDurationMs}ms`);
});

Bereitstellungsmuster

Am besten geeignet für: Starke Isolation, Mehrinstanzenumgebungen, Azure dynamische Sitzungen.

Diagramm: Flussdiagramm mit dem beschriebenen Prozess.

**Vorteile:**✅ Vollständige Isolation | ✅ Einfache Sicherheit | ✅ Einfache Skalierung

Muster 2: gemeinsam genutzter CLI-Server (ressourceneffizient)

Am besten geeignet für: Interne Tools, vertrauenswürdige Umgebungen, ressourcenbeschränkte Setups.

Diagramm: Flussdiagramm mit dem beschriebenen Prozess.

Anforderungen:

  • ⚠️ Eindeutige Sitzungs-IDs pro Benutzer
  • ⚠️ Zugriffssteuerung auf Anwendungsebene
  • ⚠️ Sitzungs-ID-Überprüfung vor Vorgängen
// Application-level access control for shared CLI
async function resumeSessionWithAuth(
  client: CopilotClient,
  sessionId: string,
  currentUserId: string
): Promise<Session> {
  // Parse user from session ID
  const [sessionUserId] = sessionId.split("-");
  
  if (sessionUserId !== currentUserId) {
    throw new Error("Access denied: session belongs to another user");
  }
  
  return client.resumeSession(sessionId);
}

dynamische Sitzungen Azure

Für Serverlose/Containerbereitstellungen, bei denen Container neu gestartet oder migriert werden können:

Persistenten Speicher einbinden

Das Sitzungsstatusverzeichnis muss an beständigen Speicher bereitgestellt werden:

# Azure Container Instance example
containers:
  - name: copilot-agent
    image: my-agent:latest
    volumeMounts:
      - name: session-storage
        mountPath: /home/app/.copilot/session-state

volumes:
  - name: session-storage
    azureFile:
      shareName: copilot-sessions
      storageAccountName: myaccount

Diagramm: Flussdiagramm mit dem beschriebenen Prozess.

Die Sitzung bleibt auch nach Container-Neustarts erhalten!

Fortlaufende Sitzungen für langandauernde Workflows

Aktivieren Sie für Workflows, die Kontextbeschränkungen überschreiten könnten, dauerhafte Sitzungen mit automatischer Datenkomprimierung.

const session = await client.createSession({
  sessionId: "long-workflow-123",
  infiniteSessions: {
    enabled: true,
    backgroundCompactionThreshold: 0.80,  // Start compaction at 80% context
    bufferExhaustionThreshold: 0.95,      // Block at 95% if needed
  },
});

Hinweis

Schwellenwerte sind Kontextauslastungsverhältnisse (0,0-1,0), keine absolute Tokenanzahl. Weitere Einzelheiten finden Sie unter SDK- und CLI-Kompatibilität.

Einschränkungen und Überlegungen

EinschränkungDescriptionAbschwächung
BYOK-Erneute AuthentifizierungAPI-Schlüssel werden nicht beibehaltenSpeichern von Schlüsseln in Ihrem Secret Manager; Bereitstellung bei Wiederaufnahme
Schreibbarer Speicher~/.copilot/session-state/ muss schreibbar seinBereitstellen persistenter Volumes in Containern
Keine SitzungssperreGleichzeitiger Zugriff auf dieselbe Sitzung ist nicht definiertImplementieren der Sperrung oder Warteschlange auf Anwendungsebene
Der Toolstatus wurde nicht beibehalten.Der Status des In-Memory-Tools geht verloren.Entwerfen von Tools, die zustandslos sind oder ihren eigenen Status beibehalten

Verwaltung gleichzeitigen Zugriffs

Das SDK bietet keine integrierte Sitzungssperre. Wenn mehrere Clients möglicherweise auf dieselbe Sitzung zugreifen:

// Option 1: Application-level locking with Redis
import Redis from "ioredis";

const redis = new Redis();

async function withSessionLock<T>(
  sessionId: string,
  fn: () => Promise<T>
): Promise<T> {
  const lockKey = `session-lock:${sessionId}`;
  const acquired = await redis.set(lockKey, "locked", "NX", "EX", 300);
  
  if (!acquired) {
    throw new Error("Session is in use by another client");
  }
  
  try {
    return await fn();
  } finally {
    await redis.del(lockKey);
  }
}

// Usage
await withSessionLock("user-123-task-456", async () => {
  const session = await client.resumeSession("user-123-task-456");
  await session.sendAndWait({ prompt: "Continue the task" });
});

Zusammenfassung

FunktionVerwendung
Reaktivierbare Sitzung erstellenBereitstellung eines eigenen sessionId
Sitzung fortsetzenclient.resumeSession(sessionId)
BYOK fortsetzenKonfiguration erneut bereitstellen provider
Sitzungen auflistenclient.listSessions(filter?)
Verbindung mit der aktiven Sitzung trennensession.disconnect()— gibt Speicherressourcen frei; Sitzungsdaten auf dem Datenträger werden für die Wiederaufnahme beibehalten.
Sitzung dauerhaft löschenclient.deleteSession(sessionId)— entfernt dauerhaft alle Sitzungsdaten vom Datenträger; Kann nicht fortgesetzt werden
Containerisierte Bereitstellung~/.copilot/session-state/ in persistenten Storage mounten

Nächste Schritte