Skip to main content

Configuração de serviços de back-end

Execute o SDK Copilot em aplicativos do lado do servidor — APIs, back-ends da Web, microsserviços e trabalhos em segundo plano. A CLI é executada como um servidor sem cabeça ao qual o código de back-end se conecta pela rede.

Melhor para: Back-ends de aplicativos web, serviços de API, ferramentas internas, integrações de CI/CD, qualquer carga de trabalho do lado do servidor.

Como funciona

Em vez do SDK gerar um processo filho da CLI, você executa a CLI de forma independente no modo de servidor sem cabeça. O back-end conecta-se a ele por TCP usando a opção Connection (UriConnection).

Diagrama: Fluxograma mostrando o processo descrito.

Principais características:

  • A CLI é executada como um processo de servidor persistente (não gerado por solicitação)
  • O SDK se conecta por TCP— a CLI e o aplicativo podem ser executados em contêineres diferentes
  • Vários clientes do SDK podem compartilhar um servidor da CLI
  • Funciona com qualquer método de autenticação (tokens GitHub, env vars, BYOK)

Arquitetura: gerenciada automaticamente versus CLI externa

Diagrama: Fluxograma mostrando o processo descrito.

Etapa 1: iniciar a CLI no modo sem cabeça

Execute a CLI como um servidor em segundo plano:

# Start with a specific port
copilot --headless --port 4321

# Or let it pick a random port (prints the URL)
copilot --headless
# Output: Listening on http://localhost:52431

Por padrão, o servidor sem cabeça aceita apenas conexões do loopback (127.0.0.1). Para aceitar conexões de outros hosts — por exemplo, de outro computador na sua rede — vincule-se a um endereço não loopback com --host:

copilot --headless --host 0.0.0.0 --port 4321

Para produção, execute-o como um serviço do sistema ou em um contêiner.

Observação

Não há imagem oficial do Docker pré-construída para a CLI do Copilot. Você pode compilar sua própria versão a partir das releases do GitHub:

FROM debian:bookworm-slim
ARG COPILOT_VERSION=1.0.7
RUN apt-get update \
    && apt-get install -y --no-install-recommends ca-certificates wget \
    && ARCH=$(dpkg --print-architecture) \
    && case "${ARCH}" in amd64) COPILOT_ARCH="x64" ;; arm64) COPILOT_ARCH="arm64" ;; *) echo "Unsupported: ${ARCH}" && exit 1 ;; esac \
    && wget -q "https://github.com/github/copilot-cli/releases/download/v${COPILOT_VERSION}/copilot-linux-${COPILOT_ARCH}.tar.gz" \
    && tar -xzf "copilot-linux-${COPILOT_ARCH}.tar.gz" \
    && mv copilot /usr/local/bin/ \
    && rm "copilot-linux-${COPILOT_ARCH}.tar.gz" \
    && apt-get purge -y wget && apt-get autoremove -y && rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["copilot"]
# Build the image
docker build --build-arg COPILOT_VERSION=1.0.7 -t copilot-cli:latest .

# For remote deployments (Kubernetes, ACI, etc.), push to your registry
docker tag copilot-cli:latest your-registry/copilot-cli:latest
docker push your-registry/copilot-cli:latest
# Docker — must bind to 0.0.0.0 so the container's published port is reachable
docker run -d --name copilot-cli \
    -p 4321:4321 \
    -e COPILOT_GITHUB_TOKEN="$TOKEN" \
    copilot-cli:latest \
    --headless --host 0.0.0.0 --port 4321

# systemd
[Service]
ExecStart=/usr/local/bin/copilot --headless --port 4321
Environment=COPILOT_GITHUB_TOKEN=your-token
Restart=always

Etapa 2: conectar o SDK

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

const client = new CopilotClient({
    cliUrl: "localhost:4321",
});

const session = await client.createSession({
    sessionId: `user-${userId}-${Date.now()}`,
    model: "gpt-4.1",
});

const response = await session.sendAndWait({ prompt: req.body.message });
res.json({ content: response?.data.content });
Python
from copilot import CopilotClient, RuntimeConnection
from copilot.session import PermissionHandler

client = CopilotClient(
    connection=RuntimeConnection.for_uri("localhost:4321"),
)
await client.start()

session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-4.1", session_id=f"user-{user_id}-{int(time.time())}")

response = await session.send_and_wait(message)
Go
package main

import (
    "context"
    "fmt"
    "time"
    copilot "github.com/github/copilot-sdk/go"
)

func main() {
    ctx := context.Background()
    userID := "user1"
    message := "Hello"

    client := copilot.NewClient(&copilot.ClientOptions{
        Connection: copilot.UriConnection{URL: "localhost:4321"},
    })
    client.Start(ctx)
    defer client.Stop()

    session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
        SessionID: fmt.Sprintf("user-%s-%d", userID, time.Now().Unix()),
        Model:     "gpt-4.1",
    })

    response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: message})
    _ = response
}
client := copilot.NewClient(&copilot.ClientOptions{
    Connection: copilot.UriConnection{URL: "localhost:4321"},
})
client.Start(ctx)
defer client.Stop()

session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
    SessionID: fmt.Sprintf("user-%s-%d", userID, time.Now().Unix()),
    Model:     "gpt-4.1",
})

response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: message})
.NET
using GitHub.Copilot;

var userId = "user1";
var message = "Hello";

var client = new CopilotClient(new CopilotClientOptions
{
    Connection = RuntimeConnection.ForUri("localhost:4321"),
});

await using var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = $"user-{userId}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}",
    Model = "gpt-4.1",
});

var response = await session.SendAndWaitAsync(
    new MessageOptions { Prompt = message });
var client = new CopilotClient(new CopilotClientOptions
{
    Connection = RuntimeConnection.ForUri("localhost:4321"),
});

await using var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = $"user-{userId}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}",
    Model = "gpt-4.1",
});

var response = await session.SendAndWaitAsync(
    new MessageOptions { Prompt = message });
Java
import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;

var userId = "user1";
var message = "Hello!";

var client = new CopilotClient(new CopilotClientOptions()
    .setCliUrl("localhost:4321")
);

try {
    client.start().get();

    var session = client.createSession(new SessionConfig()
        .setSessionId(String.format("user-%s-%d", userId, System.currentTimeMillis() / 1000))
        .setModel("gpt-4.1")
        .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
    ).get();

    var response = session.sendAndWait(new MessageOptions()
        .setPrompt(message)).get();
} finally {
    client.stop().get();
}

Autenticação para serviços de back-end

Tokens de variável de ambiente

A abordagem mais simples: defina um token no servidor da CLI:

Diagrama: Fluxograma mostrando o processo descrito.

# All requests use this token
export COPILOT_GITHUB_TOKEN="gho_service_account_token"
copilot --headless --port 4321

Tokens por usuário (OAuth)

Passe tokens de usuário individuais ao criar sessões. Consulte Configuração do OAuth do GitHub para obter o fluxo completo.

// Your API receives user tokens from your auth layer
app.post("/chat", authMiddleware, async (req, res) => {
    const client = new CopilotClient({
        cliUrl: "localhost:4321",
        gitHubToken: req.user.githubToken,
        useLoggedInUser: false,
    });

    const session = await client.createSession({
        sessionId: `user-${req.user.id}-chat`,
        model: "gpt-4.1",
    });

    const response = await session.sendAndWait({
        prompt: req.body.message,
    });

    res.json({ content: response?.data.content });
});

BYOK (sem autenticação GitHub)

Use suas próprias chaves de API para o provedor de modelos. Confira BYOK (bring your own key) para obter detalhes.

const client = new CopilotClient({
    cliUrl: "localhost:4321",
});

const session = await client.createSession({
    model: "gpt-4.1",
    provider: {
        type: "openai",
        baseUrl: "https://api.openai.com/v1",
        apiKey: process.env.OPENAI_API_KEY,
    },
});

Padrões comuns de back-end

API Web com o Express

Diagrama: Fluxograma mostrando o processo descrito.

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

const app = express();
app.use(express.json());

// Single shared CLI connection
const client = new CopilotClient({
    cliUrl: process.env.CLI_URL || "localhost:4321",
});

app.post("/api/chat", async (req, res) => {
    const { sessionId, message } = req.body;

    // Create or resume session
    let session;
    try {
        session = await client.resumeSession(sessionId);
    } catch {
        session = await client.createSession({
            sessionId,
            model: "gpt-4.1",
        });
    }

    const response = await session.sendAndWait({ prompt: message });
    res.json({
        sessionId,
        content: response?.data.content,
    });
});

app.listen(3000);

Trabalho em segundo plano

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

const client = new CopilotClient({
    cliUrl: process.env.CLI_URL || "localhost:4321",
});

// Process jobs from a queue
async function processJob(job: Job) {
    const session = await client.createSession({
        sessionId: `job-${job.id}`,
        model: "gpt-4.1",
    });

    const response = await session.sendAndWait({
        prompt: job.prompt,
    });

    await saveResult(job.id, response?.data.content);
    await session.disconnect();  // Clean up after job completes
}

Implantação do Docker compose

version: "3.8"

services:
  copilot-cli:
    image: copilot-cli:latest  # See "Step 1" above for how to build this image
    command: ["--headless", "--host", "0.0.0.0", "--port", "4321"]
    environment:
      - COPILOT_GITHUB_TOKEN=${COPILOT_GITHUB_TOKEN}
    ports:
      - "4321:4321"
    restart: always
    volumes:
      - session-data:/root/.copilot/session-state

  api:
    build: .
    environment:
      - CLI_URL=copilot-cli:4321
    depends_on:
      - copilot-cli
    ports:
      - "3000:3000"

volumes:
  session-data:

Diagrama: Fluxograma mostrando o processo descrito.

Exames de saúde

Monitore a integridade do servidor da CLI:

// Periodic health check
async function checkCLIHealth(): Promise<boolean> {
    try {
        const status = await client.getStatus();
        return status !== undefined;
    } catch {
        return false;
    }
}

Limpeza de sessão

Os serviços de back-end devem limpar ativamente as sessões para evitar vazamentos de recursos:

// Clean up expired sessions periodically
async function cleanupSessions(maxAgeMs: number) {
    const sessions = await client.listSessions();
    const now = Date.now();

    for (const session of sessions) {
        const age = now - new Date(session.createdAt).getTime();
        if (age > maxAgeMs) {
            await client.deleteSession(session.sessionId);
        }
    }
}

// Run every hour
setInterval(() => cleanupSessions(24 * 60 * 60 * 1000), 60 * 60 * 1000);

Limitações

LimitationDetalhes
Servidor único de CLI = único ponto de falhaConsulte Escalabilidade e multitenância para padrões de HA
Nenhuma autenticação interna entre o SDK e a CLIProteja o caminho de rede (mesmo host, VPC etc.)
Estado da sessão no disco localMontar armazenamento persistente para reinicializações de contêiner
Tempo limite ocioso de 30 minutosAs sessões sem atividade são limpas automaticamente

Quando seguir em frente

NecessidadePróximo Guia
Vários servidores da CLI/alta disponibilidade
Escalabilidade e multitenância
autenticação de conta GitHub para usuários
Configuração do OAuth do GitHub
Suas próprias chaves de modelo
BYOK (bring your own key)

Próximas Etapas