{"meta":{"title":"Multiinquilino e implementaciones de servidor","intro":"El modo de servidor multiusuario consiste en ejecutar el SDK de Copilot desde código de backend que da servicio a más de una persona, inquilino, espacio de trabajo o cuenta de integración. En esta configuración, la aplicación posee el enrutamiento y la autorización de solicitudes, mientras que el SDK y el tiempo de ejecución proporcionan el estado por sesión, la autenticación por sesión y el registro explícito de herramientas para que la sesión de un usuario no herede las herramientas o la identidad de otro usuario.","product":"GitHub Copilot","breadcrumbs":[{"href":"/es/copilot","title":"GitHub Copilot"},{"href":"/es/copilot/how-tos","title":"Procedimientos"},{"href":"/es/copilot/how-tos/copilot-sdk","title":"SDK de Copilot"},{"href":"/es/copilot/how-tos/copilot-sdk/setup","title":"Configuración del SDK de Copilot"},{"href":"/es/copilot/how-tos/copilot-sdk/setup/multi-tenancy","title":"Multiinquilino"}],"documentType":"article"},"body":"# Multiinquilino e implementaciones de servidor\n\nEl modo de servidor multiusuario consiste en ejecutar el SDK de Copilot desde código de backend que da servicio a más de una persona, inquilino, espacio de trabajo o cuenta de integración. En esta configuración, la aplicación posee el enrutamiento y la autorización de solicitudes, mientras que el SDK y el tiempo de ejecución proporcionan el estado por sesión, la autenticación por sesión y el registro explícito de herramientas para que la sesión de un usuario no herede las herramientas o la identidad de otro usuario.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n**Lo mejor para:** Productos SaaS, integraciones de asociados, plataformas internas y servicios back-end que controlan usuarios simultáneos.\n\n## Use esta guía cuando\n\nUtiliza esta guía cuando desarrolles:\n\n* Un producto SaaS multiusuario que inserta agentes con tecnología Copilot\n* Un backend para una integración con socios, como un patrón tipo Copilot Studio o Fabric.\n* Cualquier servidor que controle usuarios simultáneos, áreas de trabajo, inquilinos o solicitudes\n* Un entorno de ejecución compartido en el que varios clientes del SDK se conectan a un proceso de tiempo de ejecución de Copilot\n\nEsta guía es una hermana de [Escalabilidad y multitenencia](/es/copilot/how-tos/copilot-sdk/setup/scaling). Use esa guía para la topología, el equilibrio de carga y los patrones de almacenamiento. Use esta guía para las opciones de nivel de SDK y las opciones de aislamiento en tiempo de ejecución.\n\n## Opciones clave del SDK\n\n| Opción                          | Úselo para                                                                                                  | Notas                                                                                       |\n| ------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |\n| `mode: \"empty\"`                 | Deshabilitación de las herramientas del sistema operativo ambiental y los valores predeterminados de la CLI | Necesario para escenarios multiusuario o compartido.                                        |\n| `sessionIdleTimeoutSeconds`     | Depuración de sesiones inactivas                                                                            | Establezca un tiempo de espera del lado servidor para los procesos de ejecución prolongada. |\n| `baseDirectory`                 | Aislamiento de `COPILOT_HOME` por instancia del entorno de ejecución                                        | Se omite al conectarse a un entorno de ejecución existente.                                 |\n| `sessionFs`                     | Enrutamiento del almacenamiento del sistema de archivos de sesión fuera del disco local                     | Combínalo con proveedores de sistema de archivos por sesión.                                |\n| `RuntimeConnection.forUri(url)` | Uso compartido de un entorno de ejecución ya en ejecución                                                   | Los nombres de idioma varían; consulte los ejemplos siguientes.                             |\n| Por sesión `gitHubToken`        | Limitación de la autenticación al usuario solicitante                                                       | Es preferible a un solo token de usuario compartido.                                        |\n\n### `mode: \"empty\"`\n\n`mode: \"empty\"` deshabilita el comportamiento opcional de la CLI de Copilot de forma predeterminada. En el modo de servidor multiusuario, esta es la línea base segura porque la aplicación debe decidir explícitamente qué herramientas, servidores MCP, aptitudes y rutas de acceso del área de trabajo a las que puede acceder una sesión.\n\nNo use el valor predeterminado `mode: \"copilot-cli\"` para los servidores compartidos. Ese modo está diseñado para agentes de codificación similares a la CLI y puede exponer funcionalidades del sistema de archivos de host ambiente.\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\n```typescript\nimport { CopilotClient, RuntimeConnection } from \"@github/copilot-sdk\";\n\n// baseDirectory and sessionIdleTimeoutSeconds apply when the SDK spawns the\n// runtime. With RuntimeConnection.forUri(...) configure COPILOT_HOME and the\n// idle timeout on the runtime process itself.\nconst client = new CopilotClient({\n    mode: \"empty\",\n    connection: RuntimeConnection.forUri(process.env.COPILOT_RUNTIME_URL!),\n});\n\nconst session = await client.createSession({\n    sessionId: `user-${user.id}-${crypto.randomUUID()}`,\n    model: \"gpt-5.4\",\n    availableTools: [\"custom:lookupOrder\", \"custom:createTicket\"],\n    gitHubToken: user.githubToken,\n});\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\n```python\nfrom copilot import CopilotClient, RuntimeConnection\nfrom copilot.session import PermissionHandler\n\nclient = CopilotClient(\n    mode=\"empty\",\n    base_directory=f\"/var/lib/my-app/copilot/{runtime_instance_id}\",\n    session_idle_timeout_seconds=900,\n    connection=RuntimeConnection.for_uri(runtime_url),\n)\nawait client.start()\n\nsession = await client.create_session(\n    session_id=f\"user-{user.id}-{request_id}\",\n    model=\"gpt-5.4\",\n    available_tools=[\"custom:lookupOrder\", \"custom:createTicket\"],\n    github_token=user.github_token,\n    on_permission_request=PermissionHandler.approve_all,\n)\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\n```golang\nclient := copilot.NewClient(&copilot.ClientOptions{\n    Mode:                      copilot.ModeEmpty,\n    BaseDirectory:             fmt.Sprintf(\"/var/lib/my-app/copilot/%s\", runtimeInstanceID),\n    SessionIdleTimeoutSeconds: 900,\n    Connection:                copilot.URIConnection{URL: runtimeURL},\n})\n\nsession, err := client.CreateSession(ctx, &copilot.SessionConfig{\n    SessionID:      fmt.Sprintf(\"user-%s-%s\", user.ID, requestID),\n    Model:          \"gpt-5.4\",\n    AvailableTools: []string{\"custom:lookupOrder\", \"custom:createTicket\"},\n    GitHubToken:    user.GitHubToken,\n})\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\n```csharp\nvar client = new CopilotClient(new CopilotClientOptions\n{\n    Mode = CopilotClientMode.Empty,\n    BaseDirectory = $\"/var/lib/my-app/copilot/{runtimeInstanceId}\",\n    SessionIdleTimeoutSeconds = 900,\n    Connection = RuntimeConnection.ForUri(runtimeUrl),\n});\n\nawait using var session = await client.CreateSessionAsync(new SessionConfig\n{\n    SessionId = $\"user-{user.Id}-{requestId}\",\n    Model = \"gpt-5.4\",\n    AvailableTools = [\"custom:lookupOrder\", \"custom:createTicket\"],\n    GitHubToken = user.GitHubToken,\n});\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\n```java\n// setCopilotHome and setSessionIdleTimeoutSeconds are ignored when\n// setCliUrl is used; configure those on the runtime process instead.\nvar client = new CopilotClient(new CopilotClientOptions()\n    .setMode(CopilotClientMode.EMPTY)\n    .setCliUrl(runtimeUrl)\n);\n\nvar session = client.createSession(new SessionConfig()\n    .setSessionId(\"user-\" + user.id() + \"-\" + requestId)\n    .setModel(\"gpt-5.4\")\n    .setAvailableTools(List.of(\"custom:lookupOrder\", \"custom:createTicket\"))\n    .setGitHubToken(user.gitHubToken())\n).get();\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\n```rust\nuse std::path::PathBuf;\nuse github_copilot_sdk::{Client, ClientOptions, Transport};\nuse github_copilot_sdk::mode::ClientMode;\nuse github_copilot_sdk::types::SessionConfig;\n\nlet client = Client::start(\n    ClientOptions::new()\n        .with_mode(ClientMode::Empty)\n        .with_base_directory(PathBuf::from(format!(\n            \"/var/lib/my-app/copilot/{runtime_instance_id}\"\n        )))\n        .with_session_idle_timeout_seconds(900)\n        .with_transport(Transport::External {\n            host: runtime_host.to_string(),\n            port: runtime_port,\n            connection_token: None,\n        }),\n).await?;\n\nlet session = client.create_session(\n    SessionConfig::default()\n        .with_session_id(format!(\"user-{}-{request_id}\", user.id))\n        .with_model(\"gpt-5.4\")\n        .with_available_tools([\"custom:lookupOrder\", \"custom:createTicket\"])\n        .with_github_token(user.github_token),\n).await?;\n```\n\n</div>\n\n</div>\n\n### `sessionIdleTimeoutSeconds`\n\nEstablezca `sessionIdleTimeoutSeconds` en servidores para que las sesiones inactivas se limpien automáticamente. Esto evita sesiones zombi en procesos de larga duración y reduce la presión del sistema de archivos y la memoria.\n\n| Language   | Opción pública                           |\n| ---------- | ---------------------------------------- |\n| TypeScript | `sessionIdleTimeoutSeconds`              |\n| Python     | `session_idle_timeout_seconds`           |\n| Ir         | `SessionIdleTimeoutSeconds`              |\n| .NET       | `SessionIdleTimeoutSeconds`              |\n| Java       | `setSessionIdleTimeoutSeconds(...)`      |\n| Óxido      | `with_session_idle_timeout_seconds(...)` |\n\nUse un valor que coincida con la duración de la conversación del producto. En el caso de los back-end de chat, de 15 a 30 minutos suele ser un buen punto de partida. En el caso de los agentes de flujo de trabajo, use un tiempo de espera más largo y una eliminación explícita cuando se complete el flujo de trabajo.\n\n### `baseDirectory`\n\n`baseDirectory` establece `COPILOT_HOME` para una instancia en tiempo de ejecución. Utilízala para aislar el estado de ejecución, las credenciales y los datos de sesión por proceso, pod, trabajador o límite de inquilino.\n\n```typescript\nconst client = new CopilotClient({\n    mode: \"empty\",\n    baseDirectory: `/var/lib/my-app/copilot/runtime-${process.env.HOSTNAME}`,\n    sessionIdleTimeoutSeconds: 900,\n});\n```\n\nEl Integration Runtime almacena el estado de la sesión en el `COPILOT_HOME` configurado, incluido el `session-state/{sessionId}`. Si la aplicación ejecuta varias instancias en tiempo de ejecución, asigne a cada instancia un directorio distinto a menos que use intencionadamente el almacenamiento compartido.\n\nCuando el SDK se conecta a un entorno de ejecución que ya está en ejecución con `RuntimeConnection.forUri(url)`, el cliente del SDK ignora `baseDirectory`. Configura `COPILOT_HOME` en el proceso de ejecución en su lugar.\n\n### `sessionFs`\n\n`sessionFs` registra un proveedor de sistema de archivos de sesión personalizado para que la E/S de archivos con ámbito de sesión se pueda enrutar a través del almacenamiento de aplicaciones en lugar del disco local del entorno de ejecución. Úselo cuando el disco local sea efímero, cuando el estado de la sesión deba almacenarse en el almacenamiento de objetos o cuando una plataforma necesite aplicar rutas de almacenamiento específicas por tenant.\n\n```typescript\nconst client = new CopilotClient({\n    mode: \"empty\",\n    sessionFs: {\n        initialCwd: \"/workspace\",\n        sessionStatePath: \"/session-state\",\n        conventions: \"posix\",\n    },\n});\n```\n\nPara los lenguajes que exponen una llamada de retorno del proveedor, configura `sessionFs` a nivel de cliente y proporciona un controlador de sistema de archivos por sesión al crear o reanudar una sesión. Consulte [Reanudación y persistencia de sesión](/es/copilot/how-tos/copilot-sdk/features/session-persistence) para conocer los conceptos de persistencia y las ventajas de almacenamiento.\n\nSuperficies comprobadas del SDK público:\n\n| Language                                                         | Configuración de nivel de cliente | Proveedor por sesión            |\n| ---------------------------------------------------------------- | --------------------------------- | ------------------------------- |\n| TypeScript                                                       | `sessionFs`                       |                                 |\n| `createSessionFsAdapter` / devoluciones de llamada del proveedor |                                   |                                 |\n| Python                                                           | `session_fs`                      | `create_session_fs_handler`     |\n| Ir                                                               | `SessionFS`                       | `CreateSessionFSProvider`       |\n| .NET                                                             | `SessionFs`                       | `CreateSessionFsProvider`       |\n| Óxido                                                            | `with_session_fs(...)`            | `with_session_fs_provider(...)` |\n\nJava no expone actualmente una opción de \\<c0 pública comprobada />, por lo que esta guía no muestra un ejemplo de Java <c1 />.\n\n### `RuntimeConnection.forUri(url)`\n\nUse una conexión externa en tiempo de ejecución cuando varios clientes del SDK deben compartir un entorno de ejecución ya en ejecución. Esto es habitual en los servicios back-end en los que el proceso en tiempo de ejecución se administra independientemente de los controladores de solicitudes.\n\n| Language   | Conexión externa en tiempo de ejecución                |\n| ---------- | ------------------------------------------------------ |\n| TypeScript | `RuntimeConnection.forUri(url)`                        |\n| Python     | `RuntimeConnection.for_uri(url)`                       |\n| Ir         | `copilot.URIConnection{URL: url}`                      |\n| .NET       | `RuntimeConnection.ForUri(url)`                        |\n| Java       | `setCliUrl(url)`                                       |\n| Óxido      | `Transport::External { host, port, connection_token }` |\n\nLos entornos de ejecución externos administran su propia autenticación y almacenamiento de nivel de proceso. Pase tokens por sesión en `createSession` o `resumeSession` cuando necesite una autenticación específica del usuario.\n\n### Por sesión `gitHubToken`\n\nEstablezca `gitHubToken` en cada sesión para delimitar la autenticación de GitHub al usuario solicitante. Esto es diferente de un token de nivel de cliente, que autentica el proceso en tiempo de ejecución.\n\n```typescript\nconst session = await client.createSession({\n    sessionId: `user-${user.id}-support`,\n    model: \"gpt-5.4\",\n    availableTools: [\"custom:*\"],\n    gitHubToken: user.githubToken,\n});\n```\n\nUtilice tokens por sesión para la exclusión de contenido, el enrutamiento de modelos, las comprobaciones de cuotas y el acceso a Copilot específico del usuario. Evite compartir un token de servicio entre los usuarios a menos que el producto use intencionadamente la semántica de la cuenta de servicio.\n\n## Id. de integración\n\nLos asociados que crean agentes con marca pueden establecer un identificador de integración para las solicitudes de Mission Control. El entorno de ejecución lee `GITHUB_COPILOT_INTEGRATION_ID` y lo establece como la cabecera HTTP `Copilot-Integration-Id` en cada solicitud a Mission Control.\n\n```bash\nGITHUB_COPILOT_INTEGRATION_ID=my-product-agent copilot --headless --port 4321\n```\n\nEl identificador de integración predeterminado es `copilot-developer-cli`. Use un valor estable como `my-product-agent` para la atribución y el enrutamiento. Actualmente, el identificador de integración solo se puede configurar mediante una variable de entorno; no es una opción nativa del SDK.\n\nSi el SDK genera el entorno de ejecución, pase la variable de entorno a través de la opción de entorno de cliente. Si se conecta con `RuntimeConnection.forUri(url)`, establezca la variable de entorno en el propio proceso de tiempo de ejecución.\n\n## Garantías de aislamiento de nivel de sesión\n\nEl aislamiento a nivel de sesión significa que el entorno de ejecución mantiene la información del modelo y del estado específica del usuario dentro del ámbito de una sesión, y no en un estado compartido global.\n\n| Superficie                   | Comportamiento de aislamiento                                                             |\n| ---------------------------- | ----------------------------------------------------------------------------------------- |\n| Caché de lista de modelos    | Por sesión. La búsqueda de modelos usa la caché de lista de modelos de la sesión.         |\n| Estado de sesión             | Por ID de sesión en `COPILOT_HOME/session-state/{sessionId}`.                             |\n| identidad de GitHub          | Por sesión cuando `gitHubToken` está establecido en la sesión.                            |\n| Herramientas                 | Explícito en `mode: \"empty\"`; implícito en `mode: \"copilot-cli\"`.                         |\n| Sistema de archivos del host | Compartido por el proceso de tiempo de ejecución si hay herramientas de host disponibles. |\n\n`mode: \"empty\"` es lo que hace que los patrones de tiempo de ejecución compartidos sean viables: no se exponen herramientas del sistema operativo ambiente a menos que la aplicación se registre o las permita. Con `mode: \"copilot-cli\"`, el acceso al sistema de archivos del sistema operativo se comparte a través del proceso de host, por lo que no use ese modo para el modo de servidor multiusuario.\n\nEl estado de sesión se almacena en `COPILOT_HOME/session-state/{sessionId}` a menos que se enrute a través de `sessionFs`. Use identificadores de sesión únicos que incluyan su propio inquilino o límite de usuario y aplique el control de acceso antes de reanudar o eliminar sesiones.\n\n## Comparación de patrones\n\n| Pattern                                      | Se utiliza cuando                                                                                                                                              | Ventajas y desventajas                                                                                                                                                   |\n| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| Patrón 1: CLI aislada por usuario            | Necesita el límite de aislamiento más seguro o credenciales de proceso independientes por usuario.                                                             | Aislamiento fuerte; mayor costo de recursos. Consulte [Escalabilidad y multitenencia](/es/copilot/how-tos/copilot-sdk/setup/scaling).                                    |\n| Patrón 2: CLI compartida con `mode: \"empty\"` | Quiere que un entorno de ejecución sirva a muchos usuarios mientras la aplicación controla las herramientas, la autenticación y los identificadores de sesión. | Eficiente; requiere un registro cuidadoso de herramientas, tokens por sesión y comprobaciones de acceso a nivel de aplicación.                                           |\n| Patrón 3: híbrido                            | Diriges las tareas con uso intensivo de procesamiento a las sesiones en la nube y las tareas ligeras a las sesiones locales.                                   | Flexible; requiere encaminamiento de cargas de trabajo y gestión de directivas. Consulte [Sesiones en la nube](/es/copilot/how-tos/copilot-sdk/features/cloud-sessions). |\n\n### Patrón 2: CLI compartida con `mode: \"empty\"`\n\nEn este patrón, todos los usuarios se conectan a un pool de entornos de ejecución a través de tu backend. La aplicación realiza la autenticación de usuario, elige un identificador de sesión, pasa el token de GitHub del usuario en la sesión y proporciona una lista de permitidos de herramientas explícita.\n\n![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/setup-multi-tenancy-diagram-0.png)\n\nUse estas reglas:\n\n* Inicie siempre el cliente o el entorno de ejecución en `mode: \"empty\"`.\n* Use identificadores de sesión únicos y almacene los metadatos de propiedad en la base de datos de la aplicación.\n* Compruebe la titularidad antes de `resumeSession`, `deleteSession` o cualquier acción de la interfaz de usuario que haga referencia a un ID de sesión.\n* Pasa `gitHubToken` por sesión cuando las solicitudes deban ejecutarse como el usuario.\n* Registre solo las herramientas que necesita la sesión y prefiera listas de permitidos calificadas por el origen, como `custom:*` o `mcp:search_docs`.\n* Establezca `sessionIdleTimeoutSeconds` y elimine las sesiones de flujo de trabajo completadas explícitamente.\n\n## Dificultades habituales\n\n* Olvidando `mode: \"empty\"`. El modo predeterminado `copilot-cli` ofrece un comportamiento similar al de la CLI y puede exponer el sistema de archivos del host a través de herramientas del entorno.\n* Sin establecer `sessionIdleTimeoutSeconds`. Los servidores de larga duración pueden acumular sesiones inactivas si no las limpian.\n* Compartir uno `gitHubToken` entre usuarios en lugar de pasar un token por sesión.\n* Confiar en los identificadores de sesión proporcionados por el cliente sin comprobar la propiedad en el back-end.\n* Establecer `baseDirectory` en un cliente que se conecta a un entorno de ejecución existente y esperar que mueva el almacenamiento en tiempo de ejecución. Configure en su lugar el proceso de ejecución.\n* Permitir patrones de herramientas amplios, como `builtin:*` sin revisar si cada herramienta es adecuada para los usuarios.\n\n## Consulte también\n\n* [Escalabilidad y multitenencia](/es/copilot/how-tos/copilot-sdk/setup/scaling): topologías de implementación, patrones de almacenamiento y comparaciones de aislamiento\n* [Configuración de servicios back-end](/es/copilot/how-tos/copilot-sdk/setup/backend-services): ejecución del tiempo de ejecución en modo de servidor sin interfaz gráfica\n* [BYOK (traiga su propia clave)](/es/copilot/how-tos/copilot-sdk/auth/byok): uso de tus propias credenciales del proveedor de modelos\n* [Sesiones en la nube](/es/copilot/how-tos/copilot-sdk/features/cloud-sessions): enrutamiento del trabajo seleccionado a sesiones en la nube\n* [Reanudación y persistencia de sesión](/es/copilot/how-tos/copilot-sdk/features/session-persistence): gestión del estado de sesión reanudable\n* [Características](/es/copilot/how-tos/copilot-sdk/features): herramientas, eventos, enlaces y características avanzadas del SDK"}