Skip to main content

Implementaciones multiinquilino y servidor

Ejecute el SDK de Copilot en implementaciones de servidor multiusuario con aislamiento por sesión para el estado, la autenticación y las herramientas.

Lo mejor para: Productos SaaS, integraciones de asociados, plataformas internas y servicios back-end que controlan usuarios simultáneos.

Use esta guía cuando

Utiliza esta guía cuando estés compilando:

  • Un producto SaaS multiusuario que inserta agentes con tecnología Copilot
  • Un backend para una integración de socio, como un patrón de Copilot Studio o de estilo Fabric
  • Cualquier servidor que controle usuarios simultáneos, áreas de trabajo, inquilinos o solicitudes
  • 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

Esta guía es una hermana de Escalabilidad y multitenencia. 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.

Opciones clave del SDK

OpciónÚselo paraNotas
mode: "empty"Deshabilitación de las herramientas del sistema operativo ambiental y los valores predeterminados de la CLINecesario para escenarios multiusuario o compartido.
sessionIdleTimeoutSecondsDepuración de sesiones inactivasEstablezca un tiempo de espera del lado servidor para los procesos de ejecución prolongada.
baseDirectoryAislamiento de COPILOT_HOME por instancia del entorno de ejecuciónSe omite al conectarse a un entorno de ejecución existente.
sessionFsEnrutamiento del almacenamiento del sistema de archivos de sesión fuera del disco localEmparejar con proveedores de sistema de archivos por sesión.
RuntimeConnection.forUri(url)Uso compartido de un entorno de ejecución ya en ejecuciónLos nombres de idioma varían; consulte los ejemplos siguientes.
Por sesión gitHubTokenLimitar la autenticación al usuario solicitanteEs preferible a un solo token de usuario compartido.

mode: "empty"

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.

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

TypeScript
import { CopilotClient, RuntimeConnection } from "@github/copilot-sdk";

// baseDirectory and sessionIdleTimeoutSeconds apply when the SDK spawns the
// runtime. With RuntimeConnection.forUri(...) configure COPILOT_HOME and the
// idle timeout on the runtime process itself.
const client = new CopilotClient({
    mode: "empty",
    connection: RuntimeConnection.forUri(process.env.COPILOT_RUNTIME_URL!),
});

const session = await client.createSession({
    sessionId: `user-${user.id}-${crypto.randomUUID()}`,
    model: "gpt-4.1",
    availableTools: ["custom:lookupOrder", "custom:createTicket"],
    gitHubToken: user.githubToken,
});
Python
from copilot import CopilotClient, RuntimeConnection
from copilot.session import PermissionHandler

client = CopilotClient(
    mode="empty",
    base_directory=f"/var/lib/my-app/copilot/{runtime_instance_id}",
    session_idle_timeout_seconds=900,
    connection=RuntimeConnection.for_uri(runtime_url),
)
await client.start()

session = await client.create_session(
    session_id=f"user-{user.id}-{request_id}",
    model="gpt-4.1",
    available_tools=["custom:lookupOrder", "custom:createTicket"],
    github_token=user.github_token,
    on_permission_request=PermissionHandler.approve_all,
)
Go
package main

import (
    "context"
    "fmt"

    copilot "github.com/github/copilot-sdk/go"
)

type appUser struct {
    ID          string
    GitHubToken string
}

func main() {
    ctx := context.Background()
    runtimeInstanceID := "instance-1"
    runtimeURL := "http://127.0.0.1:8080"
    requestID := "req-1"
    user := appUser{ID: "alice", GitHubToken: "YOUR_GITHUB_TOKEN"}

    client := copilot.NewClient(&copilot.ClientOptions{
        Mode:                      copilot.ModeEmpty,
        BaseDirectory:             fmt.Sprintf("/var/lib/my-app/copilot/%s", runtimeInstanceID),
        SessionIdleTimeoutSeconds: 900,
        Connection:                copilot.URIConnection{URL: runtimeURL},
    })

    session, err := client.CreateSession(ctx, &copilot.SessionConfig{
        SessionID:      fmt.Sprintf("user-%s-%s", user.ID, requestID),
        Model:          "gpt-4.1",
        AvailableTools: []string{"custom:lookupOrder", "custom:createTicket"},
        GitHubToken:    user.GitHubToken,
    })
    _ = session
    _ = err
}
client := copilot.NewClient(&copilot.ClientOptions{
    Mode:                      copilot.ModeEmpty,
    BaseDirectory:             fmt.Sprintf("/var/lib/my-app/copilot/%s", runtimeInstanceID),
    SessionIdleTimeoutSeconds: 900,
    Connection:                copilot.URIConnection{URL: runtimeURL},
})

session, err := client.CreateSession(ctx, &copilot.SessionConfig{
    SessionID:      fmt.Sprintf("user-%s-%s", user.ID, requestID),
    Model:          "gpt-4.1",
    AvailableTools: []string{"custom:lookupOrder", "custom:createTicket"},
    GitHubToken:    user.GitHubToken,
})
.NET
using GitHub.Copilot;

var runtimeInstanceId = "instance-1";
var runtimeUrl = "http://127.0.0.1:8080";
var requestId = "req-1";
var user = new { Id = "alice", GitHubToken = "YOUR_GITHUB_TOKEN" };

var client = new CopilotClient(new CopilotClientOptions
{
    Mode = CopilotClientMode.Empty,
    BaseDirectory = $"/var/lib/my-app/copilot/{runtimeInstanceId}",
    SessionIdleTimeoutSeconds = 900,
    Connection = RuntimeConnection.ForUri(runtimeUrl),
});

await using var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = $"user-{user.Id}-{requestId}",
    Model = "gpt-4.1",
    AvailableTools = ["custom:lookupOrder", "custom:createTicket"],
    GitHubToken = user.GitHubToken,
});
var client = new CopilotClient(new CopilotClientOptions
{
    Mode = CopilotClientMode.Empty,
    BaseDirectory = $"/var/lib/my-app/copilot/{runtimeInstanceId}",
    SessionIdleTimeoutSeconds = 900,
    Connection = RuntimeConnection.ForUri(runtimeUrl),
});

await using var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = $"user-{user.Id}-{requestId}",
    Model = "gpt-4.1",
    AvailableTools = ["custom:lookupOrder", "custom:createTicket"],
    GitHubToken = user.GitHubToken,
});
Java
import java.util.List;
import com.github.copilot.CopilotClient;
import com.github.copilot.rpc.CopilotClientOptions;
import com.github.copilot.rpc.CopilotClientMode;
import com.github.copilot.rpc.SessionConfig;

public class MultiTenancyExample {
    record User(String id, String gitHubToken) {}

    public static void main(String[] args) throws Exception {
        String runtimeUrl = "http://localhost:4321";
        String requestId = "req-1";
        User user = new User("u1", "ghu_token");

        // setCopilotHome and setSessionIdleTimeoutSeconds are ignored when
        // setCliUrl is used; configure those on the runtime process instead.
        var client = new CopilotClient(new CopilotClientOptions()
            .setMode(CopilotClientMode.EMPTY)
            .setCliUrl(runtimeUrl)
        );

        var session = client.createSession(new SessionConfig()
            .setSessionId("user-" + user.id() + "-" + requestId)
            .setModel("gpt-4.1")
            .setAvailableTools(List.of("custom:lookupOrder", "custom:createTicket"))
            .setGitHubToken(user.gitHubToken())
        ).get();
    }
}
// setCopilotHome and setSessionIdleTimeoutSeconds are ignored when
// setCliUrl is used; configure those on the runtime process instead.
var client = new CopilotClient(new CopilotClientOptions()
    .setMode(CopilotClientMode.EMPTY)
    .setCliUrl(runtimeUrl)
);

var session = client.createSession(new SessionConfig()
    .setSessionId("user-" + user.id() + "-" + requestId)
    .setModel("gpt-4.1")
    .setAvailableTools(List.of("custom:lookupOrder", "custom:createTicket"))
    .setGitHubToken(user.gitHubToken())
).get();
Rust
use std::path::PathBuf;
use github_copilot_sdk::{Client, ClientOptions, Transport};
use github_copilot_sdk::mode::ClientMode;
use github_copilot_sdk::types::SessionConfig;

let client = Client::start(
    ClientOptions::new()
        .with_mode(ClientMode::Empty)
        .with_base_directory(PathBuf::from(format!(
            "/var/lib/my-app/copilot/{runtime_instance_id}"
        )))
        .with_session_idle_timeout_seconds(900)
        .with_transport(Transport::External {
            host: runtime_host.to_string(),
            port: runtime_port,
            connection_token: None,
        }),
).await?;

let session = client.create_session(
    SessionConfig::default()
        .with_session_id(format!("user-{}-{request_id}", user.id))
        .with_model("gpt-4.1")
        .with_available_tools(["custom:lookupOrder", "custom:createTicket"])
        .with_github_token(user.github_token),
).await?;

sessionIdleTimeoutSeconds

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

LanguageOpción pública
TypeScriptsessionIdleTimeoutSeconds
Pythonsession_idle_timeout_seconds
IrSessionIdleTimeoutSeconds
.NETSessionIdleTimeoutSeconds
JavasetSessionIdleTimeoutSeconds(...)
Óxidowith_session_idle_timeout_seconds(...)

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

baseDirectory

baseDirectory establece COPILOT_HOME para una instancia en tiempo de ejecución. Úselo para aislar el estado en tiempo de ejecución, las credenciales y los datos de sesión por proceso, pod, trabajador o límite entre inquilinos.

const client = new CopilotClient({
    mode: "empty",
    baseDirectory: `/var/lib/my-app/copilot/runtime-${process.env.HOSTNAME}`,
    sessionIdleTimeoutSeconds: 900,
});

El entorno de ejecución almacena el estado de la sesión en el COPILOT_HOME configurado, incluyendo 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.

Cuando 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. Configure COPILOT_HOME en su lugar en el proceso en tiempo de ejecución.

sessionFs

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.

const client = new CopilotClient({
    mode: "empty",
    sessionFs: {
        initialCwd: "/workspace",
        sessionStatePath: "/session-state",
        conventions: "posix",
    },
});

Para los lenguajes que exponen una función de retorno del proveedor, configure sessionFs en el cliente y proporcione un controlador del sistema de archivos para cada sesión al crear o reanudar una sesión. Consulte Reanudación y persistencia de sesión para conocer los conceptos de persistencia y las ventajas de almacenamiento.

Superficies comprobadas del SDK público:

LanguageConfiguración de nivel de clienteProveedor por sesión
TypeScriptsessionFs
createSessionFsAdapter / funciones de devolución de llamada del proveedor
Pythonsession_fscreate_session_fs_handler
IrSessionFSCreateSessionFSProvider
.NETSessionFsCreateSessionFsProvider
Óxidowith_session_fs(...)with_session_fs_provider(...)

Java no expone actualmente una opción de <c0 pública comprobada />, por lo que esta guía no muestra un ejemplo de Java .

RuntimeConnection.forUri(url)

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

LanguageConexión externa en tiempo de ejecución
TypeScriptRuntimeConnection.forUri(url)
PythonRuntimeConnection.for_uri(url)
Ircopilot.URIConnection{URL: url}
.NETRuntimeConnection.ForUri(url)
JavasetCliUrl(url)
ÓxidoTransport::External { host, port, connection_token }

Los entornos de ejecución externos administran su propia autenticación y almacenamiento de nivel de proceso. Pase tokens de sesión en createSession o resumeSession cuando necesite autenticación específica para cada usuario.

Por sesión gitHubToken

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

const session = await client.createSession({
    sessionId: `user-${user.id}-support`,
    model: "gpt-4.1",
    availableTools: ["custom:*"],
    gitHubToken: user.githubToken,
});

Use tokens por sesión para la exclusión de contenido, el enrutamiento de modelos, las comprobaciones de cuota y el acceso 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.

Id. de integración

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

GITHUB_COPILOT_INTEGRATION_ID=my-product-agent copilot --headless --port 4321

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

Si 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 a través de RuntimeConnection.forUri(url), establezca la variable de entorno en el propio proceso de ejecución.

Garantías de aislamiento de nivel de sesión

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

SuperficieComportamiento de aislamiento
Caché de lista de modelosPor sesión. La búsqueda de modelos usa la caché de lista de modelos de la sesión.
Estado de sesiónPor identificador de sesión debajo de COPILOT_HOME/session-state/{sessionId}.
identidad de GitHubPor sesión cuando gitHubToken se establece en la sesión.
HerramientasExplícito en mode: "empty"; implícito en mode: "copilot-cli".
Sistema de archivos del hostCompartido por el proceso en tiempo de ejecución si hay herramientas de host disponibles.

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.

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

Comparación de patrones

PatternSe utiliza cuandoVentajas y desventajas
Patrón 1: CLI aislada por usuarioNecesita 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.
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.
Patrón 3: híbridoDiriges 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.

Patrón 2: CLI compartida con mode: "empty"

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

Diagrama: Diagrama de flujo que muestra el proceso descrito.

Use estas reglas:

  • Inicie siempre el cliente o el entorno de ejecución en mode: "empty".
  • Use identificadores de sesión únicos y almacene los metadatos de propiedad en la base de datos de la aplicació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.
  • Pasa gitHubToken por sesión cuando las solicitudes deban ejecutarse como el usuario.
  • Registre solo las herramientas que necesita la sesión y prefiera listas de permitidos calificadas por el origen, como custom:* o mcp:search_docs.
  • Establezca sessionIdleTimeoutSeconds y elimine las sesiones de flujo de trabajo completadas explícitamente.

Dificultades habituales

  • Olvidar 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.
  • Sin establecer sessionIdleTimeoutSeconds. Los servidores de larga duración pueden acumular sesiones inactivas si no las limpian.
  • Compartir uno gitHubToken entre usuarios en lugar de pasar un token por sesión.
  • Confiar en los identificadores de sesión proporcionados por el cliente sin comprobar la propiedad en el back-end.
  • 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.
  • Permitir patrones de herramientas amplios, como builtin:* sin revisar si cada herramienta es adecuada para los usuarios.

Consulte también