Skip to main content

Configuración de servicios back-end

Ejecute el SDK de Copilot en aplicaciones del lado servidor: API, back-end web, microservicios y trabajos en segundo plano. La CLI se ejecuta como un servidor sin encabezado al que se conecta el código back-end a través de la red.

Lo mejor para: Back-end de aplicaciones web, servicios de API, herramientas internas, integraciones de CI/CD, cualquier carga de trabajo del lado servidor.

Cómo funciona

En lugar del SDK que genera un proceso secundario de la CLI, ejecute la CLI de forma independiente en modo de servidor sin encabezado. El back-end se conecta a él a través de TCP mediante la Connection opción (UriConnection).

Diagrama: Diagrama de flujo que muestra el proceso descrito.

Características principales:

  • La CLI se ejecuta como un proceso de servidor persistente (no generado por solicitud)
  • El SDK se conecta a través de TCP: la CLI y la aplicación se pueden ejecutar en distintos contenedores
  • Varios clientes del SDK pueden compartir un servidor de la CLI
  • Funciona con cualquier método de autenticación (tokens de GitHub, vars env, BYOK)

Arquitectura: administrada automáticamente frente a la CLI externa

Diagrama: Diagrama de flujo que muestra el proceso descrito.

Paso 1: iniciar la CLI en modo sin encabezado

Ejecute la CLI como servidor en 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

De forma predeterminada, el servidor headless solo acepta conexiones desde loopback (127.0.0.1). Para aceptar conexiones de otros hosts (por ejemplo, desde otra máquina de la red), enlace a una dirección que no sea de bucle invertido con --host:

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

Para producción, ejecútelo como un servicio del sistema o en un contenedor.

Nota:

No hay ninguna imagen oficial de Docker pregenerada para la CLI de Copilot. Puede compilar el suyo desde las publicaciones de 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

Paso 2: conexión del 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();
}

Autenticación para servicios back-end

Tokens de variables de entorno

El enfoque más sencillo: establezca un token en el servidor de la CLI:

Diagrama: Diagrama de flujo que muestra el proceso descrito.

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

Tokens de usuario individual (OAuth)

Pase tokens de usuario individuales al crear sesiones. Consulte Configuración de OAuth de GitHub para obtener el flujo 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 (sin autenticación de GitHub)

Use sus propias claves de API para el proveedor de modelos. Consulte BYOK (bring your own key) para obtener más información.

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,
    },
});

Patrones de back-end comunes

API web con Express

Diagrama: Diagrama de flujo que muestra el proceso 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);

Trabajo en 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
}

Implementación de 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: Diagrama de flujo que muestra el proceso descrito.

Exámenes de salud

Supervise el estado del servidor de la CLI:

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

Limpieza de sesión

Los servicios back-end deben limpiar activamente las sesiones para evitar pérdidas 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);

Limitaciones

LimitaciónDetalles
Servidor de la CLI único = punto único de errorConsulte Escalabilidad y multitenencia para los patrones de alta disponibilidad.
Ninguna autenticación integrada entre el SDK y la CLIProteger la ruta de acceso de red (el mismo host, VPC, etc.)
Estado de sesión en el disco localMontar almacenamiento persistente para los reinicios del contenedor
Tiempo de espera de inactividad de 30 minutosLas sesiones sin actividad se limpian automáticamente

Cuándo seguir adelante

RequisitoGuía siguiente
Varios servidores de la CLI o alta disponibilidad
Escalabilidad y multitenencia
autenticación de cuenta de GitHub para usuarios
Configuración de OAuth de GitHub
Sus propias claves de modelo
BYOK (bring your own key)

Pasos siguientes