Skip to main content

Sessões de nuvem

Execute sessões do Copilot em recursos computacionais hospedados pelo GitHub por meio do Mission Control, em vez de sessões locais da CLI.

Pré-requisitos

Antes de criar uma sessão na nuvem, verifique se:

  • O usuário tem acesso Copilot com direito de agente de nuvem.
  • A sessão pode se autenticar no GitHub, com um token de usuário ou uma identidade conectada do Copilot CLI.
  • Você pode associar a sessão a um repositório GitHub. Isso é opcional no tipo SDK, mas recomendado para que o Controle de Missão e o agente de nuvem tenham contexto de repositório.
  • As políticas da organização permitem o controle remoto e a exibição de sessões de superfícies de nuvem.

Criando uma sessão de nuvem

Defina a opção create-session cloud para criar uma sessão de nuvem. Você pode incluir metadados do repositório para associar a sessão de nuvem a um repositório GitHub.

TypeScript

import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
await client.start();

const session = await client.createSession({
  onPermissionRequest: async () => ({ kind: "approve-once" }),
  cloud: {
    repository: {
      owner: "github",
      name: "copilot-sdk",
      branch: "main",
    },
  },
});

Python

from copilot import (
    CloudSessionOptions,
    CloudSessionRepository,
    CopilotClient,
    PermissionHandler,
)

client = CopilotClient()
await client.start()

session = await client.create_session(
    on_permission_request=PermissionHandler.approve_all,
    cloud=CloudSessionOptions(
        repository=CloudSessionRepository(
            owner="github",
            name="copilot-sdk",
            branch="main",
        )
    ),
)

Go

package main

import (
    "context"

    copilot "github.com/github/copilot-sdk/go"
    "github.com/github/copilot-sdk/go/rpc"
)

func main() {
    _ = run(context.Background())
}

func run(ctx context.Context) error {
    client := copilot.NewClient(nil)
    if err := client.Start(ctx); err != nil {
        return err
    }

    session, err := client.CreateSession(ctx, &copilot.SessionConfig{
        Cloud: &copilot.CloudSessionOptions{
            Repository: &copilot.CloudSessionRepository{
                Owner:  "github",
                Name:   "copilot-sdk",
                Branch: "main",
            },
        },
        OnPermissionRequest: func(_ copilot.PermissionRequest, _ copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
            return &rpc.PermissionDecisionApproveOnce{}, nil
        },
    })
    _ = session
    return err
}
client := copilot.NewClient(nil)
if err := client.Start(ctx); err != nil {
    return err
}

session, err := client.CreateSession(ctx, &copilot.SessionConfig{
    Cloud: &copilot.CloudSessionOptions{
        Repository: &copilot.CloudSessionRepository{
            Owner:  "github",
            Name:   "copilot-sdk",
            Branch: "main",
        },
    },
    OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
        return &rpc.PermissionDecisionApproveOnce{}, nil
    },
})
_ = session

.NET

await using var client = new CopilotClient();

var session = await client.CreateSessionAsync(new SessionConfig
{
    Cloud = new CloudSessionOptions
    {
        Repository = new CloudSessionRepository
        {
            Owner = "github",
            Name = "copilot-sdk",
            Branch = "main",
        },
    },
    OnPermissionRequest = (req, inv) =>
        Task.FromResult(PermissionDecision.ApproveOnce()),
});

Java

import com.github.copilot.CopilotClient;
import com.github.copilot.rpc.*;

try (var client = new CopilotClient()) {
    client.start().get();

    var session = client.createSession(
        new SessionConfig()
            .setCloud(new CloudSessionOptions()
                .setRepository(new CloudSessionRepository()
                    .setOwner("github")
                    .setName("copilot-sdk")
                    .setBranch("main")))
            .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
    ).get();
}

Rust

use std::sync::Arc;
use github_copilot_sdk::{CloudSessionOptions, CloudSessionRepository, SessionConfig};
use github_copilot_sdk::handler::ApproveAllHandler;

let session = client.create_session(
    SessionConfig::default()
        .with_cloud(CloudSessionOptions::with_repository(
            CloudSessionRepository::new("github", "copilot-sdk").with_branch("main"),
        ))
        .with_permission_handler(Arc::new(ApproveAllHandler)),
).await?;

Enviando o primeiro prompt

As sessões na nuvem são iniciadas em duas fases: createSession é resolvido assim que o Mission Control reserva uma tarefa, mas o worker remoto copilot-agent leva mais um ou dois segundos para se conectar e emitir session.start. Se você chamar session.send antes disso, o RemoteSession.send do runtime lança "Remote session is still starting" — mas o wrapper de esquema é do tipo fire-and-forget e engole o erro silenciosamente, mas ainda retorna um novo messageId para o seu código. O prompt é descartado no servidor e nunca chega ao worker.

Para enviar de forma confiável, inscreva-se nos eventos antes de enviar e aguarde o primeiro evento session.start cujo producer é "copilot-agent":

import { CopilotClient, type CopilotSession } from "@github/copilot-sdk";

const client = new CopilotClient();
await client.start();

const session: CopilotSession = await client.createSession({
  streaming: true, // required for assistant.message_delta to fire
  cloud: { repository: { owner: "github", name: "copilot-sdk" } },
  onPermissionRequest: async () => ({ kind: "approve-once" }),
});

// Subscribe BEFORE sending so you don't miss the start event.
const ready = new Promise<void>((resolve) => {
  const off = session.on("session.start", (event) => {
    if (event.data?.producer === "copilot-agent") {
      off();
      resolve();
    }
  });
});

await ready;
await session.send({ prompt: "Summarize the README" });

Algumas notas:

  • Defina streaming: true em createSession para que o runtime emita eventos assistant.message_delta. Sem ele, o único sinal do assistente que você recebe é o assistant.message final — o que serve para uso em lote, mas o chat parecerá congelado se você estiver renderizando uma interface em tempo real. Consulte Eventos de sessão de streaming.
  • Só o primeirosession.send é sensível a esta corrida. Os envios subsequentes na mesma sessão funcionam normalmente porque o runtime mantém hasSessionStarted definido durante toda a sessão.
  • Aplique um tempo limite (por exemplo, 60 s) à promessa ready para que, se o provisionamento do Mission Control travar, seu aplicativo não fique travado para sempre.
  • O mesmo padrão funciona em todas as linguagens de SDK — inscreva-se em session.start, verifique producer === "copilot-agent" e, em seguida, chame send.

Acessando a URL de Controle de Missão

As sessões em nuvem são inerentemente remotas: assim que o worker se conecta, o Mission Control publica a sessão em https://github.com/copilot/tasks/{sessionId}, e o runtime emite um evento session.info com a URL. Você não precisa invocar remote.enable() — essa API é apenas para promover uma sessão local para o Mission Control.

Capture a URL subscrevendo session.info e filtrando por infoType: "remote":

session.on("session.info", (event) => {
  if (event.data?.infoType === "remote" && event.data.url) {
    console.log("Open from web or mobile:", event.data.url);
    // e.g. surface in your UI as a shareable link or QR code.
  }
});

O evento é acionado pouco depois de session.start. Se o renderizador for montado depois que o evento já tiver sido disparado, persista a URL junto com o registro da sessão no estado do aplicativo e reidrate-a ao remontar — o ambiente de execução não emitirá session.info novamente por conta própria.

Para o mesmo cabeamento em sessões locais promovidas via remote: true, consulte Sessões remotas.

Associação de repositório

O objeto cloud.repository associa a sessão de nuvem a um repositório GitHub:

CampoObrigatórioDescrição
ownerYesProprietário ou organização do repositório.
nameYesNome do repositório.
branchNoRamificação a ser usada no contexto do repositório. Omita isso para permitir que o tempo de execução escolha a ramificação padrão ou o contexto atual do repositório.

A associação de repositório é opcional no tipo SDK, mas inclua-a sempre que o aplicativo souber o repositório de destino. Ele ajuda o Controle de Missão a exibir a sessão no contexto certo e fornece ao agente de nuvem um ponto de partida mais claro.

Use branch quando o trabalho deve ser iniciado a partir de uma ramificação específica. Se o seu aplicativo estiver criando sessões a partir de pull requests, fluxos de triagem de issues ou fluxos de trabalho de implantação, passe a branch que corresponde à tarefa visível para o usuário.

Retomando uma sessão de nuvem

A cloud opção só se aplica ao criar uma nova sessão. Para retomar uma sessão de nuvem existente, use a API de retomada padrão para o idioma do SDK:

import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
await client.start();

const session = await client.resumeSession("session-id", {
  onPermissionRequest: async () => ({ kind: "approve-once" }),
});
void session;
const session = await client.resumeSession("session-id", {
  onPermissionRequest: async () => ({ kind: "approve-once" }),
});

Não passe cloud novamente ao retomar. Os metadados salvos da sessão determinam que a sessão é respaldada pela nuvem, e a retomada segue o fluxo normal de retomada da sessão.

Políticas e direitos da organização

A criação de sessão na nuvem pode falhar quando o usuário ou a organização não tem direito à execução do agente de nuvem ou quando as políticas no nível da organização bloqueiam o fluxo. Em particular, as políticas para o sandbox da nuvem podem impedir que os clientes criem a tarefa na nuvem.

Quando isso acontece, o runtime relata um "policy_blocked" motivo de falha para a criação de tarefas na nuvem. Trate isso como um resultado de autorização ou política, não como uma falha transitória de infraestrutura.

No TypeScript, verifique o motivo antes de tentar novamente:

import {
  CopilotClient,
  type CloudSessionRepository,
} from "@github/copilot-sdk";

const client = new CopilotClient();
await client.start();

const repository: CloudSessionRepository = {
  owner: "github",
  name: "copilot-sdk",
};

try {
  await client.createSession({
    cloud: { repository },
    onPermissionRequest: async () => ({ kind: "approve-once" }),
  });
} catch (error) {
  if ((error as { reason?: string }).reason === "policy_blocked") {
    // Show an admin-facing message or link to org policy settings.
  }
  throw error;
}
try {
  await client.createSession({ cloud: { repository } });
} catch (error) {
  if ((error as { reason?: string }).reason === "policy_blocked") {
    // Show an admin-facing message or link to org policy settings.
  }
  throw error;
}

Em idiomas em que os erros do SDK são representados de forma diferente, inspecione o motivo do erro ou o código exibido e manipule "policy_blocked" explicitamente. Não se espera que a repetição sem uma alteração de política seja bem-sucedida.

ID de integração e roteamento

As sessões de nuvem são carimbadas com um cabeçalho Copilot-Integration-Id derivado da variável de ambiente GITHUB_COPILOT_INTEGRATION_ID. Essa ID de integração é usada pelo Controle de Missão para roteamento, atribuição e comportamento específico de integração.

Para obter orientações sobre servidor multiusuário e detalhes completos do ID de integração, consulte Multilocação e implantações de servidores.

O Mission Control encaminha sessões na nuvem criadas pelo SDK para o slug do agente copilot-developer-sandbox. O nome é um identificador interno de roteamento para o agente na nuvem e não significa que a sessão esteja usando o sandbox local do Windows.

Avançado: COPILOT_MC_BASE_URL

Por padrão, o runtime obtém a URL base do Mission Control a partir da URL configurada da API do Copilot. Defina COPILOT_MC_BASE_URL somente quando precisar substituir esse endpoint do Mission Control.

Isso pode ser necessário para implantações do GitHub Enterprise Server. Confirme o valor correto e o status de suporte com seu representante GitHub antes de confiar nele na produção.

COPILOT_MC_BASE_URL="https://example.com/agents"

Sessões de nuvem versus sessões remotas

CapacidadeSessões remotasSessões de nuvem
Local de execuçãoComputador local ou servidorcomputação hospedada no GitHub
Função de Controle de MissãoCompartilha uma sessão local para GitHub web/móvelCria e encaminha a sessão hospedada
Opção SDK
remote: true no cliente ou na sessão
cloud: { ... } ao criar sessão
Retomar o caminhoCurrículo padrãoCurrículo padrão
Relacionado ao Windows SandboxNão relacionadoNão relacionado

Use sessões remotas quando a sessão deve ser executada onde o runtime do SDK já está em execução, mas também pode ser acessível a partir do Controle de Missão. Use sessões de nuvem quando a sessão deve ser executada na computação hospedada GitHub.

Troubleshooting

SintomaCausa provávelO que verificar
A criação de sessão na nuvem retorna "policy_blocked"Política de organização bloqueia controle remoto ou exibição de fluxos de nuvemVerificar políticas de Copilot da organização e direitos do usuário
Sessão criada sem contexto de repositório
cloud.repository foi omitidoPasse owner, name, e opcionalmente branch
Retomar ignora uma nova cloud opção
cloud aplica-se apenas a novas sessõesRetomar a sessão existente normalmente
Confusão em relação às configurações de sandboxO Windows Sandbox e as sessões na nuvem são separadosNão usar SANDBOX=true para execução na nuvem
session.send é resolvido com um messageId, mas nenhum evento assistant.* é disparado e o Controle de Missão não mostra nenhuma solicitaçãoO session.send correu à frente do session.start trabalho remoto; o runtime engoliu o promptAguarde o primeiro evento session.start com producer === "copilot-agent" antes de enviar. Consulte Enviar o primeiro prompt
A interface do usuário em tempo real nunca é atualizada, mesmo que o worker na nuvem esteja processando
streaming não foi definido em createSession, portanto apenas o assistant.message final é emitidoConfigure streaming: true em createSession e reinicie
A sessão na nuvem funciona, mas nenhuma URL compartilhável aparece na interface do usuárioO aplicativo nunca assinou session.info para a URLInscreva-se em session.info e filtre infoType === "remote". Consulte como acessar a URL do Controle de Missão

Consulte também