{"meta":{"title":"Мультиарендные и серверные развертывания","intro":"Режим многопользовательского сервера означает запуск Copilot SDK из бэкенд-кода, обслуживающего более одного человека, арендатора, рабочего пространства или интеграционного аккаунта. В этой конфигурации приложение управляет маршрутизацией и авторизацией запросов, а SDK и среда выполнения обеспечивают состояние за сессию, аутентификацию за сессию и явную регистрацию инструментов, чтобы сессия одного пользователя не наследовала инструменты или идентичность другого пользователя.","product":"GitHub Copilot","breadcrumbs":[{"href":"/ru/copilot","title":"GitHub Copilot"},{"href":"/ru/copilot/how-tos","title":"Инструкции"},{"href":"/ru/copilot/how-tos/copilot-sdk","title":"Второй пилот SDK"},{"href":"/ru/copilot/how-tos/copilot-sdk/setup","title":"Настройте Copilot SDK"},{"href":"/ru/copilot/how-tos/copilot-sdk/setup/multi-tenancy","title":"Многоарендная система"}],"documentType":"article"},"body":"# Мультиарендные и серверные развертывания\n\nРежим многопользовательского сервера означает запуск Copilot SDK из бэкенд-кода, обслуживающего более одного человека, арендатора, рабочего пространства или интеграционного аккаунта. В этой конфигурации приложение управляет маршрутизацией и авторизацией запросов, а SDK и среда выполнения обеспечивают состояние за сессию, аутентификацию за сессию и явную регистрацию инструментов, чтобы сессия одного пользователя не наследовала инструменты или идентичность другого пользователя.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n**Лучше всего для:** SaaS-продукты, интеграции с партнёрами, внутренние платформы и бэкенд-сервисы, работающие с одновременно работающими пользователями.\n\n## Используйте это руководство, когда\n\nИспользуйте это руководство при строительстве:\n\n* Многопользовательский SaaS-продукт, в котором встроены агенты на базе Copilot\n* Бэкенд для партнёрской интеграции, например, Copilot Studio или выкройка в стиле Fabric\n* Любой сервер, который обрабатывает одновременных пользователей, рабочие пространства, арендаторы или запросы\n* Общее время выполнения, где несколько SDK-клиентов подключаются к одному процессу Copilot\n\nЭто руководство является сестринским вариантом [AUTOTITLE.](/ru/copilot/how-tos/copilot-sdk/setup/scaling) Используйте это руководство для топологии, балансировки нагрузки и шаблонов хранения. Используйте это руководство для параметров на уровне SDK и выбора изоляции во время выполнения.\n\n## Ключевые опции SDK\n\n| Опция                           | Используйте его для                                                    | Notes                                                              |\n| ------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------ |\n| `mode: \"empty\"`                 | Отключение инструментов окружающей среды ОС и стандартных настроек CLI | Требуется для многопользовательских или совместных сценариев.      |\n| `sessionIdleTimeoutSeconds`     | Очистка занятий холостого хода                                         | Установите тайм-аут на стороне сервера для долгосрочных процессов. |\n| `baseDirectory`                 | Изоляция `COPILOT_HOME` каждого экземпляра во время выполнения         | Игнорируется при подключении к существующему runtime.              |\n| `sessionFs`                     | Маршрутизация файловой системы сессии с локального диска               | Сопоставьте с провайдерами файловой системы для каждой сессии.     |\n| `RuntimeConnection.forUri(url)` | Делюсь одним уже работающим временем выполнения                        | Названия языков различаются; См. примеры ниже.                     |\n| За сессию `gitHubToken`         | Определение аутентификации для запрашивающего пользователя             | Предпочитаю этот токен, а не один общий пользовательский токен.    |\n\n### `mode: \"empty\"`\n\n`mode: \"empty\"` по умолчанию отключает опциональное Copilot поведение CLI. В режиме многопользовательского сервера это безопасная база, потому что ваше приложение должно чётко определить, какие инструменты, MCP-серверы, навыки и пути рабочего пространства смогут использовать сессия.\n\nНе используйте стандартные `mode: \"copilot-cli\"` настройки для общих серверов. Этот режим предназначен для агентов кодирования, похожих на CLI, и может раскрывать возможности фоновой файловой системы хоста.\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\nНастройте `sessionIdleTimeoutSeconds` серверы так, чтобы неактивные сессии очищались автоматически. Это предотвращает зомби-сессии в долгоработающих процессах и снижает нагрузку на память и файловую систему.\n\n| Language   | Публичная опция                          |\n| ---------- | ---------------------------------------- |\n| TypeScript | `sessionIdleTimeoutSeconds`              |\n| Python     | `session_idle_timeout_seconds`           |\n| Go         | `SessionIdleTimeoutSeconds`              |\n| .NET       | `SessionIdleTimeoutSeconds`              |\n| Java       | `setSessionIdleTimeoutSeconds(...)`      |\n| Rust       | `with_session_idle_timeout_seconds(...)` |\n\nИспользуйте значение, соответствующее продолжительности общения вашего продукта. Для чат-бэкендов обычно 15–30 минут — хороший старт. Для агентов рабочих процессов используйте более длительный тайм-аут и явное удаление после завершения процесса.\n\n### `baseDirectory`\n\n`baseDirectory` устанавливает `COPILOT_HOME` для экземпляра во время выполнения. Используйте его для изоляции состояния runtime, учетных данных и сессионных данных по процессу, поду, работнику или арендатору.\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\nСостояние сессии во время выполнения хранит под настроенным `COPILOT_HOME`, включая `session-state/{sessionId}`. Если ваше приложение запускает несколько экземпляров во время выполнения, дайте каждому инстансу отдельную директорию, если только вы намеренно не используете общее хранилище.\n\nКогда SDK подключается к уже запущенному runtime с `RuntimeConnection.forUri(url)`, `baseDirectory` он игнорируется клиентом SDK. Настройте `COPILOT_HOME` на процессе выполнения вместо этого.\n\n### `sessionFs`\n\n`sessionFs` регистрирует пользовательский сервер файловой системы сессии, чтобы ввод/вывод файлов с ограниченным графиком можно было маршрутизировать через хранилище приложений вместо локального диска среды выполнения. Используйте его, когда локальный диск эфемерен, когда состояние сессии должно оставаться в объектном хранилище, или когда платформе нужно навязывать пути хранения с учётом арендаторов.\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\nДля языков, предоставляющих обратный вызов провайдера, настройте `sessionFs` на уровне клиента и предоставляйте обработчик файловой системы для каждой сессии при создании или возобновлении сессии. См. [Возобновление сессии и сохранение](/ru/copilot/how-tos/copilot-sdk/features/session-persistence) для концепций устойчивости и компромиссов при хранении.\n\nПроверенные публичные поверхности SDK:\n\n| Language                                               | Конфигурация на уровне клиента | Провайдер на сессию             |\n| ------------------------------------------------------ | ------------------------------ | ------------------------------- |\n| TypeScript                                             | `sessionFs`                    |                                 |\n| `createSessionFsAdapter` / обратные звонки провайдеров |                                |                                 |\n| Python                                                 | `session_fs`                   | `create_session_fs_handler`     |\n| Go                                                     | `SessionFS`                    | `CreateSessionFSProvider`       |\n| .NET                                                   | `SessionFs`                    | `CreateSessionFsProvider`       |\n| Rust                                                   | `with_session_fs(...)`         | `with_session_fs_provider(...)` |\n\nJava в настоящее время не показывает проверенный публичный вариант `sessionFs`, поэтому в этом руководстве не показано выборку Java `sessionFs`.\n\n### `RuntimeConnection.forUri(url)`\n\nИспользуйте внешнее подключение для выполнения времени, когда несколько SDK-клиентов должны делить одну уже запущенную среду выполнения. Это часто встречается в бэкенд-сервисах, где процесс выполнения управляется отдельно от обработчиков запросов.\n\n| Language   | Внешнее подключение во время выполнения                |\n| ---------- | ------------------------------------------------------ |\n| TypeScript | `RuntimeConnection.forUri(url)`                        |\n| Python     | `RuntimeConnection.for_uri(url)`                       |\n| Go         | `copilot.URIConnection{URL: url}`                      |\n| .NET       | `RuntimeConnection.ForUri(url)`                        |\n| Java       | `setCliUrl(url)`                                       |\n| Rust       | `Transport::External { host, port, connection_token }` |\n\nВнешние серверы выполнения управляют собственной аутентификацией и хранением на уровне процесса. Передавайте токены за сессию на `createSession` или `resumeSession` когда нужна аутентификационная лицензия пользователя.\n\n### За сессию `gitHubToken`\n\nУстановите `gitHubToken` на каждой сессии так, чтобы GitHub аутентификации для запрашивающего пользователя. Это отличается от токена на уровне клиента, который аутентифицирует процесс выполнения.\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\nИспользуйте токены за сессию для исключения контента, маршрутизации моделей, проверки квот и пользовательского доступа к Copilot. Избегайте совместного использования одного сервисного токена между пользователями, если только ваш продукт намеренно не использует семантику сервис-аккаунт.\n\n## Идентификатор интеграции\n\nПартнёры, создающие брендированные агенты, могут устанавливать идентификатор интеграции для запросов в Центр управления полётом. Время выполнения читает `GITHUB_COPILOT_INTEGRATION_ID` и маркирует его как HTTP-заголовок `Copilot-Integration-Id` на каждом запросе Управления полётами.\n\n```bash\nGITHUB_COPILOT_INTEGRATION_ID=my-product-agent copilot --headless --port 4321\n```\n\nИдентификатор интеграции по умолчанию — `copilot-developer-cli`. Используйте стабильное значение, например `my-product-agent` для атрибуции и маршрутизации. Идентификатор интеграции в настоящее время настраивается только по переменной среды; это не первоклассный SDK.\n\nЕсли SDK вызывает время выполнения, передайте переменную среды через опцию клиентской среды. Если вы подключитесь к `RuntimeConnection.forUri(url)`, установите переменную окружения непосредственно на процессе выполнения.\n\n## Гарантии изоляции на уровне сессии\n\nИзоляция на уровне сессии означает, что среда выполнения сохраняет пользовательскую информацию о модели и состояниях в рамках сессии, а не в глобальном общем состоянии.\n\n| Surface                | Изоляционное поведение                                             |\n| ---------------------- | ------------------------------------------------------------------ |\n| Кэш списка моделей     | За сессию. Поиск модели использует кэш списка моделей сессии.      |\n| Состояние сеанса       | Идентификатор сессии под `COPILOT_HOME/session-state/{sessionId}`. |\n| GitHub идентичность    | Каждую сессию, когда `gitHubToken` установлена сессия.             |\n| Tools                  | Явно в `mode: \"empty\"`; амбиент в `mode: \"copilot-cli\"`.           |\n| Файловая система хоста | Используется процессом выполнения, если доступны хост-инструменты. |\n\n`mode: \"empty\"` именно это делает общие шаблоны выполнения жизнеспособными: ни один инструмент ОС не отображается, если ваше приложение не регистрирует или не разрешает их. При `mode: \"copilot-cli\"`, доступ к файловой системе ОС осуществляется через хост-процесс, поэтому не используйте этот режим для многопользовательского сервера.\n\nСостояние сессии хранится в `COPILOT_HOME/session-state/{sessionId}` , если только вы не направите его через `sessionFs`. Используйте уникальные идентификаторы сессий, которые включают границы вашего арендатора или пользователя, и обеспечивайте контроль доступа перед возобновлением или удалением сессий.\n\n## Сравнение узоров\n\n| Pattern                                     | Используйте, если                                                                                                                                              | Trade-offs                                                                                                                                              |\n| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Шаблон 1: изолированный CLI на пользователя | Вам нужна самая строгая граница изоляции или отдельные учетные данные процесса для каждого пользователя.                                                       | Сильная изоляция; Более высокая стоимость ресурсов. См [. раздел AUTOTITLE](/ru/copilot/how-tos/copilot-sdk/setup/scaling).                             |\n| Шаблон 2: общий CLI с `mode: \"empty\"`       | Вам нужно, чтобы одна среда выполнения обслуживала многих пользователей, а ваше приложение управляло инструментами, аутентификацией и идентификаторами сессий. | Эффективно; требуется тщательная регистрация инструментов, токены за сессию и проверка доступа на уровне приложения.                                    |\n| Шаблон 3: гибрид                            | Вы перенаправляете работу с вычислительной нагрузкой в облачные сессии, а лёгкую — в локальные сессии.                                                         | Гибкий; Требуется маршрутизация рабочей нагрузки и обработка политик. См [. раздел AUTOTITLE](/ru/copilot/how-tos/copilot-sdk/features/cloud-sessions). |\n\n### Шаблон 2: общий CLI с `mode: \"empty\"`\n\nВ этом шаблоне все пользователи подключаются через ваш бэкенд к одному пулу runtime. Приложение выполняет аутентификацию пользователя, выбирает идентификатор сессии, передаёт токен GitHub пользователя на сессию и предоставляет явный список разрешений инструментов.\n\n![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/setup-multi-tenancy-diagram-0.png)\n\nИспользуйте следующие правила:\n\n* Всегда запускайте клиент или время выполнения в `mode: \"empty\"`.\n* Используйте уникальные идентификаторы сессий и храните метаданные владения в базе данных приложений.\n* Проверьте владение перед `resumeSession`, `deleteSession`или любое действие интерфейса, ссылающееся на идентификатор сессии.\n* Пропускайте `gitHubToken` каждую сессию, когда запросы должны выполняться от пользователя.\n* Регистрируйте только те инструменты, которые нужны сессии, и предпочитайте квалифицированные по источнику списки разрешений, такие как `custom:*` или `mcp:search_docs`.\n* Устанавливайте `sessionIdleTimeoutSeconds` и удаляйте завершённые сессии рабочего процесса явно.\n\n## Распространенные ловушки\n\n* Забывая `mode: \"empty\"`. Режим по умолчанию `copilot-cli` демонстрирует поведение в стиле CLI и может раскрывать файловую систему хоста с помощью окружающих инструментов.\n* Не устанавливаю `sessionIdleTimeoutSeconds`. Долгосрочные серверы могут накапливать простою, если не очищать их.\n* Обмен одним `gitHubToken` между пользователями вместо передачи токена за сессию.\n* Доверие к идентификаторам сессий, предоставленным клиентом, без проверки собственности на вашем бэкенде.\n* Настройка `baseDirectory` клиента, который подключается к существующему runtime, и ожидание перемещения хранилища во время выполнения. Настройте процесс выполнения вместо этого.\n* Разрешить общие шаблоны инструментов, например `builtin:*` , без проверки, подходит ли каждый из них вашим пользователям.\n\n## См. также\n\n* [Масштабирование и многоарендность](/ru/copilot/how-tos/copilot-sdk/setup/scaling): топологии развертывания, шаблоны хранения и сравнение изоляции\n* [Настройка серверных сервисов](/ru/copilot/how-tos/copilot-sdk/setup/backend-services): запуск времени выполнения в режиме безголового сервера\n* [БЁК (принеси свой ключ)](/ru/copilot/how-tos/copilot-sdk/auth/byok): использование учетных данных вашего собственного поставщика модели\n* [Облачные сессии](/ru/copilot/how-tos/copilot-sdk/features/cloud-sessions): маршрутизация выбранной работы в облачные сессии\n* [Возобновление сессии и сохранение](/ru/copilot/how-tos/copilot-sdk/features/session-persistence): управление восстановленным состоянием сессии\n* [Возможности](/ru/copilot/how-tos/copilot-sdk/features): инструменты, события, крючки и расширенные функции SDK"}