Nota:
SDK de Copilot actualmente está en Versión preliminar técnica. La funcionalidad y la disponibilidad están sujetas a cambios.
Tenga en cuenta los distintos patrones de aislamiento para las sesiones de la CLI y cómo desea administrar sesiones y recursos simultáneos al implementar la aplicación.
**Lo mejor para:** Desarrolladores de plataformas, generadores de SaaS y cualquier implementación que sirva a más de unos pocos usuarios simultáneos.
Patrones de aislamiento de sesión
Antes de elegir un patrón, considere tres dimensiones:
-
**Aislamiento**: ¿Quién puede ver qué sesiones? -
**Simultaneidad**: ¿Cuántas sesiones pueden ejecutarse simultáneamente? -
**Persistencia**: ¿Cuánto tiempo viven las sesiones?

Patrón 1: CLI aislada por usuario
Cada usuario obtiene su propia instancia del servidor de la CLI. Este es el aislamiento más seguro: las sesiones, la memoria y los procesos de un usuario están completamente separados.

**Cuándo usar:**
- SaaS multiinquilino donde el aislamiento de datos es crítico.
- Usuarios con credenciales de autenticación diferentes.
- Requisitos de cumplimiento, como SOC 2 o HIPAA.
// CLI pool manager—one CLI per user
class CLIPool {
private instances = new Map<string, { client: CopilotClient; port: number }>();
private nextPort = 5000;
async getClientForUser(userId: string, token?: string): Promise<CopilotClient> {
if (this.instances.has(userId)) {
return this.instances.get(userId)!.client;
}
const port = this.nextPort++;
// Spawn a dedicated CLI for this user
await spawnCLI(port, token);
const client = new CopilotClient({
cliUrl: `localhost:${port}`,
});
this.instances.set(userId, { client, port });
return client;
}
async releaseUser(userId: string): Promise<void> {
const instance = this.instances.get(userId);
if (instance) {
await instance.client.stop();
this.instances.delete(userId);
}
}
}
Patrón 2: CLI compartida con aislamiento de sesión
Varios usuarios comparten un servidor de la CLI, pero tienen sesiones aisladas a través de identificadores de sesión únicos. Esto es más ligero en los recursos, pero proporciona un aislamiento más débil.

**Cuándo usar:**
- Herramientas internas con usuarios de confianza.
- Entornos con restricción de recursos.
- Requisitos de aislamiento más bajos.
const sharedClient = new CopilotClient({
cliUrl: "localhost:4321",
});
// Enforce session isolation through naming conventions
function getSessionId(userId: string, purpose: string): string {
return `${userId}-${purpose}-${Date.now()}`;
}
// Access control: ensure users can only access their own sessions
async function resumeSessionWithAuth(
sessionId: string,
currentUserId: string
): Promise<Session> {
const [sessionUserId] = sessionId.split("-");
if (sessionUserId !== currentUserId) {
throw new Error("Access denied: session belongs to another user");
}
return sharedClient.resumeSession(sessionId);
}
Patrón 3: Sesiones compartidas (colaborativas)
Varios usuarios interactúan con la misma sesión, como un salón de chat compartido con Copilot. Este patrón requiere el bloqueo de sesión de nivel de aplicación.

**Cuándo usar:**
- Herramientas de colaboración en equipo.
- Sesiones de revisión de código compartido.
- Asistentes de programación de pares.
Nota:
El SDK no proporciona bloqueo de sesión integrado. Debe serializar el acceso para evitar escrituras simultáneas en la misma sesión.
import Redis from "ioredis";
const redis = new Redis();
async function withSessionLock<T>(
sessionId: string,
fn: () => Promise<T>,
timeoutSec = 300
): Promise<T> {
const lockKey = `session-lock:${sessionId}`;
const lockId = crypto.randomUUID();
// Acquire lock
const acquired = await redis.set(lockKey, lockId, "NX", "EX", timeoutSec);
if (!acquired) {
throw new Error("Session is in use by another user");
}
try {
return await fn();
} finally {
// Release lock only if we still own it
const currentLock = await redis.get(lockKey);
if (currentLock === lockId) {
await redis.del(lockKey);
}
}
}
// Serialize access to a shared session
app.post("/team-chat", authMiddleware, async (req, res) => {
const result = await withSessionLock("team-project-review", async () => {
const session = await client.resumeSession("team-project-review");
return session.sendAndWait({ prompt: req.body.message });
});
res.json({ content: result?.data.content });
});
Comparación de patrones de aislamiento
| CLI aislada por usuario | Cli compartida + aislamiento de sesión | Sesiones compartidas |
|---|
**Aislamiento** | Completado | Logical | compartido |
| Uso de recursos | Alto (CLI por usuario) | Bajo (una CLI) | Nivel Bajo (un CLI y una sesión) | | Complejidad | Medio | Bajo | Alto (requiere bloqueo) | | Flexibilidad de autenticación | Tokens por usuario | Token de servicio | Token de servicio | | Más adecuado para | SaaS multicliente | Herramientas internas | Colaboración |
Escalado horizontal
Varios servidores de la CLI (Interfaz de Línea de Comandos) detrás de un equilibrador de carga
Para atender a más usuarios simultáneos, ejecute varias instancias de servidor de la CLI detrás de un equilibrador de carga. El estado de sesión debe estar en el almacenamiento compartido para que cualquier servidor de la CLI pueda reanudar cualquier sesión.

// Route sessions across CLI servers
class CLILoadBalancer {
private servers: string[];
private currentIndex = 0;
constructor(servers: string[]) {
this.servers = servers;
}
// Round-robin selection
getNextServer(): string {
const server = this.servers[this.currentIndex];
this.currentIndex = (this.currentIndex + 1) % this.servers.length;
return server;
}
// Sticky sessions: same user always hits same server
getServerForUser(userId: string): string {
const hash = this.hashCode(userId);
return this.servers[hash % this.servers.length];
}
private hashCode(str: string): number {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = (hash << 5) - hash + str.charCodeAt(i);
hash |= 0;
}
return Math.abs(hash);
}
}
const lb = new CLILoadBalancer([
"cli-1:4321",
"cli-2:4321",
"cli-3:4321",
]);
app.post("/chat", async (req, res) => {
const server = lb.getServerForUser(req.user.id);
const client = new CopilotClient({ cliUrl: server });
const session = await client.createSession({
sessionId: `user-${req.user.id}-chat`,
model: "gpt-4.1",
});
const response = await session.sendAndWait({ prompt: req.body.message });
res.json({ content: response?.data.content });
});
Sesiones persistentes y almacenamiento compartido

**Las sesiones permanentes** anclan cada usuario a un servidor específico de la CLI. No se necesita almacenamiento compartido, pero la distribución de carga puede ser desigual si el tráfico del usuario varía significativamente.
**El almacenamiento compartido** permite que cualquier CLI controle cualquier sesión. La distribución de carga es más uniforme, pero requiere almacenamiento en red para `~/.copilot/session-state/`.
Escalado vertical
Ajuste de un único servidor de la CLI
Un único servidor de la CLI puede controlar muchas sesiones simultáneas. La clave es administrar el ciclo de vida de la sesión para evitar el agotamiento de recursos:

// Limit concurrent active sessions
class SessionManager {
private activeSessions = new Map<string, Session>();
private maxConcurrent: number;
constructor(maxConcurrent = 50) {
this.maxConcurrent = maxConcurrent;
}
async getSession(sessionId: string): Promise<Session> {
// Return existing active session
if (this.activeSessions.has(sessionId)) {
return this.activeSessions.get(sessionId)!;
}
// Enforce concurrency limit
if (this.activeSessions.size >= this.maxConcurrent) {
await this.evictOldestSession();
}
// Create or resume
const session = await client.createSession({
sessionId,
model: "gpt-4.1",
});
this.activeSessions.set(sessionId, session);
return session;
}
private async evictOldestSession(): Promise<void> {
const [oldestId] = this.activeSessions.keys();
const session = this.activeSessions.get(oldestId)!;
// Session state is persisted automatically—safe to disconnect
await session.disconnect();
this.activeSessions.delete(oldestId);
}
}
Sesiones efímeras frente a persistentes

Las sesiones efímeras se crean por solicitud y se destruyen después del uso. Son ideales para tareas únicas y APIs sin estado.
**Las sesiones persistentes** se denominan, sobreviven a los reinicios y se pueden reanudar. Son ideales para chats de múltiples turnos y flujos de trabajo largos.
Sesiones efímeras
app.post("/api/analyze", async (req, res) => {
const session = await client.createSession({
model: "gpt-4.1",
});
try {
const response = await session.sendAndWait({
prompt: req.body.prompt,
});
res.json({ result: response?.data.content });
} finally {
await session.disconnect();
}
});
Sesiones persistentes
// Start a conversation
app.post("/api/chat/start", async (req, res) => {
const sessionId = `user-${req.user.id}-${Date.now()}`;
const session = await client.createSession({
sessionId,
model: "gpt-4.1",
infiniteSessions: {
enabled: true,
backgroundCompactionThreshold: 0.80,
},
});
res.json({ sessionId });
});
// Continue the conversation
app.post("/api/chat/message", async (req, res) => {
const session = await client.resumeSession(req.body.sessionId);
const response = await session.sendAndWait({ prompt: req.body.message });
res.json({ content: response?.data.content });
});
// Clean up when done
app.post("/api/chat/end", async (req, res) => {
await client.deleteSession(req.body.sessionId);
res.json({ success: true });
});
Despliegues de contenedores
Kubernetes con almacenamiento persistente
En el siguiente ejemplo, se implementan tres réplicas de la CLI que comparten un PersistentVolumeClaim de modo que cualquier réplica pueda reanudar cualquier sesión.
apiVersion: apps/v1
kind: Deployment
metadata:
name: copilot-cli
spec:
replicas: 3
selector:
matchLabels:
app: copilot-cli
template:
metadata:
labels:
app: copilot-cli
spec:
containers:
- name: copilot-cli
image: ghcr.io/github/copilot-cli:latest
args: ["--headless", "--port", "4321"]
env:
- name: COPILOT_GITHUB_TOKEN
valueFrom:
secretKeyRef:
name: copilot-secrets
key: github-token
ports:
- containerPort: 4321
volumeMounts:
- name: session-state
mountPath: /root/.copilot/session-state
volumes:
- name: session-state
persistentVolumeClaim:
claimName: copilot-sessions-pvc
---
apiVersion: v1
kind: Service
metadata:
name: copilot-cli
spec:
selector:
app: copilot-cli
ports:
- port: 4321
targetPort: 4321

Lista de comprobación de envío
| Preocupación | Recomendación |
|---|
**Limpieza de sesión** | Ejecute una limpieza periódica para eliminar sesiones más antiguas que su TTL. |
|
Comprobaciones de estado | Hacer ping al servidor de la CLI periódicamente; reinicie si no responde. |
|
Storage | Monte volúmenes persistentes para ~/.copilot/session-state/. |
|
Secretos | Use el administrador de secretos de la plataforma (almacén, secretos de Kubernetes, etc.). |
|
Monitoring | Realice un seguimiento del número de sesiones activas, la latencia de respuesta y las tasas de error. |
|
Locking | Use Redis o similar para el acceso a sesión compartida. |
|
Apagado | Purga las sesiones activas antes de detener los servidores de la CLI. |
Limitaciones
| Limitación | Detalles |
|---|
**Sin bloqueo de sesión integrado** | Implemente el bloqueo de nivel de aplicación para el acceso simultáneo. |
| Sin equilibrio de carga integrado | Use un equilibrador de carga externo o una malla de servicio. | | El estado de sesión está basado en archivos | Requiere un sistema de archivos compartido para las configuraciones de varios servidores. | | Tiempo de espera de inactividad de 30 minutos | La CLI limpia automáticamente las sesiones sin actividad. | | La CLI es un proceso único | Escale agregando más instancias de servidor de la CLI, no subprocesos. |
Pasos siguientes
- Para la configuración básica del lado servidor, consulte Configuración del SDK de Copilot para los servicios de back-end.
- Para la autenticación multiusuario, consulte Uso de OAuth de GitHub con el SDK de Copilot.
- Para la instalación y el primer mensaje, consulte Introducción al SDK de Copilot.