{"meta":{"title":"Reprise de session et persistance","intro":"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.","product":"GitHub Copilot","breadcrumbs":[{"href":"/fr/copilot","title":"GitHub Copilot"},{"href":"/fr/copilot/how-tos","title":"Procédures"},{"href":"/fr/copilot/how-tos/copilot-sdk","title":"Kit de développement logiciel (SDK) Copilot"},{"href":"/fr/copilot/how-tos/copilot-sdk/features","title":"Fonctionnalités"},{"href":"/fr/copilot/how-tos/copilot-sdk/features/session-persistence","title":"Persistance de session"}],"documentType":"article"},"body":"# Reprise de session et persistance\n\nCe 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.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n## Fonctionnement des sessions\n\nLorsque 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.\n\n![Diagramme : Organigramme montrant le processus décrit.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-0.png)\n\n| State                 | Que se passe-t-il ?                                    |\n| --------------------- | ------------------------------------------------------ |\n| **Créer**             |                                                        |\n| `session_id` Attribué |                                                        |\n| **Active**            | Envoyer des invites, des appels d’outils, des réponses |\n| **suspendu**          | État enregistré sur le disque                          |\n| **Resume**            | État chargé à partir du disque                         |\n\n## Démarrage rapide : création d’une session pouvant être reprise\n\nLa 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.\n\n### TypeScript\n\n```typescript\nimport { CopilotClient } from \"@github/copilot-sdk\";\n\nconst client = new CopilotClient();\n\n// Create a session with a meaningful ID\nconst session = await client.createSession({\n  sessionId: \"user-123-task-456\",\n  model: \"gpt-5.2-codex\",\n});\n\n// Do some work...\nawait session.sendAndWait({ prompt: \"Analyze my codebase\" });\n\n// Session state is automatically persisted\n// You can safely close the client\n```\n\n### Python\n\n```python\nfrom copilot import CopilotClient\nfrom copilot.session import PermissionHandler\n\nclient = CopilotClient()\nawait client.start()\n\n# Create a session with a meaningful ID\nsession = await client.create_session(on_permission_request=PermissionHandler.approve_all, model=\"gpt-5.2-codex\", session_id=\"user-123-task-456\")\n\n# Do some work...\nawait session.send_and_wait(\"Analyze my codebase\")\n\n# Session state is automatically persisted\n```\n\n### Allez\n\n```golang\nctx := context.Background()\nclient := copilot.NewClient(nil)\n\n// Create a session with a meaningful ID\nsession, _ := client.CreateSession(ctx, &copilot.SessionConfig{\n    SessionID: \"user-123-task-456\",\n    Model:     \"gpt-5.2-codex\",\n})\n\n// Do some work...\nsession.SendAndWait(ctx, copilot.MessageOptions{Prompt: \"Analyze my codebase\"})\n\n// Session state is automatically persisted\n```\n\n### C# (.NET)\n\n```csharp\nusing GitHub.Copilot;\n\nvar client = new CopilotClient();\n\n// Create a session with a meaningful ID\nvar session = await client.CreateSessionAsync(new SessionConfig\n{\n    SessionId = \"user-123-task-456\",\n    Model = \"gpt-5.2-codex\",\n});\n\n// Do some work...\nawait session.SendAndWaitAsync(new MessageOptions { Prompt = \"Analyze my codebase\" });\n\n// Session state is automatically persisted\n```\n\n## Reprise d’une session\n\nPlus tard, minutes, heures ou même jours, vous pouvez reprendre la session à partir de l’endroit où vous vous êtes arrêté.\n\n![Diagramme : Organigramme montrant le processus décrit.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-1.png)\n\n### TypeScript\n\n```typescript\n// Resume from a different client instance (or after restart)\nconst session = await client.resumeSession(\"user-123-task-456\");\n\n// Continue where you left off\nawait session.sendAndWait({ prompt: \"What did we discuss earlier?\" });\n```\n\n### Python\n\n```python\n# Resume from a different client instance (or after restart)\nsession = await client.resume_session(\"user-123-task-456\", on_permission_request=PermissionHandler.approve_all)\n\n# Continue where you left off\nawait session.send_and_wait(\"What did we discuss earlier?\")\n```\n\n### Allez\n\n```golang\nctx := context.Background()\n\n// Resume from a different client instance (or after restart)\nsession, _ := client.ResumeSession(ctx, \"user-123-task-456\", nil)\n\n// Continue where you left off\nsession.SendAndWait(ctx, copilot.MessageOptions{Prompt: \"What did we discuss earlier?\"})\n```\n\n### C# (.NET)\n\n```csharp\n// Resume from a different client instance (or after restart)\nvar session = await client.ResumeSessionAsync(\"user-123-task-456\");\n\n// Continue where you left off\nawait session.SendAndWaitAsync(new MessageOptions { Prompt = \"What did we discuss earlier?\" });\n```\n\n## Options de reprise\n\nLors 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.\n\n| Option             | Description                                                                                |\n| ------------------ | ------------------------------------------------------------------------------------------ |\n| `model`            | Modifier le modèle de la session reprise                                                   |\n| `systemMessage`    | Remplacer ou étendre l’invite système                                                      |\n| `availableTools`   | Restreindre les outils disponibles                                                         |\n| `excludedTools`    | Désactiver des outils spécifiques                                                          |\n| `provider`         | Fournir à nouveau des informations d’identification BYOK (requises pour les sessions BYOK) |\n| `reasoningEffort`  | Ajuster le niveau d’effort de raisonnement                                                 |\n| `streaming`        | Activer/désactiver les réponses de diffusion en continu                                    |\n| `workingDirectory` | Modifier le répertoire de travail                                                          |\n| `configDir`        | Remplacer le répertoire de configuration                                                   |\n| `mcpServers`       | Configurer les serveurs MCP                                                                |\n| `customAgents`     | Configurer des agents personnalisés                                                        |\n| `agent`            | Pré-sélection d’un agent personnalisé par nom                                              |\n| `skillDirectories` | Répertoires à partir duquel charger des compétences                                        |\n| `disabledSkills`   | Compétences à désactiver                                                                   |\n| `infiniteSessions` | Configurer le comportement de session infinie                                              |\n\n### Exemple : changement de modèle à la reprise\n\n```typescript\n// Resume with a different model\nconst session = await client.resumeSession(\"user-123-task-456\", {\n  model: \"claude-sonnet-4\",  // Switch to a different model\n  reasoningEffort: \"high\",   // Increase reasoning effort\n});\n```\n\n## Utilisation de BYOK (apportez votre propre clé) avec des sessions reprises\n\nLorsque 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é.\n\n```typescript\n// Original session with BYOK\nconst session = await client.createSession({\n  sessionId: \"user-123-task-456\",\n  model: \"gpt-5.2-codex\",\n  provider: {\n    type: \"azure\",\n    endpoint: \"https://my-resource.openai.azure.com\",\n    apiKey: process.env.AZURE_OPENAI_KEY,\n    deploymentId: \"my-gpt-deployment\",\n  },\n});\n\n// When resuming, you MUST re-provide the provider config\nconst resumed = await client.resumeSession(\"user-123-task-456\", {\n  provider: {\n    type: \"azure\",\n    endpoint: \"https://my-resource.openai.azure.com\",\n    apiKey: process.env.AZURE_OPENAI_KEY,  // Required again\n    deploymentId: \"my-gpt-deployment\",\n  },\n});\n```\n\n## Qu’est-ce qui est conservé ?\n\nL’état de session est enregistré dans `~/.copilot/session-state/{sessionId}/`:\n\n```text\n~/.copilot/session-state/\n└── user-123-task-456/\n    ├── checkpoints/           # Conversation history snapshots\n    │   ├── 001.json          # Initial state\n    │   ├── 002.json          # After first interaction\n    │   └── ...               # Incremental checkpoints\n    ├── plan.md               # Agent's planning state (if any)\n    └── files/                # Session artifacts\n        ├── analysis.md       # Files the agent created\n        └── notes.txt         # Working documents\n```\n\n| Data                             | Persisté?                         | Remarques |\n| -------------------------------- | --------------------------------- | --------- |\n| Historique des conversations     |                                   |           |\n| ✅ Oui                            | Fil de message complet            |           |\n| Résultats des appels d’outil     |                                   |           |\n| ✅ Oui                            | Mis en cache pour le contexte     |           |\n| État de planification de l’agent |                                   |           |\n| ✅ Oui                            | Fichier `plan.md`                 |           |\n| Artefacts de session             |                                   |           |\n| ✅ Oui                            | Dans `files/` le répertoire       |           |\n| Clés fournisseur/API             |                                   |           |\n| ❌ Non                            | Sécurité : doit re-fournir        |           |\n| État de l’outil en mémoire       |                                   |           |\n| ❌ Non                            | Les outils doivent être sans état |           |\n\n## Bonnes pratiques relatives à l’ID de session\n\nChoisissez les ID de session qui encodent la propriété et l’objectif. Cela facilite beaucoup l’audit et le nettoyage.\n\n| Pattern                         | Example                                                  | Cas d’usage |\n| ------------------------------- | -------------------------------------------------------- | ----------- |\n| ❌                               |                                                          |             |\n| `abc123`                        |                                                          |             |\n| ID aléatoires                   | Difficile à auditer, aucune information sur la propriété |             |\n| ✅                               |                                                          |             |\n| `user-{userId}-{taskId}`        |                                                          |             |\n| `user-alice-pr-review-42`       | Applications multi-utilisateurs                          |             |\n| ✅                               |                                                          |             |\n| `tenant-{tenantId}-{workflow}`  |                                                          |             |\n| `tenant-acme-onboarding`        | SaaS multilocataire                                      |             |\n| ✅                               |                                                          |             |\n| `{userId}-{taskId}-{timestamp}` |                                                          |             |\n| `alice-deploy-1706932800`       | Nettoyage basé sur le temps                              |             |\n\n**Avantages des ID structurés :**\n\n* Simple à auditer : « Afficher toutes les sessions pour l’utilisateur alice »\n* Nettoyer facilement : « Supprimer toutes les sessions antérieures à X »\n* Contrôle d’accès naturel : Analyser l’ID utilisateur à partir de l’ID de session\n\n### Exemple : génération d’ID de session\n\n```typescript\nfunction createSessionId(userId: string, taskType: string): string {\n  const timestamp = Date.now();\n  return `${userId}-${taskType}-${timestamp}`;\n}\n\nconst sessionId = createSessionId(\"alice\", \"code-review\");\n// → \"alice-code-review-1706932800000\"\n```\n\n```python\nimport time\n\ndef create_session_id(user_id: str, task_type: str) -> str:\n    timestamp = int(time.time())\n    return f\"{user_id}-{task_type}-{timestamp}\"\n\nsession_id = create_session_id(\"alice\", \"code-review\")\n# → \"alice-code-review-1706932800\"\n```\n\n## Gestion du cycle de vie des sessions\n\n### Liste des sessions actives\n\n```typescript\n// List all sessions\nconst sessions = await client.listSessions();\nconsole.log(`Found ${sessions.length} sessions`);\n\nfor (const session of sessions) {\n  console.log(`- ${session.sessionId} (created: ${session.createdAt})`);\n}\n\n// Filter sessions by repository\nconst repoSessions = await client.listSessions({ repository: \"owner/repo\" });\n```\n\n### Nettoyage des anciennes sessions\n\n```typescript\nasync function cleanupExpiredSessions(maxAgeMs: number) {\n  const sessions = await client.listSessions();\n  const now = Date.now();\n  \n  for (const session of sessions) {\n    const age = now - new Date(session.createdAt).getTime();\n    if (age > maxAgeMs) {\n      await client.deleteSession(session.sessionId);\n      console.log(`Deleted expired session: ${session.sessionId}`);\n    }\n  }\n}\n\n// Clean up sessions older than 24 hours\nawait cleanupExpiredSessions(24 * 60 * 60 * 1000);\n```\n\n### Déconnexion d’une session (`disconnect`)\n\nLorsqu’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 :\n\n```typescript\ntry {\n  // Do work...\n  await session.sendAndWait({ prompt: \"Complete the task\" });\n  \n  // Task complete — release in-memory resources (session can be resumed later)\n  await session.disconnect();\n} catch (error) {\n  // Clean up even on error\n  await session.disconnect();\n  throw error;\n}\n```\n\nChaque KIT SDK fournit également des modèles de nettoyage automatique idiomatiques :\n\n| Language                              | Pattern                                                                             | Example                                                              |\n| ------------------------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------- |\n| **TypeScript**                        | `Symbol.asyncDispose`                                                               | `await using session = await client.createSession(config);`          |\n| **Python**                            |                                                                                     |                                                                      |\n| `async with` gestionnaire de contexte | `async with await client.create_session(on_permission_request=handler) as session:` |                                                                      |\n| **C#**                                | `IAsyncDisposable`                                                                  | `await using var session = await client.CreateSessionAsync(config);` |\n| **Go**                                | `defer`                                                                             | `defer session.Disconnect()`                                         |\n\n> \\[!NOTE]\n> `destroy()` est déconseillé au profit de `disconnect()`. Le code existant utilise `destroy()` continuera de fonctionner, mais doit être migré.\n\n### Suppression définitive d’une session (`deleteSession`)\n\nPour 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 :\n\n```typescript\n// Permanently remove session data\nawait client.deleteSession(\"user-123-task-456\");\n```\n\n> **`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.\n\n## Nettoyage automatique : temporisation d'inactivité\n\nPar 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`:\n\n```typescript\nconst client = new CopilotClient({\n  sessionIdleTimeoutSeconds: 30 * 60, // 30 minutes\n});\n```\n\nLorsqu’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.\n\n> \\[!NOTE]\n> 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.\n\n![Diagramme : Organigramme montrant le processus décrit.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-2.png)\n\nLes 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.\n\nSurveillez les événements d’inactivité pour réagir à l’inactivité de la session :\n\n```typescript\nsession.on(\"session.idle\", (event) => {\n  console.log(`Session idle for ${event.idleDurationMs}ms`);\n});\n```\n\n## Modèles de déploiement\n\n### Modèle 1 : un serveur CLI par utilisateur (recommandé)\n\nIdéal pour : isolation forte, environnements multilocataires, Azure sessions dynamiques.\n\n![Diagramme : Organigramme montrant le processus décrit.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-3.png)\n\n\\*\\*Avantages:\\*\\*✅ Isolation complète | ✅ Sécurité simple | ✅ Mise à l’échelle simple\n\n### Modèle 2 : serveur CLI partagé (ressource efficace)\n\nIdéal pour : outils internes, environnements approuvés, configurations contraintes de ressources.\n\n![Diagramme : Organigramme montrant le processus décrit.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-4.png)\n\n**Exigences:**\n\n* ⚠️ ID de session uniques par utilisateur\n* ⚠️ Contrôle d’accès au niveau de l’application\n* ⚠️ Validation de l’ID de session avant les opérations\n\n```typescript\n// Application-level access control for shared CLI\nasync function resumeSessionWithAuth(\n  client: CopilotClient,\n  sessionId: string,\n  currentUserId: string\n): Promise<Session> {\n  // Parse user from session ID\n  const [sessionUserId] = sessionId.split(\"-\");\n  \n  if (sessionUserId !== currentUserId) {\n    throw new Error(\"Access denied: session belongs to another user\");\n  }\n  \n  return client.resumeSession(sessionId);\n}\n```\n\n## sessions dynamiques Azure\n\nPour les déploiements serverless/conteneur où les conteneurs peuvent redémarrer ou migrer :\n\n### Monter un stockage persistant\n\nLe répertoire d’état de session doit être monté sur un stockage persistant :\n\n```yaml\n# Azure Container Instance example\ncontainers:\n  - name: copilot-agent\n    image: my-agent:latest\n    volumeMounts:\n      - name: session-storage\n        mountPath: /home/app/.copilot/session-state\n\nvolumes:\n  - name: session-storage\n    azureFile:\n      shareName: copilot-sessions\n      storageAccountName: myaccount\n```\n\n![Diagramme : Organigramme montrant le processus décrit.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-5.png)\n\n**La session survit aux redémarrages du conteneur !**\n\n## Sessions infinies pour les workflows de longue durée\n\nPour les flux de travail qui peuvent dépasser les limites de contexte, activez des sessions infinies avec compactage automatique :\n\n```typescript\nconst session = await client.createSession({\n  sessionId: \"long-workflow-123\",\n  infiniteSessions: {\n    enabled: true,\n    backgroundCompactionThreshold: 0.80,  // Start compaction at 80% context\n    bufferExhaustionThreshold: 0.95,      // Block at 95% if needed\n  },\n});\n```\n\n> \\[!NOTE]\n> 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](/fr/copilot/how-tos/copilot-sdk/troubleshooting/compatibility) .\n\n## Limitations et considérations\n\n| Limitation                                                   | Description                                          | Atténuation                                                                             |\n| ------------------------------------------------------------ | ---------------------------------------------------- | --------------------------------------------------------------------------------------- |\n| **Ré-authentification BYOK**                                 | Les clés API ne sont pas persistantes                | Stockez les clés dans votre gestionnaire de secrets ; fournissez-les lors de la reprise |\n| **Stockage accessible en écriture**                          |                                                      |                                                                                         |\n| `~/.copilot/session-state/` doit être accessible en écriture | Monter un volume persistant dans des conteneurs      |                                                                                         |\n| **Aucun verrouillage de session**                            | L’accès simultané à la même session n’est pas défini | Implémenter le verrouillage ou la file d’attente au niveau de l’application             |\n| **État de l’outil non persistant**                           | L’état de l’outil en mémoire est perdu               | Conception d’outils qui soient sans état ou conservent leur propre état                 |\n\n### Gestion de l’accès simultané\n\nLe 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 :\n\n```typescript\n// Option 1: Application-level locking with Redis\nimport Redis from \"ioredis\";\n\nconst redis = new Redis();\n\nasync function withSessionLock<T>(\n  sessionId: string,\n  fn: () => Promise<T>\n): Promise<T> {\n  const lockKey = `session-lock:${sessionId}`;\n  const acquired = await redis.set(lockKey, \"locked\", \"NX\", \"EX\", 300);\n  \n  if (!acquired) {\n    throw new Error(\"Session is in use by another client\");\n  }\n  \n  try {\n    return await fn();\n  } finally {\n    await redis.del(lockKey);\n  }\n}\n\n// Usage\nawait withSessionLock(\"user-123-task-456\", async () => {\n  const session = await client.resumeSession(\"user-123-task-456\");\n  await session.sendAndWait({ prompt: \"Continue the task\" });\n});\n```\n\n## Résumé\n\n| Fonctionnalité                                                                                                                  | Utilisation                                                    |\n| ------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |\n| **Créer une session pouvant être reprise**                                                                                      | Fournissez vos propres `sessionId`                             |\n| **Reprendre la session**                                                                                                        | `client.resumeSession(sessionId)`                              |\n| **Reprise BYOK**                                                                                                                | Re-fournir la `provider` configuration                         |\n| **Répertorier les sessions**                                                                                                    | `client.listSessions(filter?)`                                 |\n| **Se déconnecter de la session active**                                                                                         |                                                                |\n| `session.disconnect()`— libère des ressources en mémoire ; les données de session sur le disque sont conservées pour la reprise |                                                                |\n| **Supprimer une session définitivement**                                                                                        |                                                                |\n| `client.deleteSession(sessionId)`: supprime définitivement toutes les données de session du disque ; ne peut pas être repris    |                                                                |\n| **Déploiement en conteneur**                                                                                                    | Monter `~/.copilot/session-state/` dans un stockage persistant |\n\n## Étapes suivantes\n\n* [Hooks de session](/fr/copilot/how-tos/copilot-sdk/hooks/hooks-overview) - Personnaliser le comportement de session avec des hooks\n* [Compatibilité du Kit de développement logiciel (SDK) et de l’interface](/fr/copilot/how-tos/copilot-sdk/troubleshooting/compatibility) - Comparaison des fonctionnalités sdk et CLI\n* [Guide de débogage](/fr/copilot/how-tos/copilot-sdk/troubleshooting/debugging) - Résoudre les problèmes de session"}