Skip to main content

Déploiements multilocataires et serveurs

Exécutez le sdk Copilot dans les déploiements de serveurs multi-utilisateurs avec isolation par session pour l’état, l’authentification et les outils.

Meilleur pour : Produits SaaS, intégrations de partenaires, plateformes internes et services principaux qui gèrent les utilisateurs simultanés.

Utilisez ce guide quand

Utilisez ce guide lorsque vous créez :

  • Un produit SaaS multi-utilisateur qui intègre des agents basés sur Copilot
  • Un backend pour une intégration partenaire, comme un modèle de type Copilot Studio ou Fabric
  • Tout serveur qui gère les utilisateurs, espaces de travail, locataires ou demandes simultanés
  • Runtime partagé où plusieurs clients du KIT de développement logiciel (SDK) se connectent à un processus d’exécution Copilot

Ce guide est une sœur de Mise à l’échelle et multilocation. Utilisez ce guide pour la topologie, l’équilibrage de charge et les modèles de stockage. Utilisez ce guide pour les options au niveau du SDK et les choix d’isolation du runtime.

Options du Kit de développement logiciel (SDK) clés

OptionUtilisez-le pourRemarques
mode: "empty"Désactivation des outils de système d’exploitation ambiants et des paramètres CLI par défautRequis pour les scénarios multi-utilisateurs ou partagés.
sessionIdleTimeoutSecondsNettoyage des sessions inactivesDéfinissez un délai d’expiration côté serveur pour les processus de longue durée.
baseDirectoryIsolation par instance d’exécution COPILOT_HOMEIgnoré lors de la connexion à un runtime existant.
sessionFsRoutage du stockage du système de fichiers de session hors disque localAssocier des fournisseurs de systèmes de fichiers propres à chaque session.
RuntimeConnection.forUri(url)Partage d’un runtime déjà en cours d’exécutionLes noms de langue varient ; consultez les exemples ci-dessous.
Par session gitHubTokenLimiter l’authentification à l’utilisateur demandeurPréférez cela à un seul jeton d’utilisateur partagé.

mode: "empty"

mode: "empty" désactive le comportement facultatif Copilot CLI par défaut. En mode serveur multi-utilisateur, il s’agit de la base de référence sécurisée, car votre application doit décider explicitement quels outils, serveurs MCP, compétences et chemins d’accès à l’espace de travail qu’une session peut accéder.

N’utilisez pas la valeur par défaut mode: "copilot-cli" pour les serveurs partagés. Ce mode est destiné aux agents de codage de type CLI et peut exposer les fonctionnalités du système de fichiers hôte ambiant.

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

Configurez sessionIdleTimeoutSeconds sur des serveurs afin que les sessions inactives soient nettoyées automatiquement. Cela empêche les sessions zombies dans les processus de longue durée et réduit la sollicitation de la mémoire et du système de fichiers.

LanguageOption publique
TypeScriptsessionIdleTimeoutSeconds
Pythonsession_idle_timeout_seconds
GoSessionIdleTimeoutSeconds
.NETSessionIdleTimeoutSeconds
JavasetSessionIdleTimeoutSeconds(...)
Rustwith_session_idle_timeout_seconds(...)

Utilisez une valeur qui correspond à la durée de vie de la conversation de votre produit. Pour les back-ends de conversation, 15 à 30 minutes est généralement un bon point de départ. Pour les agents de flux de travail, utilisez un délai d’expiration plus long et une suppression explicite lorsque le flux de travail est terminé.

baseDirectory

baseDirectory définit COPILOT_HOME pour une instance d’exécution. Utilisez-le pour isoler l’état d’exécution, les informations d’authentification et les données de session pour chaque processus, pod, processus de travail ou périmètre du locataire.

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

Le runtime stocke l’état de session sous le fichier configuré COPILOT_HOME, y compris session-state/{sessionId}. Si votre application exécute plusieurs instances d’exécution, donnez à chaque instance un répertoire distinct, sauf si vous utilisez intentionnellement le stockage partagé.

Lorsque le SDK se connecte à un environnement d’exécution déjà en cours d’exécution avec RuntimeConnection.forUri(url), baseDirectory est ignoré par le client SDK. Configurez COPILOT_HOME plutôt sur le processus d’exécution.

sessionFs

sessionFs inscrit un fournisseur de système de fichiers de session personnalisé afin que les E/S de fichiers délimitées à la session puissent être routées via le stockage d’applications au lieu du disque local du runtime. Utilisez-le lorsque le disque local est éphémère, lorsque l’état de session doit être conservé dans un stockage objet, ou lorsqu’une plateforme doit imposer des chemins de stockage adaptés aux locataires.

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

Pour les langues qui exposent un rappel de fournisseur, configurez sessionFs au niveau du client et fournissez un gestionnaire de système de fichiers par session lors de la création ou de la reprise d’une session. Consultez Reprise de session et persistance pour connaître les concepts de persistance et les compromis de stockage.

Surfaces du SDK public vérifiées :

LanguageConfiguration au niveau du clientFournisseur par session
TypeScriptsessionFs
createSessionFsAdapter / rappels de fournisseurs
Pythonsession_fscreate_session_fs_handler
GoSessionFSCreateSessionFSProvider
.NETSessionFsCreateSessionFsProvider
Rustwith_session_fs(...)with_session_fs_provider(...)

Java n’expose pas actuellement une option sessionFs publique vérifiée. Ce guide n’affiche donc pas d’exemple Java sessionFs.

RuntimeConnection.forUri(url)

Utilisez une connexion d’exécution externe lorsque plusieurs clients du KIT de développement logiciel (SDK) doivent partager un runtime déjà en cours d’exécution. Cela est courant dans les services principaux où le processus d’exécution est géré séparément des gestionnaires de requêtes.

LanguageConnexion au runtime externe
TypeScriptRuntimeConnection.forUri(url)
PythonRuntimeConnection.for_uri(url)
Gocopilot.URIConnection{URL: url}
.NETRuntimeConnection.ForUri(url)
JavasetCliUrl(url)
RustTransport::External { host, port, connection_token }

Les runtimes externes gèrent leur propre authentification et stockage au niveau du processus. Transmettez des jetons propres à chaque session sur createSession ou resumeSession si vous avez besoin d’une authentification propre à l’utilisateur.

Par session gitHubToken

Définissez gitHubToken pour chaque session afin de limiter l’authentification GitHub à l’utilisateur demandeur. Cela diffère d’un jeton au niveau du client, qui authentifie le processus d’exécution.

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

Utilisez des jetons de session pour l’exclusion de contenus, le routage du modèle, la vérification des quotas et l’accès à Copilot propre à l’utilisateur. Évitez de partager un jeton de service entre les utilisateurs, sauf si votre produit utilise intentionnellement la sémantique du compte de service.

ID d’intégration

Les partenaires qui créent des agents de marque peuvent définir un ID d’intégration pour les demandes Mission Control. Le runtime lit GITHUB_COPILOT_INTEGRATION_ID et le marque comme en-tête HTTP Copilot-Integration-Id sur chaque requête Mission Control.

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

L’ID d’intégration par défaut est copilot-developer-cli. Utilisez une valeur stable telle que my-product-agent pour l’attribution et le routage. L’ID d’intégration est actuellement configuré par variable d’environnement uniquement ; il ne s’agit pas d’une option de KIT DE développement logiciel (SDK) de première classe.

Si le Kit de développement logiciel (SDK) génère le runtime, transmettez la variable d’environnement via l’option d’environnement client. Si vous vous connectez avec RuntimeConnection.forUri(url), définissez la variable d’environnement sur le processus d’exécution lui-même.

Garanties d’isolation au niveau de la session

L’isolation au niveau de la session signifie que le runtime conserve les informations de modèle et d’état spécifiques à l’utilisateur limitées à une session, et non dans un état partagé global.

SurfaceComportement d’isolation
Cache de liste de modèlesPar session. La recherche de modèle utilise le cache de liste de modèles de la session.
État de sessionPar identifiant de session sous COPILOT_HOME/session-state/{sessionId}.
identité GitHubPar session lorsque gitHubToken est défini sur la session.
ToolsExplicite en mode: "empty"; ambiante dans mode: "copilot-cli".
Système de fichiers hôtePartagé par le processus d’exécution si les outils hôtes sont disponibles.

mode: "empty" est ce qui rend les modèles d’exécution partagés viables : aucun outil de système d’exploitation ambiant n’est exposé, sauf si votre application s’inscrit ou les autorise. Avec mode: "copilot-cli", l’accès au système de fichiers du système d’exploitation est partagé via le processus hôte. N’utilisez donc pas ce mode pour le mode serveur multi-utilisateur.

L’état de session est stocké sous COPILOT_HOME/session-state/{sessionId} , sauf si vous l’acheminez jusqu’à sessionFs. Utilisez des ID de session uniques qui incluent votre propre locataire ou limite utilisateur et appliquez le contrôle d’accès avant de reprendre ou de supprimer des sessions.

Comparaison des modèles

MotifÀ utiliser lorsqueTrade-offs
Modèle 1 : interface CLI isolée par utilisateurVous avez besoin de la limite d’isolation la plus forte ou d’informations d’identification de processus distinctes par utilisateur.Isolation forte ; coût des ressources plus élevé. Consultez « Mise à l’échelle et multilocation ».
Modèle 2 : interface CLI partagée avec mode: "empty"Vous souhaitez qu’un runtime serve de nombreux utilisateurs pendant que votre application contrôle les outils, l’authentification et les ID de session.Efficace; nécessite une inscription minutieuse des outils, des jetons par session et des vérifications d’accès au niveau de l’application.
Modèle 3 : hybrideVous routez le travail lourd sur le calcul vers les sessions cloud et le travail léger vers les sessions locales.Flexible; nécessite le routage des charges de travail et la gestion des stratégies. Consultez « Sessions dans le cloud ».

Modèle 2 : interface CLI partagée avec mode: "empty"

Dans ce modèle, tous les utilisateurs se connectent via votre back-end à un pool d’exécution. L'application assure l'authentification des utilisateurs, choisit un identifiant de session, transmet le jeton GitHub de l'utilisateur dans la session et fournit une liste d'autorisation explicite d'outils.

Diagramme : Organigramme montrant le processus décrit.

Utilisez ces règles :

  • Démarrez toujours le client ou le runtime dans mode: "empty".
  • Utilisez des ID de session uniques et stockez les métadonnées de propriété dans votre base de données d’application.
  • Vérifiez la propriété avant resumeSession, deleteSessionou toute action d’interface utilisateur qui référence un ID de session.
  • Transmettez gitHubToken par session lorsque les requêtes doivent être exécutées en tant qu’utilisateur.
  • Inscrivez uniquement les outils dont la session a besoin et préférez les listes d’autorisation qualifiées sources telles que custom:* ou mcp:search_docs.
  • Définissez et supprimez sessionIdleTimeoutSeconds explicitement les sessions de flux de travail terminées.

Pièges courants

  • Oubli de mode: "empty". Le mode par défaut copilot-cli expose le comportement de style CLI et peut exposer le système de fichiers hôte via des outils ambiants.
  • Ne pas définir sessionIdleTimeoutSeconds. Les serveurs de longue durée peuvent accumuler des sessions inactives s’ils ne les nettoient pas.
  • Partage d’un gitHubToken entre les utilisateurs au lieu de transmettre un jeton propre à chaque session.
  • Approbation des ID de session fournis par le client sans vérifier la propriété dans votre back-end.
  • Définir baseDirectory sur un client qui se connecte à un runtime existant en s’attendant à ce que cela déplace le stockage du runtime. Configurez plutôt le processus d’exécution.
  • Autoriser des modèles d’outils étendus tels que builtin:* sans examiner si chaque outil est approprié pour vos utilisateurs.

Voir également :