Skip to main content

사용자 정의 에이전트 및 하위 에이전트 오케스트레이션

범위가 지정된 도구 및 프롬프트를 사용하여 특수 에이전트를 정의하고 단일 세션 내에서 하위 에이전트로 오케스트레이션할 수 있습니다 Copilot .

누가 이 기능을 사용할 수 있나요?

GitHub Copilot SDK 는 모든 Copilot 계획에서 사용할 수 있습니다.

참고

          코필로트 SDK가 현재 기술 미리 보기에 있습니다. 기능 및 가용성은 변경될 수 있습니다.

사용자 지정 에이전트는 세션에 연결하는 간단한 에이전트 정의입니다. 각 에이전트에는 고유한 시스템 프롬프트, 도구 제한 및 선택적 MCP 서버가 있습니다. 사용자의 요청이 에이전트의 전문 지식 코필로트 SDK 과 일치하면 런타임은 자동으로 해당 에이전트를 하위 에이전트로 위임하여 수명 주기 이벤트를 부모 세션으로 다시 스트리밍하는 동안 격리된 컨텍스트에서 실행합니다. 위임 흐름의 시각적 개요는 리포지토리를github/copilot-sdk 참조하세요.

개념설명
          **사용자 지정 에이전트** | 고유한 프롬프트 및 도구 집합이 있는 명명된 에이전트 구성 |

| 하위 에이전트 | 태스크의 일부를 처리하기 위해 런타임에서 호출한 사용자 지정 에이전트 | | 유추 | 사용자의 의도에 따라 에이전트를 자동으로 선택하는 런타임의 기능 | | 부모 세션 | 하위 에이전트를 생성한 세션입니다. 는 모든 수명 주기 이벤트를 수신합니다. |

사용자 지정 에이전트 정의

세션을 만들 때 customAgents 를 전달합니다. 최소한 각 에이전트에는 nameprompt가 필요합니다.

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

Python, Go 및 .NET의 예제는 리포지토리를github/copilot-sdk 참조하세요.

구성 참조

재산유형필수설명
namestring에이전트의 고유 식별자
displayNamestring
이벤트에 표시된 사람이 읽을 수 있는 이름
descriptionstring
에이전트가 수행하는 작업 - 런타임에서 선택하는 데 도움이 됩니다.
tools
          `string[]` 또는 `null` |

| 에이전트에서 사용할 수 있는 도구의 이름입니다. null 또는 생략 = 모든 도구 | | prompt | string | ✅ | 에이전트에 대한 시스템 프롬프트 | | mcpServers | object | | 이 에이전트와 관련된 MCP 서버 구성 | | infer | boolean | | 런타임에서 이 에이전트를 자동으로 선택할 수 있는지 여부(기본값: true) |

좋은 description 방법은 런타임이 사용자 의도를 올바른 에이전트와 일치시킬 수 있도록 도와줍니다. 에이전트의 전문 지식과 기능에 대해 자세히 설명합니다.

에이전트별 구성 외에도 agent을 설정 **** 하여 세션이 시작될 때 활성 상태인 사용자 지정 에이전트를 미리 선택할 수 있습니다.

세션 구성 속성유형설명
agentstring세션을 만들 때 미리 선택할 사용자 지정 에이전트의 이름입니다.
          `customAgents` 내에서 `name`와 일치해야 합니다. |

세션 생성 시 에이전트 선택

세션 구성을 전달 agent 하여 세션이 시작될 때 활성화해야 하는 사용자 지정 에이전트를 미리 선택할 수 있습니다. 값은 에 name 정의된 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
});

Python, Go 및 .NET의 예제는 리포지토리를github/copilot-sdk 참조하세요.

하위 에이전트 위임의 작동 방식

사용자 지정 에이전트를 사용하여 세션에 프롬프트를 보내면 런타임은 하위 에이전트에 위임할지 여부를 평가합니다.

  1.        **의도 일치** - 런타임은 사용자의 프롬프트를 각 에이전트의 `name` 및 `description`에 대해 분석합니다.
    
  2.        **에이전트 선택** - 일치 항목이 발견되고 `infer` 없는 `false`경우 런타임에서 에이전트를 선택합니다.
    
  3.        **격리된 실행** - 하위 에이전트는 자체 프롬프트 및 제한된 도구 집합으로 실행됩니다.
    
  4.        **이벤트 스트리밍** - 수명 주기 이벤트(`subagent.started`, `subagent.completed`등)가 부모 세션으로 다시 스트리밍됩니다.
    
  5.        **결과 통합** - 하위 에이전트의 출력이 부모 에이전트의 응답에 통합됩니다.
    

유추 제어

기본적으로 모든 사용자 지정 에이전트는 자동 선택(infer: true)에 사용할 수 있습니다. 런타임이 에이전트를 자동으로 선택하지 않도록 infer: false를 설정합니다. 명시적 사용자 요청을 통해서만 호출하려는 에이전트에 유용합니다.

{
    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
}

하위 에이전트 이벤트 수신 대기

하위 에이전트가 실행되면 부모 세션은 수명 주기 이벤트를 내보냅니다. 이러한 이벤트를 구독하여 에이전트 활동을 시각화하는 UI를 빌드합니다.

이벤트 유형

이벤트내보낸 경우데이터
subagent.selected런타임이 작업에 대한 에이전트를 선택합니다.
          `agentName`, `agentDisplayName`, `tools` |

| subagent.started | 하위 에이전트가 실행을 시작합니다. | toolCallId, agentName, , agentDisplayName, agentDescription | | subagent.completed | 하위 에이전트가 성공적으로 완료되었습니다. | toolCallId, agentName, agentDisplayName | | subagent.failed | 하위 에이전트에서 오류가 발생합니다. | toolCallId, agentName, , agentDisplayName, error | | subagent.deselected | 런타임이 하위 에이전트에서 멀리 전환됩니다. | — |

이벤트 구독

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

Python, Go 및 .NET의 예제는 리포지토리를github/copilot-sdk 참조하세요.

에이전트 트리 UI 빌드

하위 에이전트 이벤트에는 실행 트리를 다시 구성할 수 있는 필드가 포함 toolCallId 됩니다. 다음은 에이전트 활동을 추적하는 패턴입니다.

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

에이전트별 범위 지정 도구

tools 속성을 사용하여 에이전트가 액세스할 수 있는 도구를 제한합니다. 이는 보안 및 에이전트의 집중을 유지하는 데 필수적입니다.

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

참고

          `tools`가 `null`이거나 생략된 경우, 에이전트는 세션에 구성된 모든 도구에 대한 액세스를 상속받습니다. 명시적 도구 목록을 사용하여 최소 권한 원칙을 적용합니다.

에이전트에 MCP 서버 연결

각 사용자 지정 에이전트에는 고유한 MCP(모델 컨텍스트 프로토콜) 서버가 있어 특수 데이터 원본에 액세스할 수 있습니다.

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

패턴 및 모범 사례

연구원과 편집기 페어링

일반적인 패턴은 읽기 전용 연구원 에이전트 및 쓰기 가능 편집기 에이전트를 정의하는 것입니다. 런타임은 탐색 작업을 연구원에게 위임하고 수정 작업을 편집기로 위임합니다.

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.",
    },
]

에이전트 설명을 구체적으로 유지

런타임은 사용자 의도와 description 일치하도록 사용합니다. 모호한 설명은 잘못된 위임으로 이어질 수 있습니다.

// ❌ 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" }

오류를 정상적으로 처리

하위 에이전트는 실패할 수 있습니다. 항상 subagent.failed 이벤트를 수신 대기하고 애플리케이션에서 처리합니다.

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