Melhor para: Produtos saaS, integrações de parceiros, plataformas internas e serviços de back-end que lidam com usuários simultâneos.
Use este guia quando
Use este guia ao criar:
- Um produto SaaS multiusuário que incorpora agentes com tecnologia Copilot
- Um back-end para uma integração com parceiros, como um padrão no estilo do Copilot Studio ou do Fabric
- Qualquer servidor que gerencia usuários simultâneos, espaços de trabalho, tenants ou solicitações
- Um runtime compartilhado no qual vários clientes do SDK se conectam a um processo de runtime do Copilot
Este guia é um guia complementar a Escalabilidade e multitenância. Use esse guia para topologia, balanceamento de carga e padrões de armazenamento. Use este guia para opções no nível do SDK e opções de isolamento de runtime.
Principais opções do SDK
| Opção | Use-o para | Observações |
|---|---|---|
mode: "empty" | Desativação das ferramentas nativas do sistema operacional e das configurações padrão da CLI | Necessário para cenários compartilhados ou multiusuários. |
sessionIdleTimeoutSeconds | Limpar sessões ociosas | Defina um timeout no lado do servidor para processos de longa duração. |
baseDirectory | Isolando COPILOT_HOME por instância de runtime | Ignorado ao se conectar a um runtime existente. |
sessionFs | Encaminhamento do armazenamento do sistema de arquivos da sessão para fora do disco local | Emparelhar com provedores de sistema de arquivos por sessão. |
RuntimeConnection.forUri(url) | Compartilhando um runtime já em execução | Os nomes de idioma variam; veja os exemplos abaixo. |
Por sessão gitHubToken | Restringindo a autenticação ao usuário solicitante | Prefira isso em vez de um único token de usuário compartilhado. |
mode: "empty"
mode: "empty" desabilita o comportamento opcional da CLI Copilot por padrão. No modo de servidor multiusuário, essa é a linha de base segura porque seu aplicativo deve decidir explicitamente quais ferramentas, servidores MCP, habilidades e caminhos de workspace uma sessão pode acessar.
Não use o padrão mode: "copilot-cli" para servidores compartilhados. Esse modo destina-se a agentes de programação do tipo CLI e pode expor capacidades do sistema de arquivos do host no ambiente.
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,
});
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,
)
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,
})
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,
});
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();
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
Defina sessionIdleTimeoutSeconds em servidores para que as sessões inativas sejam limpas automaticamente. Isso impede sessões zumbis em processos de execução longa e reduz a pressão de memória e sistema de arquivos.
| Linguagem | Opção pública |
|---|---|
| TypeScript | sessionIdleTimeoutSeconds |
| Python | session_idle_timeout_seconds |
| Go | SessionIdleTimeoutSeconds |
| .NET | SessionIdleTimeoutSeconds |
| Java | setSessionIdleTimeoutSeconds(...) |
| Rust | with_session_idle_timeout_seconds(...) |
Use um valor que corresponda ao tempo de duração da conversa do seu produto. Para back-ends de chat, 15 a 30 minutos geralmente é um bom ponto de partida. Para agentes de fluxo de trabalho, use um tempo limite maior e uma exclusão explícita quando o fluxo de trabalho for concluído.
baseDirectory
baseDirectory define COPILOT_HOME para uma instância de runtime. Use-o para isolar o estado do runtime, as credenciais e os dados de sessão por processo, pod, trabalho ou limite de locatário.
const client = new CopilotClient({
mode: "empty",
baseDirectory: `/var/lib/my-app/copilot/runtime-${process.env.HOSTNAME}`,
sessionIdleTimeoutSeconds: 900,
});
O runtime armazena o estado da sessão no configurado COPILOT_HOME, incluindo session-state/{sessionId}. Se o aplicativo executar várias instâncias de runtime, dê a cada instância um diretório distinto, a menos que você use intencionalmente o armazenamento compartilhado.
Quando o SDK se conecta a um runtime já em execução com RuntimeConnection.forUri(url), baseDirectory é ignorado pelo cliente do SDK. Configure COPILOT_HOME no processo de execução em vez disso.
sessionFs
sessionFs registra um provedor personalizado de sistema de arquivos de sessão para que a E/S de arquivos com escopo de sessão possa ser roteada por meio do armazenamento do aplicativo em vez do disco local do ambiente de execução. Use-o quando o disco local for efêmero, quando o estado da sessão precisar ficar no armazenamento de objetos ou quando uma plataforma precisar impor caminhos de armazenamento específicos por locatário.
const client = new CopilotClient({
mode: "empty",
sessionFs: {
initialCwd: "/workspace",
sessionStatePath: "/session-state",
conventions: "posix",
},
});
Para linguagens que expõem um callback do provedor, configure sessionFs no nível do cliente e forneça um manipulador do sistema de arquivos para cada sessão ao criar ou retomar uma sessão. Consulte Retomada e persistência da sessão para obter conceitos de persistência e compensações de armazenamento.
Superfícies do SDK público verificadas:
| Linguagem | Configuração no nível do cliente | Fornecedor por sessão |
|---|---|---|
| TypeScript | sessionFs | |
createSessionFsAdapter / callbacks do provedor | ||
| Python | session_fs | create_session_fs_handler |
| Go | SessionFS | CreateSessionFSProvider |
| .NET | SessionFs | CreateSessionFsProvider |
| Rust | with_session_fs(...) | with_session_fs_provider(...) |
Java atualmente não expõe uma opção sessionFs pública verificada, portanto, este guia não mostra um exemplo de Java sessionFs.
RuntimeConnection.forUri(url)
Use uma conexão de tempo de execução externa quando vários clientes do SDK precisarem compartilhar um tempo de execução já em execução. Isso é comum em serviços de back-end em que o processo de runtime é gerenciado separadamente dos manipuladores de solicitação.
| Linguagem | Conexão com ambiente de execução externo |
|---|---|
| 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 } |
Os runtimes externos gerenciam sua própria autenticação e armazenamento em nível de processo. Passe tokens por sessão em createSession ou resumeSession quando precisar de autenticação específica do usuário.
Por sessão gitHubToken
Defina gitHubToken em cada sessão para restringir o escopo da autenticação do GitHub ao usuário solicitante. Isso é diferente de um token no nível do cliente, que autentica o processo de runtime.
const session = await client.createSession({
sessionId: `user-${user.id}-support`,
model: "gpt-4.1",
availableTools: ["custom:*"],
gitHubToken: user.githubToken,
});
Use tokens por sessão para exclusão de conteúdo, roteamento de modelos, verificações de cotas e acesso ao Copilot específico do usuário. Evite compartilhar um token de serviço entre usuários, a menos que seu produto use intencionalmente a semântica de conta de serviço.
ID de integração
Os parceiros que criam agentes de marca podem definir uma ID de integração para solicitações de Controle de Missão. O runtime lê GITHUB_COPILOT_INTEGRATION_ID e o define como o cabeçalho HTTP Copilot-Integration-Id em cada solicitação do Mission Control.
GITHUB_COPILOT_INTEGRATION_ID=my-product-agent copilot --headless --port 4321
A ID de integração padrão é copilot-developer-cli. Use um valor estável, como my-product-agent para atribuição e roteamento. A ID de integração está configurada apenas por variável de ambiente; não é uma opção de SDK de primeira classe.
Se o SDK gerar o runtime, passe a variável de ambiente pela opção de ambiente do cliente. Se você se conectar com RuntimeConnection.forUri(url), defina a variável de ambiente no próprio processo em tempo de execução.
Garantias de isolamento em nível de sessão
O isolamento no nível da sessão significa que o runtime mantém as informações de estado e modelo específicas do usuário no escopo de uma sessão, não no estado compartilhado global.
| Superfície | Comportamento de isolamento |
|---|---|
| Cache de lista de modelos | Por sessão. A pesquisa de modelo usa o cache de lista de modelos da sessão. |
| Estado da sessão | Por ID de sessão em COPILOT_HOME/session-state/{sessionId}. |
| Identidade do GitHub | Por sessão, quando gitHubToken é definido na sessão. |
| Tools | Explícito em mode: "empty"; implícito em mode: "copilot-cli". |
| Sistema de arquivos de host | Compartilhado pelo processo de runtime se as ferramentas de host estiverem disponíveis. |
mode: "empty" é o que torna os padrões de runtime compartilhados viáveis: nenhuma ferramenta de sistema operacional ambiente é exposta, a menos que seu aplicativo registre ou permita. Com mode: "copilot-cli", o acesso ao sistema de arquivos do sistema operacional é compartilhado por meio do processo de host, portanto, não use esse modo para o modo de servidor multiusuário.
O estado da sessão é armazenado em COPILOT_HOME/session-state/{sessionId}, a menos que você o direcione por sessionFs. Use IDs de sessão exclusivas que incluem seu próprio locatário ou limite de usuário e imponha o controle de acesso antes de retomar ou excluir sessões.
Comparação de padrões
| Pattern | Usar quando | Compensações |
|---|---|---|
| Padrão 1: CLI isolada por usuário | Você precisa do limite de isolamento mais forte ou das credenciais de processo separadas por usuário. | Isolamento forte; custo de recurso mais alto. Consulte Escalabilidade e multitenância. |
Padrão 2: CLI compartilhada com mode: "empty" | Você deseja que um runtime atenda a muitos usuários enquanto seu aplicativo controla as ferramentas, a autenticação e as IDs de sessão. | Eficiente; requer um registro cuidadoso de ferramentas, tokens por sessão e verificações de acesso no nível do aplicativo. |
| Padrão 3: híbrido | Você roteia o trabalho de computação pesada para sessões de nuvem e trabalho leve para sessões locais. | Flexível; requer o roteamento de carga de trabalho e o tratamento de políticas. Consulte Sessões de nuvem. |
Padrão 2: CLI compartilhada com mode: "empty"
Nesse padrão, todos os usuários se conectam por meio do back-end a um pool de runtime. O aplicativo executa a autenticação do usuário, escolhe uma ID de sessão, passa o token GitHub do usuário na sessão e fornece uma lista de permissões de ferramenta explícita.

Use estas regras:
- Sempre inicie o cliente ou o runtime em
mode: "empty". - Use IDs de sessão exclusivas e armazene metadados de propriedade no banco de dados do aplicativo.
- Verifique a titularidade antes de
resumeSession,deleteSessionou qualquer ação da interface do usuário que faça referência a um ID de sessão. - Forneça
gitHubTokenem cada sessão quando as solicitações devem ser executadas em nome do usuário. - Registre apenas as ferramentas que a sessão necessita e prefira listas de permissões com origem especificada, como
custom:*oumcp:search_docs. - Defina
sessionIdleTimeoutSecondse exclua as sessões de fluxo de trabalho concluídas explicitamente.
Armadilhas comuns
- Esquecendo
mode: "empty". O modo padrãocopilot-cliexpõe um comportamento no estilo de CLI e pode expor o sistema de arquivos do host por meio de ferramentas disponíveis no ambiente. - Não definir
sessionIdleTimeoutSeconds. Servidores que permanecem em execução por longos períodos podem acumular sessões ociosas se não as encerrarem. - Compartilhando um
gitHubTokenentre usuários em vez de passar um token por sessão. - Confiando em IDs de sessão fornecidas pelo cliente sem verificar a propriedade em seu back-end.
- Definir
baseDirectoryem um cliente que se conecta a um runtime existente esperando mover o armazenamento do runtime. Em vez disso, configure o processo de runtime. - Permitir padrões de ferramentas amplos, como
builtin:*sem examinar se cada ferramenta é apropriada para seus usuários.
Consulte também
- Escalabilidade e multitenância: topologias de implantação, padrões de armazenamento e comparações de isolamento
- Configuração de serviços de back-end: executando o runtime no modo de servidor sem cabeça
- BYOK (Bring Your Own Key - traga sua própria chave): usando suas próprias credenciais de provedor de modelo
- Sessões de nuvem: roteamento de trabalho selecionado para sessões de nuvem
- Retomada e persistência da sessão: gerenciando o estado de sessão retomável
- Features: ferramentas, eventos, ganchos e recursos avançados do SDK