Skip to main content

Agentes personalizados y orquestación de subagentes

Defina agentes especializados con herramientas y directivas delimitadas y permita que Copilot los gestione como subagentes dentro de una sola sesión.

¿Quién puede utilizar esta característica?

SDK de GitHub Copilot está disponible con todos los Copilot planes.

Nota:

SDK de Copilot actualmente está en versión preliminar pública. La funcionalidad y la disponibilidad están sujetas a cambios.

Los agentes personalizados son definiciones de agente ligeras que se adjuntan a una sesión. Cada agente tiene su propia solicitud del sistema, restricciones de herramientas y servidores MCP opcionales. Cuando la solicitud de un usuario coincide con la experiencia de un agente, el SDK de Copilot entorno de ejecución se delega automáticamente en ese agente como subagente, ejecutándolo en un contexto aislado mientras transmite eventos del ciclo de vida a la sesión principal. Para obtener información general visual sobre el flujo de delegación, consulte el github/copilot-sdk repositorio.

ConceptoDescripción
Agente personalizadoConfiguración de agente nombrada con su propio indicador y conjunto de herramientas
SubagenteUn agente personalizado invocado por el tiempo de ejecución para controlar parte de una tarea
InferenciaLa capacidad del tiempo de ejecución para seleccionar automáticamente un agente en función de la intención del usuario
Sesión principalSesión que generó el subagente; recibe todos los eventos del ciclo de vida.

Definición de agentes personalizados

Pase customAgents al crear una sesión. Como mínimo, cada agente necesita un name y un prompt.

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

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

const session = await client.createSession({
    model: "gpt-4.1",
    customAgents: [
        {
            name: "researcher",
            displayName: "Research Agent",
            description: "Explores codebases and answers questions using read-only tools",
            tools: ["grep", "glob", "view"],
            prompt: "You are a research assistant. Analyze code and answer questions. Do not modify any files.",
        },
        {
            name: "editor",
            displayName: "Editor Agent",
            description: "Makes targeted code changes",
            tools: ["view", "edit", "bash"],
            prompt: "You are a code editor. Make minimal, surgical changes to files as requested.",
        },
    ],
    onPermissionRequest: async () => ({ kind: "approved" }),
});

Para obtener ejemplos en Python, Go y .NET, consulte el github/copilot-sdk repositorio. Para Java, consulte el github/copilot-sdk-java repositorio.

Referencia de configuración

PropiedadTipoObligatorioDescripción
namestringIdentificador único del agente
displayNamestringNoNombre comprensible que se muestra en eventos
descriptionstringNoLo que hace el agente: ayuda al tiempo de ejecución a seleccionarlo.
tools
string[] o nullNoNombres de herramientas que puede usar el agente.
null o se omite = todas las herramientas
promptstringIndicativo del sistema para el agente
mcpServersobjectNoConfiguraciones de servidor MCP específicas de este agente
inferbooleanNoSi el entorno de ejecución puede seleccionar automáticamente este agente (valor predeterminado: true)
skillsstring[]NoNombres de las habilidades que se precargarán en el contexto del agente al iniciarse

Sugerencia

Una buena description ayuda al entorno de ejecución a coincidir la intención del usuario con el agente correcto. Sea específico sobre la experiencia y las funcionalidades del agente.

Además de la configuración por agente, puede establecer agent en la configuración de sesión para seleccionar previamente qué agente personalizado está activo cuando se inicia la sesión.

Propiedad de configuración de sesiónTipoDescripción
agentstringNombre del agente personalizado que se va a seleccionar previamente en la creación de la sesión. Debe coincidir con un name en customAgents.

Aptitudes por agente

Puede precargar habilidades en el contexto de un agente mediante la propiedad skills. Cuando se especifica, el contenido íntegro de cada habilidad enumerada se incorpora directamente al contexto del agente durante el inicio; el agente no necesita invocar una herramienta de habilidad, ya que las instrucciones ya están presentes. Las aptitudes son opcionales: los agentes no reciben aptitudes de forma predeterminada y los subagentes no heredan las aptitudes del elemento primario. Los nombres de habilidad se resuelven a partir de skillDirectories de nivel de sesión.

const session = await client.createSession({
    skillDirectories: ["./skills"],
    customAgents: [
        {
            name: "security-auditor",
            description: "Security-focused code reviewer",
            prompt: "Focus on OWASP Top 10 vulnerabilities",
            skills: ["security-scan", "dependency-check"],
        },
        {
            name: "docs-writer",
            description: "Technical documentation writer",
            prompt: "Write clear, concise documentation",
            skills: ["markdown-lint"],
        },
    ],
    onPermissionRequest: async () => ({ kind: "approved" }),
});

En este ejemplo, security-auditor comienza con security-scan y dependency-check ya insertado en su contexto, mientras que docs-writer comienza con markdown-lint. Un agente sin un skills campo no recibe contenido de aptitudes.

Para obtener ejemplos en otros idiomas, consulte el github/copilot-sdk repositorio. Para Java, consulte el github/copilot-sdk-java repositorio.

Selección de un agente al crear la sesión

Puede introducir agent en la configuración de la sesión para preseleccionar qué agente personalizado estará activo cuando la sesión comience. El valor debe coincidir con el name de uno de los agentes definidos en customAgents.

const session = await client.createSession({
    customAgents: [
        {
            name: "researcher",
            prompt: "You are a research assistant. Analyze code and answer questions.",
        },
        {
            name: "editor",
            prompt: "You are a code editor. Make minimal, surgical changes.",
        },
    ],
    agent: "researcher", // Pre-select the researcher agent
});

Para obtener ejemplos en Python, Go y .NET, consulte el github/copilot-sdk repositorio. Para Java, consulte el github/copilot-sdk-java repositorio.

Funcionamiento de la delegación de subagentes

Cuando se envía una solicitud a una sesión con agentes personalizados, el tiempo de ejecución evalúa si se va a delegar en un subagente:

  1. Coincidencia de intenciones: el tiempo de ejecución analiza el mensaje del usuario con respecto a los agentes name y description
  2. Selección del agente: si se encuentra una coincidencia y infer no es false, el tiempo de ejecución selecciona al agente.
  3. Ejecución aislada: el subagente se ejecuta con su propio símbolo del sistema y un conjunto de herramientas restringido
  4. Transmisión de eventos: los eventos de ciclo de vida (subagent.started, subagent.completed, etc.) vuelven a la sesión principal.
  5. Integración de resultados: la salida del subagente se incorpora a la respuesta del agente principal.

Control de la inferencia

De forma predeterminada, todos los agentes personalizados están disponibles para la selección automática (infer: true). Establézcalo infer: false para impedir que el tiempo de ejecución seleccione automáticamente un agente, útil para los agentes que solo desea invocar a través de solicitudes de usuario explícitas:

{
    name: "dangerous-cleanup",
    description: "Deletes unused files and dead code",
    tools: ["bash", "edit", "view"],
    prompt: "You clean up codebases by removing dead code and unused files.",
    infer: false, // Only invoked when user explicitly asks for this agent
}

Escuchando eventos del subagente

Cuando se ejecuta un subagente, la sesión primaria emite eventos de ciclo de vida. Suscríbase a estos eventos para crear interfaces de usuario que visualicen la actividad del agente.

Tipos de evento

EventEmitido cuandoDatos
subagent.selectedRuntime selecciona un agente para la tarea.
agentName, , agentDisplayName, tools
subagent.startedEl subagente inicia la ejecución
toolCallId, agentName, , agentDisplayName, agentDescription
subagent.completedEl subagente finaliza correctamente
toolCallId, , agentName, agentDisplayName
subagent.failedSubagente encuentra un error
toolCallId, agentName, , agentDisplayName, error
subagent.deselectedTiempo de ejecución se aleja del subagenteNinguno

Suscribirse a eventos

session.on((event) => {
    switch (event.type) {
        case "subagent.started":
            console.log(`▶ Sub-agent started: ${event.data.agentDisplayName}`);
            console.log(`  Description: ${event.data.agentDescription}`);
            console.log(`  Tool call ID: ${event.data.toolCallId}`);
            break;

        case "subagent.completed":
            console.log(`✅ Sub-agent completed: ${event.data.agentDisplayName}`);
            break;

        case "subagent.failed":
            console.log(`❌ Sub-agent failed: ${event.data.agentDisplayName}`);
            console.log(`  Error: ${event.data.error}`);
            break;

        case "subagent.selected":
            console.log(`🎯 Agent selected: ${event.data.agentDisplayName}`);
            console.log(`  Tools: ${event.data.tools?.join(", ") ?? "all"}`);
            break;

        case "subagent.deselected":
            console.log("↩ Agent deselected, returning to parent");
            break;
    }
});

const response = await session.sendAndWait({
    prompt: "Research how authentication works in this codebase",
});

Para obtener ejemplos en Python, Go y .NET, consulte el github/copilot-sdk repositorio. Para Java, consulte el github/copilot-sdk-java repositorio.

Creación de una interfaz de usuario de árbol de agente

Los eventos de subagente incluyen toolCallId campos que permiten reconstruir el árbol de ejecución. Este es un patrón para realizar el seguimiento de la actividad del agente:

interface AgentNode {
    toolCallId: string;
    name: string;
    displayName: string;
    status: "running" | "completed" | "failed";
    error?: string;
    startedAt: Date;
    completedAt?: Date;
}

const agentTree = new Map<string, AgentNode>();

session.on((event) => {
    if (event.type === "subagent.started") {
        agentTree.set(event.data.toolCallId, {
            toolCallId: event.data.toolCallId,
            name: event.data.agentName,
            displayName: event.data.agentDisplayName,
            status: "running",
            startedAt: new Date(event.timestamp),
        });
    }

    if (event.type === "subagent.completed") {
        const node = agentTree.get(event.data.toolCallId);
        if (node) {
            node.status = "completed";
            node.completedAt = new Date(event.timestamp);
        }
    }

    if (event.type === "subagent.failed") {
        const node = agentTree.get(event.data.toolCallId);
        if (node) {
            node.status = "failed";
            node.error = event.data.error;
            node.completedAt = new Date(event.timestamp);
        }
    }

    // Render your UI with the updated tree
    renderAgentTree(agentTree);
});

Herramientas de definición por agente

Use la tools propiedad para restringir las herramientas a las que puede acceder un agente. Esto es esencial para la seguridad y para mantener los agentes centrados:

const session = await client.createSession({
    customAgents: [
        {
            name: "reader",
            description: "Read-only exploration of the codebase",
            tools: ["grep", "glob", "view"],  // No write access
            prompt: "You explore and analyze code. Never suggest modifications directly.",
        },
        {
            name: "writer",
            description: "Makes code changes",
            tools: ["view", "edit", "bash"],   // Write access
            prompt: "You make precise code changes as instructed.",
        },
        {
            name: "unrestricted",
            description: "Full access agent for complex tasks",
            tools: null,                        // All tools available
            prompt: "You handle complex multi-step tasks using any available tools.",
        },
    ],
});

Nota:

Cuando tools es null o se omite, el agente hereda el acceso a todas las herramientas configuradas en la sesión. Use listas de herramientas explícitas para aplicar el principio de privilegios mínimos.

Herramientas exclusivas del agente

Utilice la propiedad defaultAgent en la configuración de la sesión para ocultar determinadas herramientas al agente predeterminado (el agente integrado que gestiona los turnos cuando no se selecciona ningún agente personalizado). Esto obliga al agente principal a delegar a los subagentes cuando se necesitan las funcionalidades de esas herramientas, manteniendo limpio el contexto del agente principal.

Resulta útil cuando:

  • Algunas herramientas generan grandes cantidades de contexto que sobrecargarían al agente principal.
  • Quiere que el agente principal actúe como orquestador y delega trabajos pesados a subagentes especializados.
  • Necesita una separación estricta entre orquestación y ejecución.
import { CopilotClient, defineTool, approveAll } from "@github/copilot-sdk";
import { z } from "zod";

const heavyContextTool = defineTool("analyze-codebase", {
    description: "Performs deep analysis of the codebase, generating extensive context",
    parameters: z.object({ query: z.string() }),
    handler: async ({ query }) => {
        // ... expensive analysis that returns lots of data
        return { analysis: "..." };
    },
});

const session = await client.createSession({
    tools: [heavyContextTool],
    defaultAgent: {
        excludedTools: ["analyze-codebase"],
    },
    customAgents: [
        {
            name: "researcher",
            description: "Deep codebase analysis agent with access to heavy-context tools",
            tools: ["analyze-codebase"],
            prompt: "You perform thorough codebase analysis using the analyze-codebase tool.",
        },
    ],
});

Para obtener ejemplos en Python, Go y .NET, consulte el github/copilot-sdk repositorio. Para Java, consulte el github/copilot-sdk-java repositorio.

Cómo funciona

Herramientas enumeradas en defaultAgent.excludedTools:

  1. Están registrados: sus controladores están disponibles para su ejecución.
  2. Están ocultas en la lista de herramientas del agente principal; el LLM no las verá ni las invocará directamente.
  3. Permanezca disponible para cualquier subagente personalizado que los incluya en su tools matriz.

Interacción con otros filtros de herramientas

defaultAgent.excludedTools es ortogonal al nivel availableTools de sesión y excludedTools:

FilterÁmbitoEfecto
availableToolsToda la sesiónLista de permitidos: solo existen estas herramientas para cualquier persona
excludedToolsToda la sesiónLista de bloqueados: estas herramientas están bloqueadas para todos los usuarios
defaultAgent.excludedToolsSolo agente principalEstas herramientas están ocultas del agente principal, pero están disponibles para los subagentes

Precedencia:

  1. El nivel de sesión availableTools/excludedTools se aplica primero (globalmente)
  2. defaultAgent.excludedTools se aplica encima, lo que restringe aún más solo al agente principal

Nota:

Si una herramienta está en excludedTools (nivel de sesión) y defaultAgent.excludedTools, la exclusión de nivel de sesión tiene prioridad, la herramienta no está disponible para todos.

Adjuntar servidores MCP a agentes

Cada agente personalizado puede tener sus propios servidores MCP (Protocolo de contexto de modelo), lo que le proporciona acceso a orígenes de datos especializados:

const session = await client.createSession({
    customAgents: [
        {
            name: "db-analyst",
            description: "Analyzes database schemas and queries",
            prompt: "You are a database expert. Use the database MCP server to analyze schemas.",
            mcpServers: {
                "database": {
                    command: "npx",
                    args: ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"],
                },
            },
        },
    ],
});

Patrones y procedimientos recomendados

Emparejar un investigador con un editor

Un patrón común es definir un agente investigador de solo lectura y un agente editor capaz de escritura. El tiempo de ejecución delega las tareas de exploración al investigador y las tareas de modificación al editor:

customAgents: [
    {
        name: "researcher",
        description: "Analyzes code structure, finds patterns, and answers questions",
        tools: ["grep", "glob", "view"],
        prompt: "You are a code analyst. Thoroughly explore the codebase to answer questions.",
    },
    {
        name: "implementer",
        description: "Implements code changes based on analysis",
        tools: ["view", "edit", "bash"],
        prompt: "You make minimal, targeted code changes. Always verify changes compile.",
    },
]

Mantener las descripciones del agente específicas

El tiempo de ejecución usa el description para que coincida con la intención del usuario. Las descripciones vagas conducen a una delegación deficiente:

// ❌ Too vague — runtime can't distinguish from other agents
{ description: "Helps with code" }

// ✅ Specific — runtime knows when to delegate
{ description: "Analyzes Python test coverage and identifies untested code paths" }

Gestiona los fallos de manera elegante

Los subagentes pueden fallar. Escuche siempre los eventos de subagent.failed y manéjelos en su aplicación.

session.on((event) => {
    if (event.type === "subagent.failed") {
        logger.error(`Agent ${event.data.agentName} failed: ${event.data.error}`);
        // Show error in UI, retry, or fall back to parent agent
    }
});