Skip to main content
Skip to content

Reanudación y persistencia de sesión

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.

Cómo funcionan las sesiones

Al 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.

Diagrama: Diagrama de flujo que muestra el proceso descrito.

Estado¿Qué ocurre?
Crearsession_id asignado
ActivoEnviar avisos, llamadas a herramientas, respuestas
En pausaEstado guardado en el disco
ResumeEstado cargado desde el disco

Inicio rápido: creación de una sesión reanudable

La 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.

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

Ir

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

Reanudación de una sesión

Más tarde —minutos, horas o incluso días después— podrá reanudar la sesión desde donde la dejó.

Permisos recordados con un sistema de archivos de sesión

Al configurar un proveedor personalizado sessionFs, las opciones de permisos duraderos gestionadas por el entorno de ejecución usan almacenamiento del proveedor en lugar de la configuración del host en tiempo de ejecución. Los archivos residen en sessionStatePath del proveedor y conservan sus formatos existentes:

  • permissions.json: un mapa locations de nivel superior que conserva los campos allowed_directories y tool_approvals existentes
  • settings.json: de nivel superior allowedUrls para approve-permanently las aprobaciones de direcciones URL y sandbox para las preferencias de espacio aislado guardadas
  • config.json: de nivel superior trustedFolders para la confianza de carpetas recordadas y sandboxOnboardingShown para el mensaje de espacio aislado habilitado por primera vez.

Las claves de ubicación son rutas de acceso de directorio del proveedor normalizadas, como /workspace, sin un prefijo agregado. El tiempo de ejecución los resuelve léxicamente mediante convenciones de ruta de acceso del proveedor, sin inspeccionar el sistema de archivos host ni detectar repositorios de Git host. Una aprobación guardada para /workspace no se selecciona automáticamente cuando el directorio de trabajo es /workspace/sub.

La confianza de carpetas asociadas a un proveedor también usa rutas de acceso léxicas: una carpeta de confianza incluye la propia carpeta y sus descendientes, no los árboles de trabajo de Git enlazados en otras rutas de acceso. Confíe explícitamente en esas rutas de acceso de worktree.

No hay ninguna partición adicional de identificador de sesión dentro de estos archivos. Las sesiones que acceden a los mismos archivos subyacentes comparten opciones recordadas. Utilice espacios de nombres de proveedor independientes cuando las sesiones o los tenants no deben compartir autorizaciones. Con un espacio de nombres por sesión, las opciones permanentes se conservan al reanudar esa sesión, pero no se transfieren automáticamente a nuevas sesiones. Para restaurar las opciones persistentes de una sesión en la reanudación, vuelva a conectarla al mismo espacio de nombres.

Las actualizaciones de consentimiento se serializan por punto de conexión de proveedor y archivo dentro de un proceso en tiempo de ejecución. Los puntos de conexión independientes no se bloquean entre sí. Si diferentes puntos de conexión de proveedor o procesos en tiempo de ejecución comparten archivos de respaldo, la aplicación debe coordinar las actualizaciones simultáneas; el tiempo de ejecución no puede deducir que esos archivos se comparten.

Estas operaciones nunca importan, actualizan o recurren a config.json, permissions-config.json o settings.json del host, incluso cuando se produce un error en las lecturas o escrituras del proveedor. Los archivos en formato existente facilitados por el proveedor se leen directamente.

Al igual que con la configuración del host, las aprobaciones de direcciones URL solo se leen de settings.json. Se omite un campo heredado allowedUrls en config.json; config.json sigue siendo el archivo de estado global para la confianza de carpetas recordada y el indicador de introducción al espacio aislado.

El enrutamiento de almacenamiento no cambia las duraciones de permisos, la precedencia de denegación de dirección URL ni el comportamiento de la directiva de sesión. Aprobar una vez y aprobar para la sesión no se convierten en concesiones permanentes.

Las preferencias de sandbox guardadas se restauran al crear y reanudar. Las llamadas de SDK options.update explícitas posteriores pueden cambiar la configuración del espacio aislado activo sin volver a escribir la preferencia guardada.

Sin sessionFs, las aplicaciones del SDK en los modos empty y copilot-cli conservan la persistencia respaldada por el host existente. Esto incluye el comportamiento existente en el que el consentimiento de dirección URL permanente guarda la configuración del host y concede acceso a la sesión activa, pero una sesión de SDK nueva no carga automáticamente la lista de permitidos de la dirección URL del host.

Consulte Multiinquilino e implementaciones de servidor para conocer las responsabilidades de aislamiento del proveedor.

Recuperación de transcripción

La opción de reanudar allowTranscriptRecovery controla la recuperación cuando el entorno de ejecución carga una transcripción del almacenamiento. El valor predeterminado es true en todos los modos. Con false, una carga que descartaría los registros dañados o mueve session.start falla con el error JSON-RPC -32075 sin volver a escribir el registro. Se acepta un registro final intacto sin una nueva línea.

Los registros omitidos para la compatibilidad hacia adelante siguen contando al comprobar el orden persistente. Si estos registros preceden a session.start, la recuperación debe mover el registro de inicio por delante de ellos. Una transcripción que solo contiene registros omitidos no está vacía y no se puede recuperar sin un session.start válido.

Cuando se permite la recuperación, la sesión devuelta expone transcriptRecovery, incluidos los números de línea no válidos, si session.start se mueve y una ruta de copia de seguridad exacta por bytes planificada. La carga por sí sola no escribe esa copia de seguridad; el siguiente anexado persistente efectúa la reparación y escribe la copia de seguridad.

Nota:

Esta opción se aplica a una nueva carga de transcripción, no a la vigencia de una sesión. La reconexión a una sesión que ya reside en el entorno de ejecución reutiliza su historial activo sin volver a validar el almacenamiento ni rechazar la recuperación autorizada por una reanudación anterior. El informe de recuperación describe el proceso que realizó la recuperación, no todas las reconexiones posteriores.

Diagrama: Diagrama de flujo que muestra el proceso descrito.

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

Ir

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

Opciones de reanudación

Al 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.

OpciónDescription
modelCambiar el modelo de la sesión reanudada
systemMessageAnular o ampliar el mensaje del sistema
availableToolsRestringir qué herramientas están disponibles
excludedToolsDeshabilitar herramientas específicas
providerVolver a proporcionar las credenciales BYOK (necesarias para las sesiones BYOK)
capi.autoTierInvalidar la preferencia de enrutamiento automático persistente
capi.enableWebSocketResponsesElige el transporte de la API Responses para la sesión reanudada
reasoningEffortAjuste del nivel de esfuerzo de razonamiento
streamingHabilitar o deshabilitar las respuestas de streaming
workingDirectoryCambiar el directorio de trabajo
configDirInvalidar el directorio de configuración
mcpServersConfiguración de servidores MCP
customAgentsConfiguración de agentes personalizados
agentSelección previa de un agente personalizado por nombre
skillDirectoriesDirectorios desde los que cargar habilidades
disabledSkillsHabilidades para desactivar
infiniteSessionsConfiguración del comportamiento infinito de la sesión

Persistencia del nivel automático

Con model: "auto", la configuración opcional capi.autoTier selecciona una preferencia de enrutamiento automático: efficiency, balance, intelligenceo fast. En Python, use capi={"auto_tier": "balance"}. Esta configuración se aplica al enrutamiento automático V2; Las solicitudes automáticas V1 no se modifican.

Cuando la característica de desactivación predeterminada DYNAMIC_AUTO_TIERS del entorno de ejecución está habilitada, la RPC de la sesión model.list también devuelve metadatos opcionales auto del punto de conexión del proveedor /meta. Utilice los descriptores habilitados con type: "auto" para detectar identificadores de nivel admitidos adicionales, sus nombres para mostrar, descripciones y ordenación. Los métodos de selección existentes y los campos JSON aceptan estos identificadores. Un error de detección no recurre a /models y una respuesta satisfactoria sin metadatos de auto no proporciona niveles Auto seleccionables.

Para rellenar un selector de modelos antes de que exista cualquier sesión, habilite DYNAMIC_AUTO_TIERS en el entorno del tiempo de ejecución (por ejemplo, la env opción de cliente). El RPC de nivel models.list de servidor (client.rpc.models.list() en Node.js) devuelve los mismos metadatos auto de la misma respuesta /meta, con el mismo comportamiento sin retroceso. El listado a nivel de servidor lee la marca que el tiempo de ejecución resolvió al iniciarse, no las marcas de características por sesión o las asignaciones de experimentos, por lo que establece la marca donde se inicia el tiempo de ejecución. Con la marca deshabilitada, models.list no cambia y omite auto.

Trate los identificadores de nivel como valores extensibles, no como una enumeración cerrada. Los valores con nombre existentes permanecen disponibles; para identificadores adicionales, use cadenas en Node.js y Python, AutoTier("premium-v2") en Go, new AutoTier("premium-v2") en .NET, AutoTier::Custom en Rust o AutoTier.fromValue en Java. El defaultTier del proveedor describe su enrutamiento predeterminado sin crear una preferencia confirmada del SDK.

Si se quita o deshabilita un nivel persistente, Resume conserva la preferencia explícita en lugar de reemplazarla por el valor predeterminado del proveedor. Seleccione un reemplazo disponible antes de activar el enrutamiento automático.

La CLI también conserva las preferencias derivadas de la configuración durante el inicio, incluso cuando un nivel no está disponible o la detección dinámica está deshabilitada. A continuación, puede seleccionar una alternativa en el selector de modelos. Las preferencias explícitas de creación y reanudación del SDK se siguen validando antes de que la operación tenga éxito, y la activación automática siempre valida la disponibilidad según el modo de detección resuelto.

Cuando una solicitud de creación o reanudación incluye expAssignments, el entorno de ejecución instala esas asignaciones antes de validar una preferencia automática explícita. La validación, el descubrimiento y la activación usan la misma decisión de característica resuelta.

fast es un preajuste de latencia exclusivo para integradores, no una preferencia del producto nativo GitHub Copilot. Fast no se valida con el catálogo de niveles /meta al configurar una sesión. El SDK no determina la idoneidad para Fast, ni inspecciona la identidad del cliente, ni lo selecciona como opción predeterminada, ni recurre a otro nivel cuando un entorno de ejecución no es compatible con él: una versión anterior del entorno de ejecución devuelve su error nativo sin cambios.

El tiempo de ejecución conserva el nivel seleccionado, por lo que las aplicaciones no necesitan volver a enviarlos en cada currículum:

  • Si se omite el nivel al crear una sesión, se usa el comportamiento de enrutamiento predeterminado del entorno de ejecución.
  • La reanudación en frío restaura el nivel persistente. Proporcionar un nivel explícito invalida el valor restaurado para la nueva activación.
  • Al reanudar una sesión que ya reside en el entorno de ejecución, omitir el nivel conserva la selección actual y proporcionar el mismo nivel es un no-op. Especificar un nivel diferente solicita un cambio seguro que el entorno de ejecución aplica después de que la reanudación se complete correctamente; no puede cambiar un turno que ya está en ejecución.
  • Las sesiones anteriores sin un nivel persistente conservan el comportamiento de enrutamiento predeterminado.

La selección de nivel no es una operación de cambio de modelo en tiempo real. El SDK reenvía la preferencia; el entorno de ejecución posee la persistencia y la validación.

Los eventos session.start y session.resume incluyen el nivel seleccionado en su campo opcional data.autoTier (data.auto_tier en Python). Cuando no se selecciona ningún nivel, se omite el campo.

Cambiar el nivel automático durante una sesión

Llame setAutoTier a para cambiar la preferencia de enrutamiento en una sesión activa sin cambiar el modelo seleccionado. Pase null (Python None, Gonil) para volver al enrutamiento automático predeterminado del proveedor.

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

El entorno de ejecución no aplica la preferencia de inmediato. Registra la solicitud y la confirma solo cuando un usuario posterior vuelve a usar el auto modelo correctamente obtiene un modelo utilizable del proveedor. Por lo tanto, un pending estado confirma que se aceptó la solicitud, no que surtió efecto. Solo permanece la solicitud más reciente: una nueva solicitud reemplaza cualquier solicitud anterior que ningún turno haya recogido todavía.

Si una solicitud anterior sigue validándose cuando llega una solicitud de preferencia o un restablecimiento más recientes, la llamada anterior produce un error de solicitud sustituida por otra más reciente en lugar de reemplazar la intención más reciente.

Observe el resultado a través de estos eventos:

  • session.model_change cuando se confirma la preferencia.
  • session.auto_tier_switch_failed cuando no lo hace. Este evento es efímero, por lo que el entorno de ejecución nunca lo guarda ni lo vuelve a reproducir al reanudar. Su campo reason es uno de policy_rejected, request_failed, setup_failed o unsupported, y la preferencia que estaba activa anteriormente sigue activa.

También puede leer el estado autorizado en cualquier momento a través del método RPC de model.getCurrent de la sesión, que informa del autoTier confirmado, de cualquier pendingAutoTier no reclamado y de activatingAutoTier reclamado actualmente mediante una activación en curso.

SDK (Sistema de traducciónCambiar el nivelVolver al enrutamiento predeterminado del proveedor
Node.jssession.setAutoTier("balance")session.setAutoTier(null)
Pythonsession.set_auto_tier("balance")session.set_auto_tier(None)
Irsession.SetAutoTier(ctx, &tier)session.SetAutoTier(ctx, nil)
.NETsession.SetAutoTierAsync(AutoTier.Balance)session.SetAutoTierAsync(null)
Óxidosession.set_auto_tier(Some(AutoTier::Balance))session.set_auto_tier(None)
Javasession.setAutoTier(AutoTier.BALANCE)session.setAutoTier(null)

Para seleccionar el modelo auto y su preferencia de enrutamiento en una sola llamada, configure en su lugar el nivel en el selector de modelo. El tiempo de ejecución rechaza esta opción cuando el modelo es algo distinto de auto.

SDK (Sistema de traducciónPreparar un nivel con el interruptorRestablecimiento al enrutamiento predeterminado del proveedor
Node.jssetModel("auto", { autoTier: "balance" })setModel("auto", { autoTier: null })
Pythonset_model("auto", auto_tier="balance")set_model("auto", auto_tier=None)
IrSetModelOptions{AutoTier: &tier}SetModelOptions{ResetAutoTier: true}
.NETnew SetModelOptions { AutoTier = AutoTier.Balance }new SetModelOptions { ResetAutoTier = true }
ÓxidoSetModelOptions::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 y Rust expresan los tres estados en un solo valor: Node.js y Python porque null/None se puede distinguir de un argumento omitido y Rust porque AutoTierPreference::Reset es una variante distinta de la misma opción. Go, .NET y Java no tienen forma de distinguir "reset" de "unset" en un valor, por lo que llevan una marca de restablecimiento independiente. Omitir ambos siempre significa "dejar solo la preferencia actual".

Transferencia de respuestas al reanudar

La configuración opcional capi.enableWebSocketResponses elige el transporte de la API de respuestas CAPI. El valor predeterminado es true, por lo que el transporte de WebSocket se usa cada vez que el modelo seleccionado anuncia el ws:/responses punto de conexión. Si se establece en false, se vuelve a usar el transporte HTTP. En Python, use capi={"enable_web_socket_responses": False}.

Proporciónelo en la llamada de reanudación cuando lo necesite. Vale la pena establecer cuando las conexiones de WebSocket producen un error detrás de un proxy y cuando una sesión reanudada notifica 400 input item ID does not belong to this connection, que es específica del transporte de WebSocket.

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

Establecer esto en false es equivalente a la COPILOT_CLI_DISABLE_WEBSOCKET_RESPONSES variable de entorno, que tiene la polaridad opuesta.

Ejemplo: cambio de modelo al reanudar

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

Uso de BYOK (traiga su propia clave) con sesiones reanudadas

Al 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.

// 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é se conserva?

El estado de sesión se guarda en ~/.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
Data¿Continúa?Notas
El historial de conversaciones
✅ SíHilo de mensajes completo
Resultados de la llamada a la herramienta
✅ SíAlmacenado en caché para el contexto
Estado de planificación del agente
✅ SíArchivo plan.md
Artefactos de sesión
✅ SíEn files/ el directorio
Claves de proveedor o API
❌ NoSeguridad: debe proporcionarse nuevamente
Estado de la herramienta en memoria
❌ NoLas herramientas no deben tener estado

Procedimientos recomendados de identificador de sesión

Elija identificadores de sesión que codifiquen la propiedad y el propósito. Esto facilita mucho la auditoría y la limpieza.

PatternExampleCaso de uso
❌abc123Identificadores aleatoriosDifícil de auditar, sin información de propiedad
✅user-{userId}-{taskId}user-alice-pr-review-42Aplicaciones multiusuario
✅tenant-{tenantId}-{workflow}tenant-acme-onboardingSaaS multicliente
✅{userId}-{taskId}-{timestamp}alice-deploy-1706932800Limpieza basada en tiempo

Ventajas de los identificadores estructurados:

  • Fácil de auditar: "Mostrar todas las sesiones para el usuario alice"
  • Fácil de limpiar: "Eliminar todas las sesiones anteriores a X"
  • Control de acceso automatizado: extraer el identificador de usuario desde el identificador de sesión

Ejemplo: generación de identificadores de sesión

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"

Administración del ciclo de vida de la sesión

Enumeración de sesiones activas

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

Limpieza de sesiones antiguas

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

Desconexión de una sesión (disconnect)

Cuando 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:

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

Cada SDK también proporciona patrones de limpieza automática idiomáticos:

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

Nota:

destroy() ha quedado obsoleto en favor de disconnect(). El código existente que usa destroy() seguirá funcionando, pero se debe migrar.

Eliminación permanente de una sesión (deleteSession)

Para 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:

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

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.

Limpieza automática: tiempo de espera por inactividad

De 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:

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

Cuando 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.

Nota:

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.

Diagrama: Diagrama de flujo que muestra el proceso descrito.

Las 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.

Escuche eventos inactivos para reaccionar a la inactividad de sesión:

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

Patrones de implementación

Ideal para: Aislamiento seguro, entornos multiinquilino, Azure sesiones dinámicas.

Diagrama: Diagrama de flujo que muestra el proceso descrito.

**Ventajas:**✅ Aislamiento completo | ✅ Seguridad simple | ✅ Escalado sencillo

Patrón 2: servidor de la CLI compartido (eficiente para recursos)

Ideal para: Herramientas internas, entornos de confianza, configuraciones restringidas a recursos.

Diagrama: Diagrama de flujo que muestra el proceso descrito.

Requisitos:

  • ⚠️ Identificadores de sesión únicos por usuario
  • ⚠️ Control de acceso de nivel de aplicación
  • ⚠️ Validación del identificador de sesión antes de las operaciones
// 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);
}

Azure sesiones dinámicas

En el caso de las implementaciones sin servidor o contenedor en las que los contenedores pueden reiniciar o migrar:

Montaje del almacenamiento persistente

El directorio de estado de sesión debe montarse en almacenamiento persistente:

# 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

Diagrama: Diagrama de flujo que muestra el proceso descrito.

¡La sesión sobrevive a los reinicios del contenedor!

Sesiones ilimitadas para flujos de trabajo de larga duración

En el caso de los flujos de trabajo que pueden superar los límites de contexto, habilite sesiones infinitas con compactación automática:

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

Nota:

Los umbrales son relaciones de uso de contexto (0,0-1,0), no recuentos absolutos de tokens. Consulte autotitle para obtener más información.

Limitaciones y consideraciones

LimitaciónDescriptionMitigación
Volver a autenticar BYOKLas claves de API no se conservanAlmacene claves en su gestor de secretos; proporciónelas al reanudar
Almacenamiento escribible~/.copilot/session-state/ debe ser escribibleMonte volumen persistente en contenedores
Sin bloqueo de sesiónEl acceso simultáneo a la misma sesión no está definidoImplementar el bloqueo o la cola a nivel de aplicación
El estado de la herramienta no se conservaSe pierde el estado de la herramienta en memoriaDiseñe herramientas para que sean sin estado o conserven su propio estado.

Control del acceso simultáneo

El SDK no proporciona bloqueo de sesión integrado. Si varios clientes pueden acceder a la misma sesión:

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

Resumen

FeatureCómo se usa
Creación de una sesión reanudableProporcione su propio sessionId
Reanudar sesiónclient.resumeSession(sessionId)
Reanudación de BYOKVolver a proporcionar la configuración de provider
Enumerar las sesionesclient.listSessions(filter?)
Desconexión de la sesión activasession.disconnect()— libera recursos en memoria; se conservan los datos de sesión en el disco para la reanudación
Eliminar sesión permanentementeclient.deleteSession(sessionId)— quita permanentemente todos los datos de sesión del disco; no se puede reanudar
Implementación en contenedoresMontar ~/.copilot/session-state/ a almacenamiento persistente

Pasos siguientes