Microsoft의 에이전트 프레임워크를 사용하여 다중 에이전트 AI 시스템 구축
소개
우리는 멀티 에이전트 AI 시스템 시대에 들어섰습니다. 모든 것을 처리하는 단일 모놀리식 AI 대신, 업계는 잘 조직된 전문가 팀처럼 복잡한 문제를 해결하기 위해 협력하는 전문 에이전트로 전환하고 있습니다. 한 에이전트는 조사하고, 다른 에이전트는 분석하고, 세 번째 에이전트는 작성하고, 코디네이터는 모든 사람의 정보를 추적합니다.
대규모 언어 모델로 작업한 경우 단일 프롬프트로 수행할 수 있는 작업의 한계에 도달했을 가능성이 높습니다. 컨텍스트 창이 가득 차고 지침이 엉키며 품질이 저하됩니다. 다중 에이전트 아키텍처는 복잡한 작업을 각 에이전트가 한 분야의 전문가인 집중된 책임으로 분해하여 이 문제를 해결합니다.
광범위한 Semantic Kernel 에코시스템의 일부인 Microsoft Agent Framework는 .NET 개발자에게 이러한 종류의 시스템을 구축하기 위한 최고의 도구 키트를 제공합니다. 이 게시물에서는 시작하는 데 필요한 핵심 개념, 오케스트레이션 패턴 및 실제 코드를 다루면서 완전하게 작동하는 다중 에이전트 파이프라인으로 이동합니다.
Microsoft의 에이전트 프레임워크란 무엇입니까?
에이전트 프레임워크는 .NET에서 AI 에이전트 및 다중 에이전트 시스템을 구축, 조정 및 배포하기 위한 Microsoft의 답변입니다. 이는 2023년부터 Microsoft의 AI 오케스트레이션을 위한 오픈 소스 SDK인 Semantic Kernel과 나란히 위치하며 긴밀하게 통합됩니다.
이렇게 생각해보세요. 의미론적 커널은 기본 요소(커널, 플러그인, 메모리, 플래너)를 제공하는 반면 에이전트 프레임워크는 에이전트 간 통신 및 조정을 위해 특별히 설계된 상위 수준 추상화를 제공합니다.
프레임워크는 Azure OpenAI, OpenAI 및 Azure AI Foundry에서 호스팅되는 모델을 포함한 여러 모델 공급자를 지원합니다. 디자인 면에서는 모델에 구애받지 않지만 Azure 에코시스템과 긴밀하게 통합되어 있어 엔터프라이즈 시나리오에 특히 매력적입니다.
주요 기능은 다음과 같습니다.
- 여러 에이전트 유형: 다양한 백엔드에 대한
ChatCompletionAgent,OpenAIAssistantAgent및AzureAIAgent - 오케스트레이션 패턴: 순차, 동시, 핸드오프 및 그룹 채팅 워크플로
- 플러그인 에코시스템: 기본 C# 기능, OpenAPI 사양 및 MCP(Model Context Protocol) 도구를 사용하여 에이전트 확장
- 대화 관리: 스레딩, 이력 관리, 종료 전략 내장
- 관찰 가능성: 에이전트 상호 작용 추적을 위해 OpenTelemetry와 통합
주요 개념
코드를 작성하기 전에 어휘를 설정해 보겠습니다. 에이전트 프레임워크는 몇 가지 핵심 추상화를 중심으로 진행됩니다.
에이전트
에이전트는 특정 지침(시스템 프롬프트), 이름 및 선택적으로 플러그인 또는 도구 세트로 구성된 AI 모델의 지원을 받는 엔터티입니다. 각 에이전트는 전문가입니다. 에이전트가 무엇을 알고 있는지, 무엇을 할 수 있는지, 어떻게 행동해야 하는지 정의할 수 있습니다.
ChatCompletionAgent가장 간단한 에이전트 유형입니다. 채팅 완료 엔드포인트(Azure OpenAI, OpenAI 등)를 래핑하고 대화를 유지 관리합니다. 호출 간에는 상태 비저장입니다. 기록을 제공하면 응답합니다. 이렇게 하면 가볍고 추론하기 쉽습니다.
ChatCompletionAgent agent = new()
{
Name = "Reviewer",
Instructions = "You are a senior code reviewer. Analyze the provided code for bugs, security issues, and style violations. Be concise and actionable.",
Kernel = kernel
};
OpenAIAssistantAgent
이 에이전트 유형은 서버 측 대화 상태, 파일 처리 및 코드 해석을 제공하는 OpenAI Assistants API를 활용합니다. 더 무겁지만 지속적인 스레드와 코드 해석기 및 파일 검색과 같은 내장 도구를 제공합니다.
OpenAIAssistantAgent agent = await OpenAIAssistantAgent.CreateAsync(
clientProvider: clientProvider,
definition: new OpenAIAssistantDefinition("gpt-4o")
{
Name = "DataAnalyst",
Instructions = "You analyze datasets and produce statistical summaries."
}
);
에이전트그룹채팅
오케스트레이터입니다. AgentGroupChat는 여러 에이전트 간의 다단계 대화를 관리하여 다음에 말할 사람, 대화 종료 시기 및 기록 공유 방법을 제어합니다. 다중 에이전트 협업의 마법이 일어나는 곳입니다.
오케스트레이션 패턴
프레임워크는 각기 다른 문제에 적합한 네 가지 기본 오케스트레이션 패턴을 지원합니다.
순차
에이전트는 정의된 순서에 따라 하나씩 실행됩니다. 에이전트 A의 출력은 에이전트 B로 공급되고, 에이전트 B의 출력은 에이전트 C로 공급됩니다. 이는 초안 → 검토 → 편집 → 게시와 같은 파이프라인에 이상적입니다.
// Conceptual flow
var draft = await writerAgent.InvokeAsync("Write a blog post about .NET 9");
var reviewed = await reviewerAgent.InvokeAsync($"Review this: {draft}");
var edited = await editorAgent.InvokeAsync($"Edit based on feedback: {reviewed}");
동시
여러 에이전트가 동일한 입력에 대해 동시에 작업합니다. 작업을 펼치고 결과를 집계합니다. 세 명의 검토자가 동일한 끌어오기 요청을 보는 것과 같이 다양한 관점을 얻는 데 적합합니다.
핸드오프
에이전트는 대화 컨텍스트를 기반으로 다른 에이전트에게 제어권을 이전하기로 결정합니다. 이는 고객 서비스 팀의 업무 방식을 모방합니다. 일선 상담원이 기본 쿼리를 처리하고 필요할 때 전문가에게 에스컬레이션합니다.
그룹 채팅
여러 에이전트가 선택 전략에 따라 차례로 공개 대화에 참여합니다. AgentGroupChat 클래스는 구성 가능한 차례 진행 및 종료 논리를 사용하여 이 패턴을 구현합니다.
첫 번째 에이전트 구축
실습해 봅시다. 첫 번째 에이전트를 단계별로 구축하는 방법은 다음과 같습니다.
전제조건
다음이 필요합니다.
- .NET 9 SDK
- 배포된 모델이 있는 Azure OpenAI 리소스(예:
gpt-4o) - 비주얼 스튜디오 또는 VS 코드
프로젝트 설정
새 콘솔 애플리케이션을 만들고 필요한 패키지를 설치합니다.
dotnet new console -n AgentDemo
cd AgentDemo
dotnet add package Microsoft.SemanticKernel --prerelease
dotnet add package Microsoft.SemanticKernel.Agents.Core --prerelease
dotnet add package Azure.AI.OpenAI
dotnet add package Azure.Identity
단순 에이전트 만들기
먼저 Azure OpenAI 구성으로 커널을 설정합니다.
using Azure.Identity;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;
var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4o",
endpoint: "https://your-resource.openai.azure.com/",
credentials: new DefaultAzureCredential()
);
Kernel kernel = builder.Build();
이제 에이전트를 생성하고 호출합니다.
ChatCompletionAgent agent = new()
{
Name = "TechWriter",
Instructions = """
You are a technical writer specializing in software documentation.
Write clear, concise content aimed at experienced developers.
Use code examples when appropriate.
Always structure your output with headings and bullet points.
""",
Kernel = kernel
};
ChatHistory history = new();
history.AddUserMessage("Explain dependency injection in .NET in 200 words.");
await foreach (ChatMessageContent response in agent.InvokeAsync(history))
{
Console.WriteLine(response.Content);
}
그게 다야. 근무 중인 에이전트가 있습니다. 하지만 진정한 힘은 상담원들이 함께 일할 때 나옵니다.
AgentGroupChat을 사용한 다중 에이전트 오케스트레이션
여러 에이전트가 협업하는 그룹 채팅이라는 좀 더 흥미로운 것을 만들어 보겠습니다. AgentGroupChat 클래스는 다음에 말할 사람과 중지할 시간을 포함하여 대화 흐름을 관리합니다.
에이전트 정의
작가, 리뷰어, 편집자의 세 가지 에이전트를 만듭니다.
ChatCompletionAgent writer = new()
{
Name = "Writer",
Instructions = """
You are a content writer. When given a topic, produce a well-structured
draft. Focus on clarity and technical accuracy.
When you receive feedback from the Reviewer, incorporate it into a
revised draft.
""",
Kernel = kernel
};
ChatCompletionAgent reviewer = new()
{
Name = "Reviewer",
Instructions = """
You are a content reviewer. Analyze drafts for technical accuracy,
clarity, and completeness. Provide specific, actionable feedback.
Do NOT rewrite the content — only provide feedback.
When the content meets your standards, respond with: APPROVED
""",
Kernel = kernel
};
ChatCompletionAgent editor = new()
{
Name = "Editor",
Instructions = """
You are an editor. Once content is approved by the Reviewer,
polish it for grammar, tone, and formatting.
Output only the final polished version.
When you have produced the final version, respond with: COMPLETE
""",
Kernel = kernel
};
그룹 채팅 설정하기
AgentGroupChat에는 선택 전략(다음에 말할 사람)과 종료 전략(중지할 시기)이라는 두 가지 핵심 구성이 필요합니다.
AgentGroupChat chat = new(writer, reviewer, editor)
{
ExecutionSettings = new()
{
SelectionStrategy = new SequentialSelectionStrategy(),
TerminationStrategy = new ApprovalTerminationStrategy()
{
Agents = [editor],
MaximumIterations = 12
}
}
};
맞춤형 종료 전략종료 전략은 대화가 끝나는 시기를 정의합니다. 다음은 “COMPLETE” 키워드를 찾는 사용자 정의입니다.
class ApprovalTerminationStrategy : TerminationStrategy
{
protected override Task<bool> ShouldAgentTerminateAsync(
Agent agent,
IReadOnlyList<ChatMessageContent> history,
CancellationToken cancellationToken = default)
{
bool isComplete = history
.Last()
.Content?
.Contains("COMPLETE", StringComparison.OrdinalIgnoreCase) ?? false;
return Task.FromResult(isComplete);
}
}
대화 실행하기
사용자 메시지로 대화를 시작하고 상담원이 협업할 수 있도록 하세요.
chat.AddChatMessage(
new ChatMessageContent(AuthorRole.User,
"Write a 300-word technical overview of gRPC vs REST for microservices.")
);
await foreach (ChatMessageContent message in chat.InvokeAsync())
{
Console.WriteLine($"[{message.AuthorName}]: {message.Content}");
Console.WriteLine("---");
}
흐름은 다음과 같습니다.
- 작가가 초안을 작성합니다.
- 검토자가 피드백을 제공합니다.
- 작가는 피드백을 바탕으로 수정합니다.
- 검토자가 “승인됨"이라고 말합니다.
- 편집자가 다듬고 “완료"라고 말합니다.
- 대화가 종료됩니다
이러한 앞뒤 이동은 종료 조건이 충족되거나 MaximumIterations에 도달할 때까지 자동으로 계속됩니다.
플러그인 및 도구
에이전트는 외부 시스템과 상호 작용할 수 있을 때 진정으로 강력해집니다. Agent Framework는 세 가지 주요 확장 메커니즘을 지원합니다.
기본 기능(커널 플러그인)
에이전트에 도구로 C# 메서드에 대한 액세스 권한을 부여할 수 있습니다. 에이전트는 필요하다고 판단되면 다음 함수를 호출합니다.
public class ContentToolsPlugin
{
[KernelFunction("word_count")]
[Description("Counts the number of words in the provided text.")]
public int WordCount([Description("The text to count words in")] string text)
{
return text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
}
[KernelFunction("check_readability")]
[Description("Calculates a readability score for the given text.")]
public string CheckReadability([Description("The text to analyze")] string text)
{
var words = text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
var sentences = text.Split(['.', '!', '?'], StringSplitOptions.RemoveEmptyEntries).Length;
if (sentences == 0) return "Unable to calculate — no sentences found.";
double avgWordsPerSentence = (double)words / sentences;
return avgWordsPerSentence switch
{
< 15 => $"Easy to read (avg {avgWordsPerSentence:F1} words/sentence)",
< 25 => $"Moderate difficulty (avg {avgWordsPerSentence:F1} words/sentence)",
_ => $"Difficult to read (avg {avgWordsPerSentence:F1} words/sentence). Consider shorter sentences."
};
}
}
에이전트를 만들기 전에 커널에 플러그인을 등록하세요.
kernel.Plugins.AddFromType<ContentToolsPlugin>();
ChatCompletionAgent analyst = new()
{
Name = "ContentAnalyst",
Instructions = "Analyze content using available tools. Report word count and readability.",
Kernel = kernel,
Arguments = new KernelArguments(
new PromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
})
};
모델 컨텍스트 프로토콜(MCP)
MCP는 AI 모델을 외부 도구 및 데이터 소스에 연결하기 위한 개방형 표준입니다. 에이전트 프레임워크는 MCP를 지원합니다. 즉, 에이전트는 모든 MCP 호환 서버에서 제공하는 도구를 사용할 수 있습니다. 이는 표준화된 인터페이스를 통해 파일 시스템, 데이터베이스, API 등에 대한 문을 열어줍니다.
// Example: Adding an MCP server for file operations
kernel.Plugins.AddFromMcpServer("filesystem",
new Uri("http://localhost:3000/mcp"));
이는 귀하의 에이전트가 귀하가 구축한 것에 국한되지 않고 다른 사람들이 개발하고 공유하는 MCP 도구 생태계를 활용할 수 있다는 것을 의미하기 때문에 특히 흥미롭습니다.
실제 사례: 콘텐츠 검토 파이프라인
실용적인 시나리오로 모든 것을 하나로 묶어 봅시다. 문서화 팀의 콘텐츠 검토를 자동화하는 내부 도구를 구축한다고 상상해 보십시오. 파이프라인에는 4단계가 있습니다.
- 연구원 — 관련 기술 정보 수집
- 작가 — 연구를 바탕으로 초안을 작성합니다.
- 검토자 — 정확성과 완전성을 확인합니다.
- 게시자 — 최종 출력 형식을 지정하고 준비합니다.
요약된 구현은 다음과 같습니다.
using Azure.Identity;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;
// Build the kernel
var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4o",
endpoint: "https://your-resource.openai.azure.com/",
credentials: new DefaultAzureCredential()
);
Kernel kernel = builder.Build();
// Define specialized agents
ChatCompletionAgent researcher = new()
{
Name = "Researcher",
Instructions = """
You are a technical researcher. Given a topic, identify the key
concepts, recent developments, and important details that should
be covered. Output a structured research brief.
""",
Kernel = kernel
};
ChatCompletionAgent writer = new()
{
Name = "Writer",
Instructions = """
You are a technical writer. Using the research brief provided,
write a comprehensive, well-structured article. Include code
examples where relevant. Target audience: experienced developers.
""",
Kernel = kernel
};
ChatCompletionAgent reviewer = new()
{
Name = "Reviewer",
Instructions = """
You are a senior technical reviewer. Check the article for:
- Technical accuracy
- Completeness relative to the research brief
- Code correctness
- Clarity and structure
If everything looks good, respond with APPROVED.
Otherwise, provide specific feedback for revision.
""",
Kernel = kernel
};
ChatCompletionAgent publisher = new()
{
Name = "Publisher",
Instructions = """
You are a content publisher. Once the article is approved,
format it with proper markdown, add a summary at the top,
and ensure consistent formatting throughout.
End your response with COMPLETE.
""",
Kernel = kernel
};
// Configure the group chat
AgentGroupChat chat = new(researcher, writer, reviewer, publisher)
{
ExecutionSettings = new()
{
SelectionStrategy = new SequentialSelectionStrategy(),
TerminationStrategy = new ApprovalTerminationStrategy()
{
Agents = [publisher],
MaximumIterations = 15
}
}
};
// Start the pipeline
chat.AddChatMessage(new ChatMessageContent(
AuthorRole.User,
"Create a technical article about implementing health checks in ASP.NET Core microservices."
));
await foreach (ChatMessageContent message in chat.InvokeAsync())
{
Console.ForegroundColor = message.AuthorName switch
{
"Researcher" => ConsoleColor.Cyan,
"Writer" => ConsoleColor.Green,
"Reviewer" => ConsoleColor.Yellow,
"Publisher" => ConsoleColor.Magenta,
_ => ConsoleColor.White
};
Console.WriteLine($"\n{'='new string('=', 60)}");
Console.WriteLine($"[{message.AuthorName}]");
Console.WriteLine(new string('=', 60));
Console.WriteLine(message.Content);
}
Console.ResetColor();
이 파이프라인은 에이전트 협업을 통해 완벽하게 조사하고, 작성하고, 검토하고, 형식화된 기사를 생성합니다. 각 에이전트는 자신이 가장 잘하는 일에 집중하고 AgentGroupChat는 워크플로를 조정합니다.
모범 사례
여러 다중 에이전트 시스템을 구축한 후 가장 가치 있다고 생각한 패턴과 사례는 다음과 같습니다.
오류 처리
종료 전략에 항상 MaximumIterations를 설정하세요. 이것이 없으면 상담원은 무한 루프에 빠질 수 있습니다. 특히 검토자가 계속 문제를 찾고 작성자가 개선 없이 계속 수정하는 경우에는 더욱 그렇습니다.
TerminationStrategy = new ApprovalTerminationStrategy()
{
MaximumIterations = 12 // Safety net
}
에이전트 호출을 try-catch 블록으로 래핑합니다. API 속도 제한, 네트워크 문제 및 모델 오류는 모두 프로덕션 시스템의 현실입니다.
try
{
await foreach (var message in chat.InvokeAsync(cancellationToken))
{
// Process messages
}
}
catch (HttpOperationException ex) when (ex.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
{
// Implement retry with exponential backoff
await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken);
}
관찰 가능성Agent Framework는 OpenTelemetry와 통합되어 모든 에이전트 상호 작용, 도구 호출 및 토큰 사용을 추적할 수 있습니다. 이는 어떤 에이전트가 문제를 일으켰는지 항상 명확하지 않은 다중 에이전트 워크플로를 디버깅하는 데 필수적입니다.
Semantic Kernel 원격 분석 패키지를 추가하고 기본 내보내기 도구(Application Insights, Jaeger 등)를 구성하여 기본 원격 분석을 설정합니다.
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing.AddSource("Microsoft.SemanticKernel*");
tracing.AddOtlpExporter();
});
비용 관리
다중 에이전트 시스템은 API 비용을 배가시킵니다. 모든 에이전트 차례는 API 호출이며 그룹 채팅은 많은 차례를 생성할 수 있습니다. 비용을 통제하기 위한 몇 가지 전략:
- 간단한 에이전트를 위해 더 저렴한 모델을 사용하세요: 모든 에이전트에 GPT-4o가 필요한 것은 아닙니다. 평론가는 더 작은 모델로 작업할 수 있지만 작성자에게는 강력한 모델이 필요합니다.
- 기록 제한: 실행 설정에서
ReducedHistoryCount를 사용하여 각 에이전트가 수신하는 대화 컨텍스트의 양을 제한합니다. - 엄격한 반복 제한 설정: 합리적인
MaximumIterations값으로 폭주 대화를 방지합니다. - 가능한 경우 캐시: 에이전트가 동일한 조회를 반복적으로 수행하는 경우 결과를 플러그인에 캐시합니다.
에이전트 디자인
- 지침에 집중: 각 상담원은 하나의 명확한 책임을 져야 합니다. 광범위한 지침은 모든 작업에서 평범한 성능으로 이어집니다.
- 출력 형식을 명시하세요: 상담원에게 응답 구성 방법을 정확하게 알려줍니다. 이는 다운스트림 구문 분석을 안정적으로 만듭니다.
- 종료 키워드 사용: 상담원이 완료되었음을 나타내기 위해 사용하는 명확한 신호(예: “승인됨” 또는 “완료”)를 정의합니다. 이는 종료 전략을 간단하고 예측 가능하게 만듭니다.
결론
다중 에이전트 AI 시스템은 지능형 애플리케이션 구축 방법의 근본적인 변화를 나타냅니다. 모든 것을 처리하기 위해 단일 프롬프트로 씨름하는 대신 문제를 전문적인 역할로 분해하고 상담원이 협업할 수 있도록 할 수 있습니다.
Microsoft의 Agent Framework를 사용하면 .NET 개발자에게 이러한 기능이 실용적으로 제공됩니다. 에이전트, 그룹 채팅, 선택 및 종료 전략 등 추상화는 깨끗하며 자연스럽게 구성됩니다. Semantic Kernel의 플러그인 에코시스템과 Azure의 모델 호스팅이 결합되어 프로덕션 수준의 다중 에이전트 시스템을 구축하기 위한 전체 스택을 갖게 됩니다.
프레임워크는 계속 발전하고 있지만(많은 패키지가 미리 보기 상태임) 핵심 패턴은 견고하고 방향은 명확합니다. .NET에서 AI 기반 애플리케이션을 구축하고 있다면 이제 다중 에이전트 아키텍처 실험을 시작할 때입니다.
소규모로 시작하세요. 간단한 작업을 위해 협업하는 두 개의 에이전트를 구축하세요. 단일 에이전트 접근 방식에 비해 품질 향상이 확인되면 모든 것을 에이전트 팀으로 분해하고 싶을 것입니다.
즐거운 코딩하세요!