# Multilocataire et déploiements de serveurs

Le mode serveur multi-utilisateur consiste à exécuter le SDK Copilot à partir d’un code côté serveur qui dessert plus d’un utilisateur, locataire, espace de travail ou compte d’intégration. Dans cette configuration, l’application possède le routage et l’autorisation de demande, tandis que le SDK et le runtime fournissent l’état par session, l’authentification par session et l’inscription d’outils explicites afin que la session d’un utilisateur n’hérite pas des outils ou de l’identité d’un autre utilisateur.

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

**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 multilocataire](/fr/copilot/how-tos/copilot-sdk/setup/scaling). 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

| Option                          | Utilisez-le pour                                                                             | Remarques                                                                         |
| ------------------------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `mode: "empty"`                 | Désactivation des outils de système d’exploitation ambiants et des paramètres CLI par défaut | Requis pour les scénarios multi-utilisateurs ou partagés.                         |
| `sessionIdleTimeoutSeconds`     | Nettoyage des sessions inactives                                                             | Définissez un délai d’expiration côté serveur pour les processus de longue durée. |
| `baseDirectory`                 | Isolation par instance d’exécution `COPILOT_HOME`                                            | Ignoré lors de la connexion à un runtime existant.                                |
| `sessionFs`                     | Routage du stockage du système de fichiers de session hors disque local                      | Associez-les à des fournisseurs de système de fichiers par session.               |
| `RuntimeConnection.forUri(url)` | Partage d’un runtime déjà en cours d’exécution                                               | Les noms de langue varient ; consultez les exemples ci-dessous.                   |
| Par session `gitHubToken`       | Limiter l'authentification à l'utilisateur à l'origine de la demande                         | Pré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.

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```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-5.4",
    availableTools: ["custom:lookupOrder", "custom:createTicket"],
    gitHubToken: user.githubToken,
});
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```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-5.4",
    available_tools=["custom:lookupOrder", "custom:createTicket"],
    github_token=user.github_token,
    on_permission_request=PermissionHandler.approve_all,
)
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
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-5.4",
    AvailableTools: []string{"custom:lookupOrder", "custom:createTicket"},
    GitHubToken:    user.GitHubToken,
})
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
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-5.4",
    AvailableTools = ["custom:lookupOrder", "custom:createTicket"],
    GitHubToken = user.GitHubToken,
});
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

```java
// 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-5.4")
    .setAvailableTools(List.of("custom:lookupOrder", "custom:createTicket"))
    .setGitHubToken(user.gitHubToken())
).get();
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```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-5.4")
        .with_available_tools(["custom:lookupOrder", "custom:createTicket"])
        .with_github_token(user.github_token),
).await?;
```

</div>

</div>

### `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.

| Language   | Option publique                          |
| ---------- | ---------------------------------------- |
| TypeScript | `sessionIdleTimeoutSeconds`              |
| Python     | `session_idle_timeout_seconds`           |
| Go         | `SessionIdleTimeoutSeconds`              |
| .NET       | `SessionIdleTimeoutSeconds`              |
| Java       | `setSessionIdleTimeoutSeconds(...)`      |
| Rust       | `with_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 cette fonctionnalité pour isoler l'état du runtime, les informations d'identification et les données de session par processus, Pod, Worker ou limite de locataire.

```typescript
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.

```typescript
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](/fr/copilot/how-tos/copilot-sdk/features/session-persistence) pour connaître les concepts de persistance et les compromis de stockage.

Surfaces du SDK public vérifiées :

| Language                                          | Configuration au niveau du client | Fournisseur par session         |
| ------------------------------------------------- | --------------------------------- | ------------------------------- |
| TypeScript                                        | `sessionFs`                       |                                 |
| `createSessionFsAdapter` / rappels du fournisseur |                                   |                                 |
| Python                                            | `session_fs`                      | `create_session_fs_handler`     |
| Go                                                | `SessionFS`                       | `CreateSessionFSProvider`       |
| .NET                                              | `SessionFs`                       | `CreateSessionFsProvider`       |
| Rust                                              | `with_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.

| Language   | Connexion au runtime externe                           |
| ---------- | ------------------------------------------------------ |
| TypeScript | `RuntimeConnection.forUri(url)`                        |
| Python     | `RuntimeConnection.for_uri(url)`                       |
| Go         | `copilot.URIConnection{URL: url}`                      |
| .NET       | `RuntimeConnection.ForUri(url)`                        |
| Java       | `setCliUrl(url)`                                       |
| Rust       | `Transport::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.

```typescript
const session = await client.createSession({
    sessionId: `user-${user.id}-support`,
    model: "gpt-5.4",
    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.

```bash
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.

| Surface                   | Comportement d’isolation                                                                |
| ------------------------- | --------------------------------------------------------------------------------------- |
| Cache de liste de modèles | Par session. La recherche de modèle utilise le cache de liste de modèles de la session. |
| État de session           | Par identifiant de session sous `COPILOT_HOME/session-state/{sessionId}`.               |
| identité GitHub           | Par session lorsque `gitHubToken` est défini sur la session.                            |
| Tools                     | Explicite en `mode: "empty"`; ambiante dans `mode: "copilot-cli"`.                      |
| Système de fichiers hôte  | Partagé 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 lorsque                                                                                                                                      | Trade-offs                                                                                                                                                                           |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Modèle 1 : interface CLI isolée par utilisateur        | Vous 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 multilocataire](/fr/copilot/how-tos/copilot-sdk/setup/scaling) ».                                 |
| 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 : hybride                                     | Vous 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](/fr/copilot/how-tos/copilot-sdk/features/cloud-sessions) ». |

### 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.](/assets/images/help/copilot/copilot-sdk/setup-multi-tenancy-diagram-0.png)

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`, `deleteSession`ou 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.
* Sans 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 :

* [Mise à l'échelle et multilocataire](/fr/copilot/how-tos/copilot-sdk/setup/scaling) : topologies de déploiement, modèles de stockage et comparaisons d’isolation
* [Configuration des services principaux](/fr/copilot/how-tos/copilot-sdk/setup/backend-services) : exécution du runtime en mode serveur sans tête
* [BYOK (apportez votre propre clé)](/fr/copilot/how-tos/copilot-sdk/auth/byok) : utilisation de vos propres identifiants de fournisseur de modèle
* [Sessions dans le cloud](/fr/copilot/how-tos/copilot-sdk/features/cloud-sessions) : routage sélectionné du travail vers des sessions cloud
* [Reprise de session et persistance](/fr/copilot/how-tos/copilot-sdk/features/session-persistence) : gestion de l’état de session pouvant être repris
* [Fonctionnalités](/fr/copilot/how-tos/copilot-sdk/features) : outils, événements, hooks et fonctionnalités avancées du Kit de développement logiciel (SDK)