Skip to main content
Skip to content

Reprise de session et persistance

Ce guide vous guide tout au long des fonctionnalités de persistance de session du Kit de développement logiciel (SDK) : comment suspendre le travail, le reprendre ultérieurement et gérer les sessions dans les environnements de production.

Fonctionnement des sessions

Lorsque vous créez une session, l’interface cli Copilot gère l’historique des conversations, l’état de l’outil et le contexte de planification. Par défaut, cet état vit en mémoire et disparaît lorsque la session se termine. Une fois la persistance activée, vous pouvez reprendre des sessions entre les redémarrages, les migrations de conteneurs ou même différentes instances clientes.

Diagramme : Organigramme montrant le processus décrit.

StateQue se passe-t-il ?
Créersession_id Attribué
ActiveEnvoyer des invites, des appels d’outils, des réponses
suspenduÉtat enregistré sur le disque
ResumeÉtat chargé à partir du disque

Démarrage rapide : création d’une session pouvant être reprise

La clé pour permettre la reprise des sessions consiste à fournir votre propre session_id. Sans un, le SDK génère un ID aléatoire et la session ne peut pas être reprise ultérieurement.

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

Allez

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

Reprise d’une session

Plus tard, minutes, heures ou même jours, vous pouvez reprendre la session à partir de l’endroit où vous vous êtes arrêté.

Permissions mémorisées dans un système de fichiers de session

Lorsque vous configurez un fournisseur personnalisé sessionFs , les choix d’autorisations durables appartenant au runtime utilisent le stockage du fournisseur plutôt que la configuration de l’hôte d’exécution. Les fichiers se trouvent sous le sessionStatePath du fournisseur et conservent leurs formats existants :

  • permissions.json : une locationscarte de premier niveau conservant les champs allowed_directories et tool_approvals existants
  • settings.json: Niveau principal allowedUrls pour approve-permanently les approbations d’URL et sandbox pour les préférences de bac à sable enregistrées
  • config.json: niveau supérieur trustedFolders pour la confiance des dossiers mémorisés et sandboxOnboardingShown pour le message de bac à sable pour la première activation

Les clés d’emplacement sont des chemins d’accès de répertoire de fournisseur normalisés, tels que /workspace, sans préfixe ajouté. Le runtime les résout lexicalement à l’aide de conventions de chemin d’accès du fournisseur, sans inspecter le système de fichiers hôte ou découvrir les dépôts Git hôtes. Une approbation enregistrée pour /workspace n’est pas automatiquement sélectionnée lorsque le répertoire de travail est /workspace/sub.

L’approbation des dossiers prise en charge par le fournisseur utilise également des chemins lexicaux : un dossier approuvé couvre ce dossier lui-même et ses descendants, et non les arborescences de travail Git liées à d’autres chemins. Marquez explicitement comme fiables ces chemins d’accès de worktree.

Il n’existe aucune partition d’ID de session supplémentaire à l’intérieur de ces fichiers. Les sessions qui accèdent aux mêmes fichiers de stockage partagent des choix mémorisés. Utilisez des espaces de noms de fournisseur distincts lorsque les sessions ou les locataires ne doivent pas partager d’autorisations. Avec un espace de noms par session, les choix permanents survivent aux reprises de cette session, mais ne passent pas automatiquement aux nouvelles sessions. Pour restaurer les choix persistants d’une session lors de la reprise, reconnectez-la au même espace de noms.

Les mises à jour de consentement sont sérialisées par point de terminaison de fournisseur et par fichier au sein d’un processus d’exécution. Les points de terminaison distincts ne se bloquent pas les uns les autres. Si différents points de terminaison de fournisseur ou processus d’exécution partagent des fichiers de stockage, l’application doit coordonner les mises à jour simultanées ; le runtime ne peut pas déduire que ces fichiers sont partagés.

Ces opérations n’importent jamais, ne mettent jamais à jour et ne se rabattent jamais sur les permissions-config.json, settings.json ou config.json de l’hôte, y compris lorsque les opérations de lecture ou d’écriture du fournisseur échouent. Les fichiers au format existant fournis par le fournisseur sont lus directement.

Comme pour la configuration de l’hôte, les autorisations d’URL sont lues uniquement à partir de settings.json. Un champ hérité allowedUrls dans config.json est ignoré ; config.json reste le fichier d’état global pour l’approbation de dossiers mémorisé et le marqueur d’intégration du bac à sable.

Le routage du stockage ne modifie pas les durées de vie des autorisations, la priorité par déni d’URL ou le comportement de stratégie de session. Approuver une fois et approuver pour la session ne deviennent pas des autorisations permanentes.

Les préférences de sandbox enregistrées sont restaurées lors de la création et de la reprise. Les appels de SDK options.update explicites ultérieurement peuvent modifier la configuration du bac à sable en direct sans réécrire la préférence enregistrée.

Sans sessionFs, les applications SDK dans les modes empty et copilot-cli conservent la persistance existante soutenue par l’hôte. Cela inclut le comportement existant dans lequel le consentement d’URL permanent enregistre les paramètres de l’hôte et accorde l’accès dans la session en direct, mais une nouvelle session SDK ne charge pas automatiquement la liste d’autorisation de l’URL de l’hôte.

Consultez Multilocataire et déploiements de serveurs pour connaître les responsabilités d’isolation du fournisseur.

Récupération du relevé

L’option resume allowTranscriptRecovery contrôle la récupération lorsque le runtime charge une transcription à partir du stockage. La valeur par défaut est true dans tous les modes. Avec false, une charge qui rejetterait les enregistrements endommagés ou déplacerait session.start échoue avec l’erreur JSON-RPC -32075 sans réécrire la transcription. Un enregistrement final intact sans saut de ligne est accepté.

Les enregistrements ignorés pour la compatibilité ascendante sont toujours comptabilisés lors de la vérification de l’ordre persistant. Si de tels enregistrements précèdent session.start, la récupération doit déplacer l’enregistrement de début au-delà de ceux-ci. Une transcription contenant uniquement les enregistrements ignorés n’est pas vide et ne peut pas être récupérée sans session.start valide.

Lorsque la récupération est autorisée, la session retournée expose transcriptRecovery, y compris les numéros de ligne non valides, si session.start a été déplacé et un chemin de sauvegarde planifié, exact à l’octet. Le chargement à lui seul n’écrit pas cette sauvegarde ; l’écriture en ajout durable suivante effectue la réparation et la sauvegarde.

Remarque

Cette option s’applique à une nouvelle charge de transcription, et non à la durée de vie d’une session. La reconnexion à une session qui réside déjà dans le runtime réutilise son historique en direct sans revalider le stockage ou rejeter la récupération autorisée par une reprise antérieure. Le rapport de récupération décrit le chargement qui a effectué la récupération, pas toutes les reconnexions suivantes.

Diagramme : Organigramme montrant le processus décrit.

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?")

Allez

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?" });

Options de reprise

Lors de la reprise d’une session, vous pouvez éventuellement reconfigurer de nombreux paramètres. Cela est utile lorsque vous devez modifier le modèle, mettre à jour les configurations de l’outil ou modifier le comportement.

OptionDescription
modelModifier le modèle de la session reprise
systemMessageRemplacer ou étendre l’invite système
availableToolsRestreindre les outils disponibles
excludedToolsDésactiver des outils spécifiques
providerFournir à nouveau des informations d’identification BYOK (requises pour les sessions BYOK)
capi.autoTierRemplacer la préférence de routage automatique persistante
capi.enableWebSocketResponsesChoisir le transport de l’API Responses pour la session reprise
reasoningEffortAjuster le niveau d’effort de raisonnement
streamingActiver/désactiver les réponses de diffusion en continu
workingDirectoryModifier le répertoire de travail
configDirRemplacer le répertoire de configuration
mcpServersConfigurer les serveurs MCP
customAgentsConfigurer des agents personnalisés
agentPré-sélection d’un agent personnalisé par nom
skillDirectoriesRépertoires à partir duquel charger des compétences
disabledSkillsCompétences à désactiver
infiniteSessionsConfigurer le comportement de session infinie

Conservation automatique du niveau

Avec model: "auto", le paramètre facultatif capi.autoTier sélectionne une préférence de routage automatique : efficiency, balance, intelligenceou fast. Dans Python, utilisez capi={"auto_tier": "balance"}. Ce paramètre s’applique au routage automatique V2 ; Les requêtes automatiques V1 sont inchangées.

Lorsque la fonctionnalité de désactivation DYNAMIC_AUTO_TIERS par défaut du runtime est activée, le RPC de la session model.list retourne également des métadonnées facultatives auto à partir du point de terminaison du /meta fournisseur. Utilisez les descripteurs type: "auto" activés pour découvrir des identificateurs de niveau pris en charge supplémentaires, leurs noms d’affichage, descriptions et classement. Les méthodes de sélection existantes et les champs JSON acceptent ces identificateurs. Un échec de découverte ne bascule pas sur /models, et une réponse réussie sans métadonnées auto ne fournit aucun niveau Auto sélectionnable.

Pour remplir un sélecteur de modèle avant l’existence d’une session, activez DYNAMIC_AUTO_TIERS dans l’environnement d’exécution (par exemple, l’option client env). Le RPC au niveau models.list du serveur (client.rpc.models.list() dans Node.js) retourne ensuite les mêmes métadonnées auto à partir de la même réponse /meta, avec le même comportement sans solution de repli. La liste au niveau du serveur lit l’indicateur résolu au démarrage, et non les indicateurs de fonctionnalités par session ou les affectations d’expérience. Définissez donc l’indicateur là où vous lancez le runtime. Avec l’indicateur désactivé, models.list reste inchangé et omet auto.

Traitez les identificateurs de niveau comme des valeurs extensibles, et non comme une énumération fermée. Les valeurs nommées existantes restent disponibles ; pour des identificateurs supplémentaires, utilisez des chaînes dans Node.js et Python, AutoTier("premium-v2") dans Go, new AutoTier("premium-v2") dans .NET, AutoTier::Custom dans Rust ou AutoTier.fromValue dans Java. Le defaultTier du fournisseur décrit son routage par défaut sans créer de préférence de SDK validée.

Si un niveau persistant est supprimé ou désactivé, la reprise conserve la préférence explicite plutôt que de la remplacer par la valeur par défaut du fournisseur. Sélectionnez un remplacement disponible avant d’activer le routage automatique.

L’interface CLI conserve également les préférences dérivées des paramètres au démarrage, même lorsqu’un niveau n’est pas disponible ou si la découverte dynamique est désactivée. Vous pouvez ensuite sélectionner un modèle de remplacement dans le sélecteur de modèles. Les préférences de création et de reprise explicites du Kit de développement logiciel (SDK) sont toujours validées avant la réussite de l’opération, et l’activation automatique valide toujours la disponibilité par rapport au mode de découverte résolu.

Lorsqu’une demande de création ou de reprise inclut expAssignments, le runtime installe ces affectations avant de valider une préférence Auto explicite. La validation, la découverte et l’activation utilisent la même décision de fonctionnalité résolue.

fast est un préréglage de latence réservé aux intégrateurs, et non une préférence native du produit GitHub Copilot. Fast n’est pas validé par rapport au catalogue des /meta niveaux lors de la configuration d’une session. Le Kit de développement logiciel (SDK) ne détermine pas l’éligibilité rapide, inspecte l’identité du client, le choisit comme valeur par défaut ou revient à un autre niveau lorsqu’un runtime ne le prend pas en charge. Un runtime plus ancien retourne son erreur native inchangée.

Le runtime conserve le niveau sélectionné. Les applications n’ont donc pas besoin de les renvoyer à chaque reprise :

  • Omettre le niveau lors de la création d’une session utilise le comportement de routage par défaut du runtime.
  • Une reprise à froid restaure le niveau persistant. Le fait de spécifier un niveau explicite écrase la valeur restaurée lors de la nouvelle activation.
  • Lors de la reprise d’une session déjà présente dans l’environnement d’exécution, l’omission du niveau conserve la sélection actuelle, et fournir le même niveau n’a aucun effet. Le fait de spécifier un niveau différent déclenche un basculement sécurisé que le runtime applique une fois la reprise effectuée avec succès ; il ne peut pas modifier un tour déjà en cours.
  • Les sessions plus anciennes sans niveau persistant conservent le comportement de routage par défaut.

La sélection de niveau n’est pas une opération de changement de modèle en direct. Le Kit de développement logiciel (SDK) transfère la préférence ; le runtime possède la persistance et la validation.

Les événements session.start et session.resume indiquent le niveau sélectionné dans le champ facultatif data.autoTier (data.auto_tier en Python). Lorsqu’aucun niveau n’est sélectionné, le champ est omis.

Changer le niveau Auto pendant une session

Appelez setAutoTier pour modifier la préférence de routage sur une session dynamique sans modifier le modèle sélectionné. Passez null (Python None, Go nil) pour revenir au routage automatique par défaut du fournisseur.

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

Le runtime n’applique pas immédiatement la préférence. Elle enregistre la requête et ne la confirme que lorsqu’un tour utilisateur ultérieur utilisant le modèle auto permet d’obtenir auprès du fournisseur un modèle exploitable. Un pending état confirme donc que la demande a été acceptée, et non qu’elle a pris effet. Seule la demande la plus récente survive : une nouvelle demande remplace toute demande antérieure qu’aucun tour n’a encore revendiqué.

Si une demande plus ancienne est toujours en cours de validation lorsqu’une demande de préférence plus récente ou une réinitialisation arrive, l’ancien appel échoue avec une erreur de requête supplantée au lieu de remplacer l’intention plus récente.

Surveillez les résultats par le biais de ces événements :

  • session.model_change lorsque la préférence est validée.
  • session.auto_tier_switch_failed quand ce n’est pas le cas. Cet événement est éphémère, donc l’environnement d’exécution ne l’enregistre ni ne le rejoue lors de la reprise. Son reason champ est l’un des suivants : policy_rejected, request_failed, setup_failed ou unsupported, et la préférence précédemment en vigueur reste active.

Vous pouvez également lire à tout moment l’état de référence via la méthode RPC model.getCurrent de la session, qui renvoie le autoTier validé, les pendingAutoTier non revendiqués, ainsi que les activatingAutoTier actuellement revendiqués par une activation en cours.

SDKModifier le niveauRevenir au routage par défaut du fournisseur
Node.JSsession.setAutoTier("balance")session.setAutoTier(null)
Pythonsession.set_auto_tier("balance")session.set_auto_tier(None)
Allezsession.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)

Pour sélectionner le modèle auto et sa préférence de routage en un seul appel, configurez plutôt le niveau sur le sélecteur de modèle. Le runtime rejette cette option lorsque le modèle est autre que auto.

SDKConfigurez un niveau à l’aide du commutateurRéinitialisation au routage par défaut du fournisseur
Node.JSsetModel("auto", { autoTier: "balance" })setModel("auto", { autoTier: null })
Pythonset_model("auto", auto_tier="balance")set_model("auto", auto_tier=None)
AllezSetModelOptions{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 et Rust expriment les trois états dans une seule valeur : Node.js et Python, car null/None il est distingué d’un argument omis et Rust, car AutoTierPreference::Reset il s’agit d’une variante distincte de la même option. Go, .NET et Java n’ont aucun moyen de distinguer « reset » de « unset » dans une valeur, de sorte qu’ils portent un indicateur de réinitialisation distinct. Omettre les deux signifie toujours « laisser la préférence actuelle seule ».

Transport des réponses lors de la reprise

Le paramètre facultatif capi.enableWebSocketResponses choisit le transport de l’API Réponses CAPI. Par défaut true, le transport WebSocket est utilisé chaque fois que le modèle sélectionné publie le ws:/responses point de terminaison. La définition de ce false paramètre revient au transport HTTP. Dans Python, utilisez capi={"enable_web_socket_responses": False}.

Fournissez-le lors de l’appel de reprise lorsque vous en avez besoin. Il vaut la peine de définir lorsque les connexions WebSocket échouent derrière un proxy et lorsqu’une session reprise signale 400 input item ID does not belong to this connection, qui est spécifique au transport WebSocket.

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

Définir cette valeur false équivaut à la COPILOT_CLI_DISABLE_WEBSOCKET_RESPONSES variable d’environnement, qui a la polarité opposée.

Exemple : changement de modèle à la reprise

// 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
});

Utilisation de BYOK (apportez votre propre clé) avec des sessions reprises

Lorsque vous utilisez vos propres clés API, vous devez fournir à nouveau la configuration du fournisseur lors de la reprise. Les clés API ne sont jamais conservées sur le disque pour des raisons de sécurité.

// 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",
  },
});

Qu’est-ce qui est conservé ?

L’état de session est enregistré dans ~/.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
DataPersisté?Remarques
Historique des conversations
✅ OuiFil de message complet
Résultats des appels d’outil
✅ OuiMis en cache pour le contexte
État de planification de l’agent
✅ OuiFichier plan.md
Artefacts de session
✅ OuiDans files/ le répertoire
Clés fournisseur/API
❌ NonSécurité : doit re-fournir
État de l’outil en mémoire
❌ NonLes outils doivent être sans état

Bonnes pratiques relatives à l’ID de session

Choisissez les ID de session qui encodent la propriété et l’objectif. Cela facilite beaucoup l’audit et le nettoyage.

PatternExampleCas d’usage
❌abc123ID aléatoiresDifficile à auditer, aucune information sur la propriété
✅user-{userId}-{taskId}user-alice-pr-review-42Applications multi-utilisateurs
✅tenant-{tenantId}-{workflow}tenant-acme-onboardingSaaS multilocataire
✅{userId}-{taskId}-{timestamp}alice-deploy-1706932800Nettoyage basé sur le temps

Avantages des ID structurés :

  • Simple à auditer : « Afficher toutes les sessions pour l’utilisateur alice »
  • Nettoyer facilement : « Supprimer toutes les sessions antérieures à X »
  • Contrôle d’accès naturel : Analyser l’ID utilisateur à partir de l’ID de session

Exemple : génération d’ID de session

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"

Gestion du cycle de vie des sessions

Liste des sessions actives

// 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" });

Nettoyage des anciennes sessions

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);

Déconnexion d’une session (disconnect)

Lorsqu’une tâche est terminée, déconnectez-vous de la session explicitement plutôt que d’attendre des délais d’expiration. Cette opération libère des ressources en mémoire, mais conserve les données de session sur le disque, de sorte que la session peut toujours être reprise ultérieurement :

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;
}

Chaque KIT SDK fournit également des modèles de nettoyage automatique idiomatiques :

LanguagePatternExample
TypeScriptSymbol.asyncDisposeawait using session = await client.createSession(config);
Pythonasync with gestionnaire de contexteasync with await client.create_session(on_permission_request=handler) as session:
C#IAsyncDisposableawait using var session = await client.CreateSessionAsync(config);
Godeferdefer session.Disconnect()

Remarque

destroy() est déconseillé au profit de disconnect(). Le code existant utilise destroy() continuera de fonctionner, mais doit être migré.

Suppression définitive d’une session (deleteSession)

Pour supprimer définitivement une session et toutes ses données du disque (historique des conversations, état de planification, artefacts), utilisez deleteSession. Cela est irréversible : la session ne peut pas être reprise après la suppression :

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

disconnect() vs deleteSession():disconnect() libère des ressources en mémoire, mais conserve les données de session sur le disque pour une reprise ultérieure. deleteSession() supprime définitivement tout, y compris les fichiers sur le disque.

Nettoyage automatique : temporisation d'inactivité

Par défaut, les sessions n’ont pas de délai d’inactivité et vivent indéfiniment jusqu’à ce qu’elles aient été explicitement déconnectées ou supprimées. Vous pouvez éventuellement configurer un délai d’inactivité à l’échelle du serveur via CopilotClientOptions.sessionIdleTimeoutSeconds:

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

Lorsqu’un délai d’expiration est configuré, les sessions sans activité pendant cette durée sont automatiquement nettoyées. Définissez sur 0 ou omettez pour désactiver.

Remarque

Cette option s’applique uniquement lorsque le Kit de développement logiciel (SDK) génère le processus d’exécution. Lors de la connexion à un serveur existant via cliUrl, la configuration du délai d’expiration du serveur s’applique.

Diagramme : Organigramme montrant le processus décrit.

Les sessions avec travail actif (commandes en cours d’exécution, assistants en arrière-plan) sont toujours protégées contre le nettoyage inactif, quel que soit le paramètre de délai d’expiration.

Surveillez les événements d’inactivité pour réagir à l’inactivité de la session :

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

Modèles de déploiement

Idéal pour : isolation forte, environnements multilocataires, Azure sessions dynamiques.

Diagramme : Organigramme montrant le processus décrit.

**Avantages:**✅ Isolation complète | ✅ Sécurité simple | ✅ Mise à l’échelle simple

Modèle 2 : serveur CLI partagé (ressource efficace)

Idéal pour : outils internes, environnements approuvés, configurations contraintes de ressources.

Diagramme : Organigramme montrant le processus décrit.

Exigences:

  • ⚠️ ID de session uniques par utilisateur
  • ⚠️ Contrôle d’accès au niveau de l’application
  • ⚠️ Validation de l’ID de session avant les opérations
// 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);
}

sessions dynamiques Azure

Pour les déploiements serverless/conteneur où les conteneurs peuvent redémarrer ou migrer :

Monter un stockage persistant

Le répertoire d’état de session doit être monté sur un stockage persistant :

# 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

Diagramme : Organigramme montrant le processus décrit.

La session survit aux redémarrages du conteneur !

Sessions infinies pour les workflows de longue durée

Pour les flux de travail qui peuvent dépasser les limites de contexte, activez des sessions infinies avec compactage automatique :

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
  },
});

Remarque

Les seuils sont des ratios d’utilisation du contexte (0,0-1,0), et non des nombres de jetons absolus. Pour plus d’informations, consultez autoTITLE .

Limitations et considérations

LimitationDescriptionAtténuation
Ré-authentification BYOKLes clés API ne sont pas persistantesStockez les clés dans votre gestionnaire de secrets ; fournissez-les lors de la reprise
Stockage accessible en écriture~/.copilot/session-state/ doit être accessible en écritureMonter un volume persistant dans des conteneurs
Aucun verrouillage de sessionL’accès simultané à la même session n’est pas définiImplémenter le verrouillage ou la file d’attente au niveau de l’application
État de l’outil non persistantL’état de l’outil en mémoire est perduConception d’outils qui soient sans état ou conservent leur propre état

Gestion de l’accès simultané

Le Kit de développement logiciel (SDK) ne fournit pas de verrouillage de session intégré. Si plusieurs clients peuvent accéder à la même session :

// 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" });
});

Résumé

FonctionnalitéUtilisation
Créer une session pouvant être repriseFournissez vos propres sessionId
Reprendre la sessionclient.resumeSession(sessionId)
Reprise BYOKRe-fournir la provider configuration
Répertorier les sessionsclient.listSessions(filter?)
Se déconnecter de la session activesession.disconnect()— libère des ressources en mémoire ; les données de session sur le disque sont conservées pour la reprise
Supprimer une session définitivementclient.deleteSession(sessionId): supprime définitivement toutes les données de session du disque ; ne peut pas être repris
Déploiement en conteneurMonter ~/.copilot/session-state/ dans un stockage persistant

Étapes suivantes