Observação
SDK do Copilot está atualmente em versão prévia técnica. A funcionalidade e a disponibilidade estão sujeitas a alterações.
Agentes personalizados são as definições de agentes leves que você anexa a uma sessão. Cada agente tem seu próprio prompt do sistema, restrições de ferramenta e servidores MCP opcionais. Quando a solicitação de um usuário corresponde à especialização de um agente, o SDK do Copilot runtime delega automaticamente a esse agente como um subagente, executando-o em um contexto isolado enquanto transmite eventos de ciclo de vida de volta para a sessão pai. Para obter uma visão geral visual do fluxo de delegação, consulte o github/copilot-sdk repositório.
| Conceito | Descrição |
|---|
**Agente personalizado** | Uma configuração de agente nomeado com seu próprio prompt e conjunto de ferramentas |
| Subagente | Um agente personalizado invocado pelo runtime para lidar com parte de uma tarefa | | Inferência | A capacidade do runtime de selecionar automaticamente um agente com base na intenção do usuário | | Sessão principal | A sessão que gerou o subagente; recebe todos os eventos do ciclo de vida. |
Definindo agentes personalizados
Passe customAgents ao criar uma sessão. No mínimo, cada agente precisa de um name e 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 obter exemplos em Python, Go e .NET, consulte o github/copilot-sdk repositório.
Referência de configuração
| Propriedade | Tipo | Obrigatório | Descrição |
|---|---|---|---|
name | string | ✅ | Identificador exclusivo para o agente |
displayName | string | ||
| Nome legível por humanos exibido em eventos | |||
description | string | ||
| O que o agente faz — ajuda o runtime a selecioná-lo | |||
tools |
`string[]` ou `null` |
| Nomes de ferramentas que o agente pode usar.
null ou excluído = todas as ferramentas |
| prompt | string | ✅ | Comando do sistema ao agente |
| mcpServers | object |
| Configurações de servidor MCP específicas para este agente |
| infer | boolean |
| Se o runtime pode selecionar automaticamente este agente (padrão: true) |
Dica
Um bom description ajuda o runtime a corresponder a intenção do usuário com o agente certo. Seja específico sobre a experiência e as funcionalidades do agente.
Além da configuração por agente, você pode definir agent na configuração da sessão para selecionar previamente qual agente personalizado está ativo quando a sessão é iniciada.
| Propriedade de configuração de sessão | Tipo | Descrição |
|---|---|---|
agent | string | Nome do agente personalizado a ser pré-selecionado na criação da sessão. Deve corresponder a um name em customAgents. |
Selecionando um agente na criação da sessão
Você pode passar agent na configuração da sessão para predefinir qual agente personalizado deverá ser ativado quando a sessão for iniciada. O valor deve corresponder ao name de um dos agentes definidos em 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 obter exemplos em Python, Go e .NET, consulte o github/copilot-sdk repositório.
Como funciona a delegação de subagente
Quando você envia um prompt para uma sessão com agentes personalizados, o runtime avalia se deseja delegar a um subagente:
-
**Correspondência de intenção** – o runtime analisa o prompt do usuário em relação a cada agente `name` e `description` -
**Seleção de agente**— Se uma correspondência for encontrada e `infer` não for `false`, o runtime selecionará o agente -
**Execução isolada** – o sub-agente é executado com seu próprio prompt e conjunto de ferramentas restritas -
**Transmissão de** eventos — eventos de ciclo de vida (`subagent.started`, `subagent.completed` etc.) são transmitidos de volta para a sessão pai -
**Integração de resultados** – a saída do sub-agente é incorporada à resposta do agente pai
Controlando a inferência
Por padrão, todos os agentes personalizados estão disponíveis para seleção automática (infer: true). Defina infer: false para impedir que o runtime selecione automaticamente um agente, útil para agentes que você só deseja invocar por meio de solicitações explícitas do usuário:
{
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
}
Escutando eventos de subagente
Quando um subagente é executado, a sessão pai emite eventos de ciclo de vida. Assine esses eventos para criar UIs que visualizam a atividade do agente.
Tipos de evento
| Acontecimento | Emitido quando | Dados |
|---|---|---|
subagent.selected | O runtime seleciona um agente para a tarefa |
`agentName`
`agentDisplayName`
`tools`
|
| subagent.started | Subagente inicia a execução |
toolCallId, agentName, , agentDisplayName``agentDescription |
| subagent.completed | O subagente foi concluído com êxito |
toolCallId
agentName
agentDisplayName
|
| subagent.failed | O subagente encontra um erro |
toolCallId, agentName, , agentDisplayName``error |
| subagent.deselected | O runtime muda seu foco do sub-agente | — |
Inscrevendo-se para 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 obter exemplos em Python, Go e .NET, consulte o github/copilot-sdk repositório.
Construindo uma interface do usuário de árvore de agente
Eventos de subagente incluem campos que permitem toolCallId reconstruir a árvore de execução. Aqui está um padrão para acompanhar a atividade do 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);
});
Ferramentas de escopo por agente
Use a tools propriedade para restringir quais ferramentas um agente pode acessar. Isso é essencial para a segurança e para manter os agentes focados:
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.",
},
],
});
Observação
Quando tools é null ou omitido, o agente herda o acesso a todas as ferramentas configuradas na sessão. Use listas de ferramentas explícitas para impor o princípio do privilégio mínimo.
Anexando servidores MCP a agentes
Cada agente personalizado pode ter seus próprios servidores MCP (Model Context Protocol), dando-lhe acesso a fontes de dados especializadas:
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"],
},
},
},
],
});
Padrões e melhores práticas
Emparelhar um pesquisador com um editor
Um padrão comum é definir um agente de pesquisa somente leitura e um agente editor com capacidade de escrita. O tempo de execução delega tarefas de exploração ao pesquisador e tarefas de modificação ao 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.",
},
]
Manter descrições de agente específicas
O runtime usa o description para corresponder à intenção do usuário. Descrições vagas levam à má delegação:
// ❌ 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" }
Lidar com falhas de forma elegante
Sub-agentes podem falhar. Sempre ouça subagent.failed eventos e manipule-os em seu aplicativo:
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
}
});