참고
코필로트 SDK가 현재 기술 미리 보기에 있습니다. 기능 및 가용성은 변경될 수 있습니다.
사용자 지정 에이전트는 세션에 연결하는 간단한 에이전트 정의입니다. 각 에이전트에는 고유한 시스템 프롬프트, 도구 제한 및 선택적 MCP 서버가 있습니다. 사용자의 요청이 에이전트의 전문 지식 코필로트 SDK 과 일치하면 런타임은 자동으로 해당 에이전트를 하위 에이전트로 위임하여 수명 주기 이벤트를 부모 세션으로 다시 스트리밍하는 동안 격리된 컨텍스트에서 실행합니다. 위임 흐름의 시각적 개요는 리포지토리를github/copilot-sdk 참조하세요.
| 개념 | 설명 |
|---|
**사용자 지정 에이전트** | 고유한 프롬프트 및 도구 집합이 있는 명명된 에이전트 구성 |
| 하위 에이전트 | 태스크의 일부를 처리하기 위해 런타임에서 호출한 사용자 지정 에이전트 | | 유추 | 사용자의 의도에 따라 에이전트를 자동으로 선택하는 런타임의 기능 | | 부모 세션 | 하위 에이전트를 생성한 세션입니다. 는 모든 수명 주기 이벤트를 수신합니다. |
사용자 지정 에이전트 정의
세션을 만들 때 customAgents 를 전달합니다. 최소한 각 에이전트에는 name 및 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" }),
});
Python, Go 및 .NET의 예제는 리포지토리를github/copilot-sdk 참조하세요.
구성 참조
| 재산 | 유형 | 필수 | 설명 |
|---|---|---|---|
name | string | ✅ | 에이전트의 고유 식별자 |
displayName | string | ||
| 이벤트에 표시된 사람이 읽을 수 있는 이름 | |||
description | string | ||
| 에이전트가 수행하는 작업 - 런타임에서 선택하는 데 도움이 됩니다. | |||
tools |
`string[]` 또는 `null` |
| 에이전트에서 사용할 수 있는 도구의 이름입니다.
null 또는 생략 = 모든 도구 |
| prompt | string | ✅ | 에이전트에 대한 시스템 프롬프트 |
| mcpServers | object |
| 이 에이전트와 관련된 MCP 서버 구성 |
| infer | boolean |
| 런타임에서 이 에이전트를 자동으로 선택할 수 있는지 여부(기본값: true) |
팁
좋은 description 방법은 런타임이 사용자 의도를 올바른 에이전트와 일치시킬 수 있도록 도와줍니다. 에이전트의 전문 지식과 기능에 대해 자세히 설명합니다.
에이전트별 구성 외에도 agent을 설정 **** 하여 세션이 시작될 때 활성 상태인 사용자 지정 에이전트를 미리 선택할 수 있습니다.
| 세션 구성 속성 | 유형 | 설명 |
|---|---|---|
agent | string | 세션을 만들 때 미리 선택할 사용자 지정 에이전트의 이름입니다. |
`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 참조하세요.
하위 에이전트 위임의 작동 방식
사용자 지정 에이전트를 사용하여 세션에 프롬프트를 보내면 런타임은 하위 에이전트에 위임할지 여부를 평가합니다.
-
**의도 일치** - 런타임은 사용자의 프롬프트를 각 에이전트의 `name` 및 `description`에 대해 분석합니다. -
**에이전트 선택** - 일치 항목이 발견되고 `infer` 없는 `false`경우 런타임에서 에이전트를 선택합니다. -
**격리된 실행** - 하위 에이전트는 자체 프롬프트 및 제한된 도구 집합으로 실행됩니다. -
**이벤트 스트리밍** - 수명 주기 이벤트(`subagent.started`, `subagent.completed`등)가 부모 세션으로 다시 스트리밍됩니다. -
**결과 통합** - 하위 에이전트의 출력이 부모 에이전트의 응답에 통합됩니다.
유추 제어
기본적으로 모든 사용자 지정 에이전트는 자동 선택(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
}
});