# Mandantenfähigkeit und Serverbereitstellungen

Der Mehrbenutzerservermodus bedeutet, dass das Copilot SDK aus Back-End-Code ausgeführt wird, der mehr als ein menschliches, Mandanten-, Arbeitsbereichs- oder Integrationskonto bedient. In dieser Konfiguration übernimmt die Anwendung das Routing von Anfragen und die Autorisierung, während das SDK und die Laufzeit sitzungsspezifischen Zustand, sitzungsspezifische Authentifizierung und die explizite Registrierung von Tools bereitstellen, damit die Sitzung eines Benutzers weder die Tools noch die Identität eines anderen Benutzers übernimmt.

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

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

**Am besten geeignet für:** SaaS-Produkte, Partnerintegrationen, interne Plattformen und Back-End-Dienste, die gleichzeitige Benutzer verarbeiten.

## Verwenden Sie dieses Handbuch, wenn

Verwenden Sie diesen Leitfaden, wenn Sie Folgendes erstellen:

* Ein Mehrbenutzer-SaaS-Produkt, das Copilot-gestützte Agenten einbettet
* Ein Backend für eine Partnerintegration, beispielsweise ein Muster im Stil von Copilot Studio oder Fabric
* Jeder Server, der gleichzeitige Benutzer, Arbeitsbereiche, Mandanten oder Anforderungen verarbeitet
* Eine freigegebene Laufzeit, bei der mehrere SDK-Clients eine Verbindung mit einem Copilot Laufzeitprozess herstellen

Dieser Leitfaden ist eine Schwester von [Skalierung und Mehrinstanzenfähigkeit](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/setup/scaling). Verwenden Sie dieses Handbuch für Topologie, Lastenausgleich und Speichermuster. Verwenden Sie dieses Handbuch für Optionen auf SDK-Ebene und Optionen für die Laufzeitisolation.

## Schlüssel-SDK-Optionen

| Auswahl                         | Verwenden Sie es für                                                         | Hinweise                                                                              |
| ------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `mode: "empty"`                 | Deaktivieren von Umgebungsbetriebssystem-Tools und CLI-Standardwerten        | Erforderlich für Szenarien mit mehreren Benutzern oder gemeinsam genutzten Szenarien. |
| `sessionIdleTimeoutSeconds`     | Bereinigen von inaktiven Sitzungen                                           | Festlegen eines serverseitigen Timeouts für lange ausgeführte Prozesse.               |
| `baseDirectory`                 | Isolieren von `COPILOT_HOME` pro Laufzeitinstanz                             | Wird ignoriert, wenn eine Verbindung mit einer vorhandenen Laufzeit hergestellt wird. |
| `sessionFs`                     | Umleitung des Dateisystemspeichers für Sitzungen weg vom lokalen Datenträger | Kombinieren Sie dies mit Dateisystemanbietern pro Sitzung.                            |
| `RuntimeConnection.forUri(url)` | Teilen einer bereits laufenden Runtime                                       | Sprachnamen variieren; siehe Beispiele unten.                                         |
| Pro Sitzung `gitHubToken`       | Einschränken der Authentifizierung auf den anfordernden Benutzer             | Verwenden Sie dies anstelle eines gemeinsam genutzten Benutzertokens.                 |

### `mode: "empty"`

`mode: "empty"` deaktiviert standardmäßig optionales Copilot CLI-Verhalten. Im Servermodus mit mehreren Benutzern ist dies der sichere Basisplan, da Ihre Anwendung explizit entscheiden muss, auf welche Tools, MCP-Server, Fähigkeiten und Arbeitsbereichspfade eine Sitzung zugreifen kann.

Verwenden Sie für gemeinsam genutzte Server nicht die Standardeinstellung `mode: "copilot-cli"`. Dieser Modus ist für CLI-ähnliche Codierungs-Agents vorgesehen und kann Umgebungshost-Dateisystemfunktionen verfügbar machen.

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

Legen Sie `sessionIdleTimeoutSeconds` auf Servern fest, damit inaktive Sitzungen automatisch beendet werden. Dies verhindert Zombie-Sitzungen in lang laufenden Prozessen und reduziert den Speicher- und Dateisystemdruck.

| Language   | Öffentliche Option                       |
| ---------- | ---------------------------------------- |
| Typescript | `sessionIdleTimeoutSeconds`              |
| Python     | `session_idle_timeout_seconds`           |
| Go         | `SessionIdleTimeoutSeconds`              |
| .NET       | `SessionIdleTimeoutSeconds`              |
| Java       | `setSessionIdleTimeoutSeconds(...)`      |
| Rust       | `with_session_idle_timeout_seconds(...)` |

Verwenden Sie einen Wert, der der Lebensdauer einer Konversation in Ihrem Produkt entspricht. Bei Chat-Back-Ends ist in der Regel 15 bis 30 Minuten ein guter Ausgangspunkt. Verwenden Sie für Workflow-Agents ein längeres Timeout und explizites Löschen, wenn der Workflow abgeschlossen ist.

### `baseDirectory`

`baseDirectory` legt `COPILOT_HOME` für eine Laufzeitinstanz fest. Verwenden Sie dies, um Laufzeitstatus, Anmeldeinformationen und Sitzungsdaten pro Prozess, Pod, Worker oder Mandantengrenze zu isolieren.

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

Die Laufzeit speichert den Sitzungsstatus unter dem konfigurierten `COPILOT_HOME`, einschließlich `session-state/{sessionId}`. Wenn Ihre App mehrere Laufzeitinstanzen ausführt, weisen Sie jeder Instanz ein eigenes Verzeichnis zu, es sei denn, Sie verwenden absichtlich freigegebenen Speicher.

Wenn das SDK eine Verbindung mit einer bereits ausgeführten Laufzeit mit `RuntimeConnection.forUri(url)` herstellt, wird `baseDirectory` vom SDK-Client ignoriert. Konfigurieren Sie `COPILOT_HOME` stattdessen für den Laufzeitprozess.

### `sessionFs`

`sessionFs` registriert einen benutzerdefinierten Sitzungsdateisystemanbieter, sodass sitzungsbezogene Datei-E/A über den Anwendungsspeicher statt über die lokale Festplatte der Laufzeitumgebung geleitet werden kann. Verwenden Sie sie, wenn der lokale Datenträger kurzlebig ist, wenn der Sitzungszustand im Objektspeicher gespeichert werden muss oder wenn eine Plattform mandantenbezogene Speicherpfade erzwingen muss.

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

Konfigurieren Sie für Sprachen, die einen Provider-Callback bereitstellen, `sessionFs` auf Client-Ebene, und stellen Sie beim Erstellen oder Fortsetzen einer Sitzung einen sitzungsspezifischen Dateisystem-Handler bereit. Siehe [Wiederaufnahme und Persistenz der Sitzung](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/session-persistence) für Persistenzkonzepte und Speicherabschläge.

Überprüfte öffentliche SDK-Oberflächen:

| Language                                    | Konfiguration auf Clientebene | Sitzungsbasierter Anbieter      |
| ------------------------------------------- | ----------------------------- | ------------------------------- |
| Typescript                                  | `sessionFs`                   |                                 |
| `createSessionFsAdapter` / Anbieterrückrufe |                               |                                 |
| Python                                      | `session_fs`                  | `create_session_fs_handler`     |
| Go                                          | `SessionFS`                   | `CreateSessionFSProvider`       |
| .NET                                        | `SessionFs`                   | `CreateSessionFsProvider`       |
| Rust                                        | `with_session_fs(...)`        | `with_session_fs_provider(...)` |

Java stellt derzeit keine überprüfte öffentliche `sessionFs`-Option zur Verfügung, sodass in diesem Handbuch kein Java `sessionFs`-Beispiel angezeigt wird.

### `RuntimeConnection.forUri(url)`

Verwenden Sie eine externe Laufzeitverbindung, wenn mehrere SDK-Clients eine bereits ausgeführte Laufzeit gemeinsam nutzen sollten. Dies ist in Back-End-Diensten üblich, bei denen der Laufzeitprozess getrennt von Anforderungshandlern verwaltet wird.

| Language   | Externe Laufzeitverbindung                             |
| ---------- | ------------------------------------------------------ |
| 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 }` |

Externe Laufzeiten verwalten ihre eigene Authentifizierung und Speicherung auf Prozessebene. Übergeben Sie Token pro Sitzung an `createSession` oder `resumeSession` wenn Sie eine benutzerspezifische Authentifizierung benötigen.

### Pro Sitzung `gitHubToken`

Legen Sie `gitHubToken` in jeder Sitzung fest, um die GitHub-Authentifizierung auf den anfordernden Benutzer zu beschränken. Dies unterscheidet sich von einem Token auf Clientebene, das den Laufzeitprozess authentifiziert.

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

Verwenden Sie sitzungsbezogene Tokens für den Ausschluss von Inhalten, das Modellrouting, Kontingentprüfungen und den benutzerspezifischen Copilot-Zugriff. Vermeiden Sie die Freigabe eines Diensttokens für alle Benutzer, es sei denn, Ihr Produkt verwendet absichtlich die Semantik des Dienstkontos.

## Integration-ID

Partner, die Branding-Agents erstellen, können eine Integrations-ID für Mission Control-Anforderungen festlegen. Die Laufzeit liest `GITHUB_COPILOT_INTEGRATION_ID` und stempelt sie als HTTP-Header `Copilot-Integration-Id` bei jeder Mission Control-Anforderung.

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

Die Standardintegrations-ID lautet `copilot-developer-cli`. Verwenden Sie einen stabilen Wert wie `my-product-agent` für Attribution und Routing. Die Integrations-ID wird derzeit nur von der Umgebungsvariablen konfiguriert. Es handelt sich nicht um eine erstklassige SDK-Option.

Wenn das SDK die Laufzeit startet, übergeben Sie die Umgebungsvariable über die Client-Umgebungsoption. Wenn Sie eine Verbindung mit `RuntimeConnection.forUri(url)` herstellen, legen Sie die Umgebungsvariable direkt für den Laufzeitprozess selbst fest.

## Isolationsgarantien auf Sitzungsebene

Die Isolation auf Sitzungsebene bedeutet, dass die Laufzeit benutzerspezifische Modell- und Zustandsinformationen auf eine Sitzung beschränkt und nicht in einem global gemeinsam genutzten Zustand hält.

| Oberfläche            | Isolationsverhalten                                                           |
| --------------------- | ----------------------------------------------------------------------------- |
| Cache der Modellliste | Pro Sitzung. Die Modellsuche verwendet den Cache der Modellliste der Sitzung. |
| Sitzungszustand       | Pro Sitzungs-ID unter `COPILOT_HOME/session-state/{sessionId}`.               |
| GitHub Identität      | Pro Sitzung, wenn `gitHubToken` für die Sitzung festgelegt ist.               |
| Tools                 | Explizit in `mode: "empty"`; umgebend in `mode: "copilot-cli"`.               |
| Dateisystem des Hosts | Wird vom Laufzeitprozess gemeinsam genutzt, wenn Host-Tools verfügbar sind.   |

`mode: "empty"` macht freigegebene Laufzeitmuster praktikabel: Es werden keine umgebenden Betriebssystemtools verfügbar gemacht, es sei denn, Ihre Anwendung registriert oder lässt sie zu. Mit `mode: "copilot-cli"` wird der Zugriff auf das Dateisystem des Betriebssystems über den Hostprozess gemeinsam genutzt. Verwenden Sie diesen Modus daher nicht im Mehrbenutzer-Servermodus.

Der Sitzungszustand wird unter `COPILOT_HOME/session-state/{sessionId}` gespeichert, es sei denn, Sie leiten ihn über `sessionFs` um. Verwenden Sie eindeutige Sitzungs-IDs, die Ihre eigene Mandanten- oder Benutzergrenze enthalten, und erzwingen Sie die Zugriffssteuerung, bevor Sie Sitzungen fortsetzen oder löschen.

## Mustervergleich

| Schema                                       | Verwenden Sie, wenn                                                                                                         | Trade-offs                                                                                                                                                                |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Muster 1: isolierte CLI pro Benutzer         | Sie benötigen die stärkste Isolationsgrenze oder separate Prozessanmeldeinformationen pro Benutzer.                         | Starke Isolation; höhere Ressourcenkosten. Siehe [Skalierung und Mehrinstanzenfähigkeit](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/setup/scaling).          |
| Muster 2: gemeinsame CLI mit `mode: "empty"` | Sie möchten, dass eine Laufzeit viele Benutzer bedient, während Ihre App Tools, Authentifizierung und Sitzungs-IDs steuert. | Effiziente; erfordert sorgfältige Toolregistrierung, Zugriffstoken pro Sitzung und Zugriffsprüfungen auf Anwendungsebene.                                                 |
| Muster 3: Hybrid                             | Sie verlagern rechenintensive Aufgaben in Cloud-Sitzungen und weniger rechenintensive Aufgaben in lokale Sitzungen.         | Flexibel; erfordert Workload-Routing und Richtlinienverwaltung. Siehe [Cloud-Sitzungen](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/cloud-sessions). |

### Muster 2: gemeinsame CLI mit `mode: "empty"`

In diesem Muster verbinden sich alle Benutzer über Ihr Back-End mit einem Laufzeitpool. Die Anwendung führt die Benutzerauthentifizierung aus, wählt eine Sitzungs-ID aus, übergibt das GitHub-Token des Benutzers in der Sitzung und stellt eine explizite Tool-Zulassungsliste bereit.

![Diagramm: Flussdiagramm mit dem beschriebenen Prozess.](/assets/images/help/copilot/copilot-sdk/setup-multi-tenancy-diagram-0.png)

Verwenden Sie die folgenden Regeln:

* Starten Sie den Client oder die Runtime immer in `mode: "empty"`.
* Verwenden Sie eindeutige Sitzungs-IDs, und speichern Sie Besitzermetadaten in Ihrer Anwendungsdatenbank.
* Überprüfen Sie die Inhaberschaft vor `resumeSession`, `deleteSession` oder jeder UI-Aktion, die auf eine Sitzungs-ID verweist.
* Übergeben Sie `gitHubToken` pro Sitzung, wenn Anforderungen als der Benutzer ausgeführt werden sollen.
* Registrieren Sie nur die Tools, die die Sitzung benötigt, und bevorzugen Sie quellqualifizierte Zulassungslisten wie `custom:*` oder `mcp:search_docs`.
* Legen Sie `sessionIdleTimeoutSeconds` fest und löschen Sie abgeschlossene Workflow-Sitzungen explizit.

## Häufige Fallstricke

* Vergessen von `mode: "empty"`. Der Standardmodus `copilot-cli` macht das CLI-Stilverhalten verfügbar und kann das Hostdateisystem über Umgebungstools verfügbar machen.
* Keine Festlegung von `sessionIdleTimeoutSeconds`. Server mit langen Laufzeiten können inaktive Sitzungen ansammeln, wenn diese nicht bereinigt werden.
* Freigeben eines `gitHubToken` für mehrere Benutzer anstelle der Übergabe eines Tokens pro Sitzung.
* Blindes Vertrauen in vom Client übermittelte Sitzungs-IDs, ohne im Backend ihre Zugehörigkeit zu prüfen.
* Festlegen von `baseDirectory` auf einem Client, der eine Verbindung mit einer vorhandenen Laufzeit herstellt, und Erwarten, dass der Laufzeitspeicher verschoben wird. Konfigurieren Sie stattdessen den Laufzeitprozess.
* Das Zulassen weit gefasster Toolmuster wie `builtin:*`, ohne zu prüfen, ob jedes Tool für Ihre Benutzer geeignet ist.

## Siehe auch

* [Skalierung und Mehrinstanzenfähigkeit](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/setup/scaling): Bereitstellungstopologien, Speichermuster und Isolationsvergleiche
* [Einrichtung von Back-End-Diensten](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/setup/backend-services): Ausführen der Runtime im Headless-Servermodus
* [Bring Your Own Key (BYOK)](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/auth/byok): Verwendung der Anmeldedaten Ihres eigenen Modellanbieters
* [Cloud-Sitzungen](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/cloud-sessions): Weiterleiten ausgewählter Arbeit an Cloud-Sitzungen
* [Wiederaufnahme und Persistenz der Sitzung](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/session-persistence): Verwalten des fortsetzungsfähigen Sitzungszustands
* [Funktionen](/de/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features): Tools, Ereignisse, Hooks und erweiterte SDK-Features