{"meta":{"title":"Reanudación y persistencia de sesión","intro":"Esta guía le guía a través de las funcionalidades de persistencia de sesión del SDK, cómo pausar el trabajo, reanudarlo más adelante y administrar sesiones en entornos de producción.","product":"GitHub Copilot","breadcrumbs":[{"href":"/es/enterprise-cloud@latest/copilot","title":"GitHub Copilot"},{"href":"/es/enterprise-cloud@latest/copilot/how-tos","title":"Procedimientos"},{"href":"/es/enterprise-cloud@latest/copilot/how-tos/copilot-sdk","title":"SDK de Copilot"},{"href":"/es/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features","title":"Características"},{"href":"/es/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/session-persistence","title":"Persistencia de sesión"}],"documentType":"article"},"body":"# Reanudación y persistencia de sesión\n\nEsta guía le guía a través de las funcionalidades de persistencia de sesión del SDK, cómo pausar el trabajo, reanudarlo más adelante y administrar sesiones en entornos de producción.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n## Cómo funcionan las sesiones\n\nAl crear una sesión, la CLI de Copilot mantiene el historial de conversaciones, el estado de la herramienta y el contexto de planificación. De forma predeterminada, este estado reside en la memoria y desaparece cuando finaliza la sesión. Con la persistencia habilitada, puede reanudar las sesiones entre reinicios, migraciones de contenedor o incluso instancias de cliente diferentes.\n\n![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-0.png)\n\n| Estado                | ¿Qué ocurre?                                       |\n| --------------------- | -------------------------------------------------- |\n| **Crear**             |                                                    |\n| `session_id` asignado |                                                    |\n| **Activo**            | Enviar avisos, llamadas a herramientas, respuestas |\n| **En pausa**          | Estado guardado en el disco                        |\n| **Resume**            | Estado cargado desde el disco                      |\n\n## Inicio rápido: creación de una sesión reanudable\n\nLa clave para las sesiones reanudables es proporcionar su propia `session_id`. Sin uno, el SDK genera un identificador aleatorio y la sesión no se puede reanudar más adelante.\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### Ir\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## Reanudación de una sesión\n\nMás tarde —minutos, horas o incluso días después— podrá reanudar la sesión desde donde la dejó.\n\n![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/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### Ir\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## Opciones de reanudación\n\nAl reanudar una sesión, puede volver a configurar muchas opciones de configuración. Esto resulta útil cuando necesita cambiar el modelo, actualizar configuraciones de herramientas o modificar el comportamiento.\n\n| Opción             | Description                                                                     |\n| ------------------ | ------------------------------------------------------------------------------- |\n| `model`            | Cambiar el modelo de la sesión reanudada                                        |\n| `systemMessage`    | Anular o ampliar el mensaje del sistema                                         |\n| `availableTools`   | Restringir qué herramientas están disponibles                                   |\n| `excludedTools`    | Deshabilitar herramientas específicas                                           |\n| `provider`         | Volver a proporcionar las credenciales BYOK (necesarias para las sesiones BYOK) |\n| `reasoningEffort`  | Ajuste del nivel de esfuerzo de razonamiento                                    |\n| `streaming`        | Habilitar o deshabilitar las respuestas de streaming                            |\n| `workingDirectory` | Cambiar el directorio de trabajo                                                |\n| `configDir`        | Invalidar el directorio de configuración                                        |\n| `mcpServers`       | Configuración de servidores MCP                                                 |\n| `customAgents`     | Configuración de agentes personalizados                                         |\n| `agent`            | Selección previa de un agente personalizado por nombre                          |\n| `skillDirectories` | Directorios desde los que cargar habilidades                                    |\n| `disabledSkills`   | Habilidades para desactivar                                                     |\n| `infiniteSessions` | Configuración del comportamiento infinito de la sesión                          |\n\n### Ejemplo: cambio de modelo al reanudar\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## Uso de BYOK (traiga su propia clave) con sesiones reanudadas\n\nAl usar sus propias claves de API, debe volver a proporcionar la configuración del proveedor al reanudar la sesión. Las claves de API nunca se conservan en el disco por motivos de seguridad.\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é se conserva?\n\nEl estado de sesión se guarda en `~/.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                                      | ¿Continúa?                                | Notas |\n| ----------------------------------------- | ----------------------------------------- | ----- |\n| El historial de conversaciones            |                                           |       |\n| ✅ Sí                                      | Hilo de mensajes completo                 |       |\n| Resultados de la llamada a la herramienta |                                           |       |\n| ✅ Sí                                      | Almacenado en caché para el contexto      |       |\n| Estado de planificación del agente        |                                           |       |\n| ✅ Sí                                      | Archivo `plan.md`                         |       |\n| Artefactos de sesión                      |                                           |       |\n| ✅ Sí                                      | En `files/` el directorio                 |       |\n| Claves de proveedor o API                 |                                           |       |\n| ❌ No                                      | Seguridad: debe proporcionarse nuevamente |       |\n| Estado de la herramienta en memoria       |                                           |       |\n| ❌ No                                      | Las herramientas no deben tener estado    |       |\n\n## Procedimientos recomendados de identificador de sesión\n\nElija identificadores de sesión que codifiquen la propiedad y el propósito. Esto facilita mucho la auditoría y la limpieza.\n\n| Pattern                         | Example                                          | Caso de uso |\n| ------------------------------- | ------------------------------------------------ | ----------- |\n| ❌                               |                                                  |             |\n| `abc123`                        |                                                  |             |\n| Identificadores aleatorios      | Difícil de auditar, sin información de propiedad |             |\n| ✅                               |                                                  |             |\n| `user-{userId}-{taskId}`        |                                                  |             |\n| `user-alice-pr-review-42`       | Aplicaciones multiusuario                        |             |\n| ✅                               |                                                  |             |\n| `tenant-{tenantId}-{workflow}`  |                                                  |             |\n| `tenant-acme-onboarding`        | SaaS multicliente                                |             |\n| ✅                               |                                                  |             |\n| `{userId}-{taskId}-{timestamp}` |                                                  |             |\n| `alice-deploy-1706932800`       | Limpieza basada en tiempo                        |             |\n\n**Ventajas de los identificadores estructurados:**\n\n* Fácil de auditar: \"Mostrar todas las sesiones para el usuario alice\"\n* Fácil de limpiar: \"Eliminar todas las sesiones anteriores a X\"\n* Control de acceso automatizado: extraer el identificador de usuario desde el identificador de sesión\n\n### Ejemplo: generación de identificadores de sesión\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## Administración del ciclo de vida de la sesión\n\n### Enumeración de sesiones activas\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### Limpieza de sesiones antiguas\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### Desconexión de una sesión (`disconnect`)\n\nCuando se complete una tarea, desconecte de la sesión explícitamente en lugar de esperar tiempos de espera. Esto libera recursos en memoria, pero **conserva los datos de sesión en el disco**, por lo que la sesión todavía se puede reanudar más adelante:\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\nCada SDK también proporciona patrones de limpieza automática idiomáticos:\n\n| Language                               | Pattern                                                                             | Example                                                              |\n| -------------------------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------- |\n| **TypeScript**                         | `Symbol.asyncDispose`                                                               | `await using session = await client.createSession(config);`          |\n| **Python**                             |                                                                                     |                                                                      |\n| `async with` administrador de contexto | `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()` ha quedado obsoleto en favor de `disconnect()`. El código existente que usa `destroy()` seguirá funcionando, pero se debe migrar.\n\n### Eliminación permanente de una sesión (`deleteSession`)\n\nPara quitar permanentemente una sesión y todos sus datos del disco (historial de conversaciones, estado de planeación, artefactos), use `deleteSession`. Esto es irreversible: la sesión **no se puede** reanudar después de la eliminación:\n\n```typescript\n// Permanently remove session data\nawait client.deleteSession(\"user-123-task-456\");\n```\n\n> **`disconnect()` vs `deleteSession()`:**`disconnect()` libera recursos en memoria, pero mantiene los datos de sesión en el disco para la reanudación posterior. `deleteSession()` quita permanentemente todo, incluidos los archivos en el disco.\n\n## Limpieza automática: tiempo de espera por inactividad\n\nDe forma predeterminada, las sesiones **no tienen tiempo de espera de inactividad** y se encuentran indefinidamente hasta que se desconectan o eliminan explícitamente. Opcionalmente, puede configurar un tiempo de espera de inactividad de todo el servidor mediante `CopilotClientOptions.sessionIdleTimeoutSeconds`:\n\n```typescript\nconst client = new CopilotClient({\n  sessionIdleTimeoutSeconds: 30 * 60, // 30 minutes\n});\n```\n\nCuando se configura un tiempo de espera, las sesiones sin actividad durante esa duración se limpian automáticamente. Establezca en `0` u omítalo para desactivarlo.\n\n> \\[!NOTE]\n> Esta opción solo se aplica cuando el SDK genera el proceso en tiempo de ejecución. Al conectarse a un servidor existente a través de `cliUrl`, se aplica la configuración de tiempo de espera del propio servidor.\n\n![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-2.png)\n\nLas sesiones con trabajo activo (comandos en ejecución, agentes en segundo plano) siempre están protegidas contra la limpieza por inactividad, independientemente de la configuración del tiempo de espera.\n\nEscuche eventos inactivos para reaccionar a la inactividad de sesión:\n\n```typescript\nsession.on(\"session.idle\", (event) => {\n  console.log(`Session idle for ${event.idleDurationMs}ms`);\n});\n```\n\n## Patrones de implementación\n\n### Patrón 1: un servidor de la CLI por usuario (recomendado)\n\nIdeal para: Aislamiento seguro, entornos multiinquilino, Azure sesiones dinámicas.\n\n![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-3.png)\n\n\\*\\*Ventajas:\\*\\*✅ Aislamiento completo | ✅ Seguridad simple | ✅ Escalado sencillo\n\n### Patrón 2: servidor de la CLI compartido (eficiente para recursos)\n\nIdeal para: Herramientas internas, entornos de confianza, configuraciones restringidas a recursos.\n\n![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-4.png)\n\n**Requisitos:**\n\n* ⚠️ Identificadores de sesión únicos por usuario\n* ⚠️ Control de acceso de nivel de aplicación\n* ⚠️ Validación del identificador de sesión antes de las operaciones\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## Azure sesiones dinámicas\n\nEn el caso de las implementaciones sin servidor o contenedor en las que los contenedores pueden reiniciar o migrar:\n\n### Montaje del almacenamiento persistente\n\nEl directorio de estado de sesión debe montarse en almacenamiento persistente:\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![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-session-persistence-diagram-5.png)\n\n**¡La sesión sobrevive a los reinicios del contenedor!**\n\n## Sesiones ilimitadas para flujos de trabajo de larga duración\n\nEn el caso de los flujos de trabajo que pueden superar los límites de contexto, habilite sesiones infinitas con compactación automática:\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> Los umbrales son relaciones de uso de contexto (0,0-1,0), no recuentos absolutos de tokens. Consulte [autotitle](/es/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/troubleshooting/compatibility) para obtener más información.\n\n## Limitaciones y consideraciones\n\n| Limitación                                      | Description                                             | Mitigación                                                                 |\n| ----------------------------------------------- | ------------------------------------------------------- | -------------------------------------------------------------------------- |\n| **Volver a autenticar BYOK**                    | Las claves de API no se conservan                       | Almacene claves en su gestor de secretos; proporciónelas al reanudar       |\n| **Almacenamiento escribible**                   |                                                         |                                                                            |\n| `~/.copilot/session-state/` debe ser escribible | Monte volumen persistente en contenedores               |                                                                            |\n| **Sin bloqueo de sesión**                       | El acceso simultáneo a la misma sesión no está definido | Implementar el bloqueo o la cola a nivel de aplicación                     |\n| **El estado de la herramienta no se conserva**  | Se pierde el estado de la herramienta en memoria        | Diseñe herramientas para que sean sin estado o conserven su propio estado. |\n\n### Control del acceso simultáneo\n\nEl SDK no proporciona bloqueo de sesión integrado. Si varios clientes pueden acceder a la misma sesión:\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## Resumen\n\n| Feature                                                                                                              | Cómo se usa                                                     |\n| -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |\n| **Creación de una sesión reanudable**                                                                                | Proporcione su propio `sessionId`                               |\n| **Reanudar sesión**                                                                                                  | `client.resumeSession(sessionId)`                               |\n| **Reanudación de BYOK**                                                                                              | Volver a proporcionar la configuración de `provider`            |\n| **Enumerar las sesiones**                                                                                            | `client.listSessions(filter?)`                                  |\n| **Desconexión de la sesión activa**                                                                                  |                                                                 |\n| `session.disconnect()`— libera recursos en memoria; se conservan los datos de sesión en el disco para la reanudación |                                                                 |\n| **Eliminar sesión permanentemente**                                                                                  |                                                                 |\n| `client.deleteSession(sessionId)`— quita permanentemente todos los datos de sesión del disco; no se puede reanudar   |                                                                 |\n| **Implementación en contenedores**                                                                                   | Montar `~/.copilot/session-state/` a almacenamiento persistente |\n\n## Pasos siguientes\n\n* [Enlaces de sesión](/es/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/hooks-overview) - Personaliza el comportamiento de la sesión con hooks\n* [Compatibilidad del SDK y la CLI](/es/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/troubleshooting/compatibility) : comparación de características del SDK frente a la CLI\n* [Guía de depuración](/es/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/troubleshooting/debugging) : Solución de problemas de sesión"}