본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 05. 14. 04:26

Microsoft Agent Framework의 Magentic을 시도해 보았다 (C# ver 1.5.0 확인)

요약

본 기사는 Microsoft Agent Framework v1.5.0에서 멀티 에이전트 오케스트레이션 패턴인 Magentic을 로컬 LLM(LM Studio)과 함께 시험적으로 사용한 경험을 다룹니다. Magentic은 전용 매니저가 공유 컨텍스트를 기반으로 다음에 움직일 에이전트를 선택하고, 필요에 따라 재계획하는 방식으로 복잡한 태스크 처리에 적합합니다. .NET 버전에서는 특정 예외(`System.InvalidOperationException`)로 인해 최종 답변 도출에는 실패했으나, Fact Sheet 생성, 역할 분담 계획 수립, Human Review 단계 등 Magentic의 핵심 작동 원리를 성공적으로 관찰할 수 있었습니다.

핵심 포인트

  • Magentic은 전용 매니저가 공유 컨텍스트를 기반으로 에이전트 간 상호작용을 오케스트레이션하는 멀티 에이전트 패턴이다.
  • Magentic은 복잡한 태스크에 적합하며, 미리 절차를 고정하기보다 필요에 따라 재계획(Re-planning)할 수 있다.
  • Microsoft Agent Framework는 `WithMaxRounds`, `RequirePlanSignoff` 등 오케스트레이션 설정을 직관적으로 구성할 수 있는 장점이 있다.
  • 실제 .NET 환경에서 Magentic을 구동하는 과정은 성공적이었으나, 특정 예외로 인해 최종 답변 도출 단계에서는 실패했다.
  • Manager가 Fact Sheet 작성 및 에이전트 역할 분담 계획을 먼저 수행하는 등 체계적인 프로세스를 보여주었다.

서론

Microsoft Agent Framework v1.5.0에서는 멀티 에이전트(Multi-agent)인 Magentic을 시험적으로 사용할 수 있게 되었습니다.

이번에는 로컬 LLM(Large Language Model)으로 LM Studio를 사용하여, Magentic이 어떻게 작동하는지 확인합니다.

특히 다음 사항들을 살펴봅니다.

  • Magentic이 어떤 오케스트레이션 (Orchestration)인지
  • Microsoft Agent Framework에서는 어떻게 선언하는지
  • 실행 결과와 LM Studio의 로그를 통해 무엇을 알 수 있는지

결론부터 말씀드리면 최종 답변까지는 도달하지 못했습니다.

하지만 fact sheet 생성과 역할 분담 계획, Human Review와 Magentic의 계획 생성 페이즈(Phase) 모습은 상당히 확인할 수 있었습니다.

5/11 Python 버전의 Microsoft Agent Framework로 시도했을 때는 정상적으로 동작했습니다.

차이점은 계획을 세운 후, 개별 에이전트의 채팅에 성공했는지 실패했는지 여부입니다.

.NET 버전에서는 다음 예외로 인해 실패했습니다: System.InvalidOperationException: Executor 'MagenticOrchestrator' cannot send messages of type 'Microsoft.Extensions.AI.ChatMessage'.

5/12 .NET 버전으로 구동할 수 있게 되어 조만간 기사로 작성하겠습니다.

5/13 .NET 버전에 수정 사항이 반영되어 다음 릴리스에서는 개선될 것으로 보입니다.

주의

Magentic이란

Magentic은 멀티 에이전트 오케스트레이션 (Multi-agent Orchestration) 중 하나입니다.

Semantic Kernel의 공식 블로그에서는 AutoGen의 MagenticOne 패턴을 베이스로 한 범용적인 멀티 에이전트 패턴으로 설명되어 있습니다.

특징은 전용 매니저(Manager)가 공유 컨텍스트(Shared Context)와 진행 상황을 보면서 다음에 움직일 에이전트를 매번 선택한다는 점입니다.

미리 절차를 고정하는 것이 아니라, 필요에 따라 재계획(Re-planning)하며 진행할 수 있습니다.

따라서 처음부터 정답인 절차가 정해져 있지 않은 복잡한 태스크 (Task)에 적합합니다.

이번 샘플에서도 Manager가 처음에 태스크를 정리하고, TimeAgent와 WeatherAgent, LocalGuideAgent에 역할을 할당하는 구성으로 만들었습니다.

참고

선언을 살펴보기

Microsoft Agent Framework에서의 선언 예시

MagenticWorkflowBuilder builder = new MagenticWorkflowBuilder(managerAgent)
.WithName("TokyoTripAdvisor")
.WithDescription("Magentic Orchestration으로 일시·날씨·거리 산책 정보를 모아서 제안하는 샘플입니다.")
...

Semantic Kernel에서의 선언 예시

// OpenAI의 ChatCompletionService를 사용하여 MagenticManager를 생성
var promptSettings = new OpenAIPromptExecutionSettings();
MyManager manager =
...

Microsoft Agent Framework 측은 Builder에 설정을 쌓아 올리는 형태이므로, Magentic 고유의 설정을 읽기 쉽습니다.

이번 선언에서 확인해 두고 싶은 점은 다음 4가지입니다.

  • WithMaxRounds(8)로 매니저와 참여 에이전트 간의 상호작용을 최대 8라운드까지 허용
  • WithMaxStalls(2)로 진행이 멈췄을 때의 허용 횟수를 2회로 설정
  • RequirePlanSignoff(true)로 실행 전 인간 리뷰 (Human Review)를 필수화
  • AddParticipants(...)로 Manager 이외의 에이전트를 등록

워크플로 (Workflow) 실행 등을 포함하여 Semantic Kernel보다 Microsoft Agent Framework 쪽이 오케스트레이션 설정이 더 정리되어 있다는 인상을 받았습니다.

실행해 보기

이번에는 다음 4개의 에이전트로 시도합니다.

  • Manager: 전체 계획과 담당 할당을 수행
  • TimeAgent: GetDateTime

를 사용하여 현재 일시를 반환 - WeatherAgent:
GetWeatherForecast

를 사용하여 날씨를 반환 - LocalGuideAgent:
GetCityHighlights

를 사용하여 방문지 후보를 반환

날씨나 관광 정보는 외부 API가 아닌 로컬 함수로 반환하고 있습니다.

실행 결과

=== Initial Plan Created ===
We are working to address the following user request:
今日の午後に東京駅周辺へ行きます。現在日時、東京の天気、立ち寄り先候補を確認したうえで、持ち物・過ごし方・注意点をまとめて提案してください。
...

이번에는 최종 답변이 출력되지 않고 종료되었습니다.

실행 결과에서 알 수 있는 점

  • 처음에 Manager가 fact sheet를 작성합니다. 갑자기 각 에이전트를 동작시키는 것이 아니라, 먼저 태스크를 정리하여 공유를 위한 전제를 만드는 움직임을 보입니다.
  • 다음으로 Manager가 TimeAgent와 WeatherAgent와 LocalGuideAgent의 담당을 명문화합니다. 이는 Magentic이 태스크 분해(Task Decomposition)와 역할 분담을 먼저 수행한다는 것을 잘 보여줍니다.
  • RequirePlanSignoff(true)를 설정했기 때문에, 중간에 Human Review (인간 검토)가 끼어 있습니다.

코드에서도 MagenticPlanReviewRequest를 받아 승인하고 있으며, 인간의 승인을 실제로 오케스트레이션 (Orchestration)에 포함할 수 있음을 알 수 있습니다.

  • 반면, TimeAgent나 WeatherAgent나 LocalGuideAgent의 응답 스트림 (Response Stream)은 나오지 않았습니다.

이번에는 계획 생성까지는 진행되었으나, 참여 에이전트의 실행 단계까지는 안정적으로 진행되지 못했습니다.

출력 결과와 LM Studio 로그를 결합한 고찰

출력 결과와 LM Studio의 로그를 대조해 보면, 이번 실행은 크게 4단계로 나뉘었다고 생각됩니다.

먼저, 이번에 관측된 흐름을 도식화하면 다음과 같습니다.

LM Studio의 로그를 보면 계획 생성까지는 진행되었음을 알 수 있습니다.

반면, 그 이후의 제어 응답 (Control Response)에서는 형식이 무너진 모습이 보입니다.

2026-05-09 15:44:00 [INFO]
[openai/gpt-oss-20b] Generated prediction:
"content": "**1. GIVEN OR VERIFIED FACTS** ... **4. EDUCATED GUESSES** ..."
...
  • 첫 번째 요청에서는 Manager가 사전 조사용 프롬프트를 받았습니다. 그리고 GIVEN OR VERIFIED FACTS부터 EDUCATED GUESSES까지의 fact sheet를 생성합니다. 콘솔에 표시된 === Initial Plan Created ===의 내용은 LM Studio의 첫 번째 응답 본문과 대응합니다.
  • 다음 요청에서는 Manager가 참여 에이전트의 역할 분담을 만듭니다.

계획은 콘솔의 === Human Review: Proposed Plan ===과 일치합니다.

LM Studio의 두 번째 응답과도 정합합니다.

  • 그 후에는 RequirePlanSignoff(true) 설정대로 인간 승인 단계로 진입하여, 코드 측에서 reviewRequest.Approve()를 반환합니다. 여기까지는 Magentic의 '계획 작성'과 '인간 리뷰'가 올바르게 작동하고 있습니다.

문제는 승인 후의 요청과 응답입니다.

LM Studio의 로그를 보면, Manager에게는 다음 담당자나 진행 상태를 JSON으로 반환하도록 요구되었습니다.

하지만 실제로는 설명문이 포함된 응답이나 스키마 (Schema)에 맞지 않는 JSON, 필수 항목이 누락된 JSON이 반환되었습니다.

이것이 원인이 되어 처리에 실패한 것으로 생각됩니다.

이번 검증에서는 사용자 역할 지정에 따른 Magentic의 제어용 응답이 로컬 LLM (Large Language Model)에게는 다소 어려웠던 것으로 보입니다.

다만, 다음 추가 조사에서는 미들웨어에서 Structured Output (구조화된 출력) 설정을 넣음으로써, 이 제어용 JSON 자체는 안정화되었습니다.

따라서 중단 요인은 단순한 모델 성능뿐만 아니라, 출력 형식 (Output Format)의 고정 방법과 workflow 측의 구현 의존성을 함께 살펴볼 필요가 있어 보입니다.

이후 추가 조사 메모

추가 조사 결과, 모델의 JSON 응답이 불안정했을 뿐만 아니라, Microsoft.Agents.AI.Workflows 1.5.0의 Magentic 구현 측에도 주의가 필요한 점이 있는 것으로 보였습니다.

특히 신경 쓰였던 점은 다음 3가지입니다.

  • orchestrator의 선언과 실제로 송수신하고 있는 타입 간의 정합성이 부족할 가능성이 있습니다. 내부에서는 ChatMessageList<ChatMessage>를 다루고 있지만, 해당 타입을 workflow 측에서 충분히 받아들이지 못하고 있는 것처럼 보입니다. 만약 이 추측이 맞다면, 최종 답변이 workflow output으로 확정되지 않아 Final Result가 비게 되는 현상을 설명하기 쉬워집니다.
  • progress ledger 주변은 JSON을 전제로 동작하고 있을 가능성이 높습니다. 이번 로그에서는 Manager가 자연어를 섞거나 JSON 형식을 깨뜨리고 있어, 파싱 (Parsing)에 실패하면 참여 에이전트(Agent)로 넘어가기 전의 제어 단계에서 멈추기 쉽습니다. 이 점은 미들웨어에서 Structured Output (구조화된 출력)을 설정함으로써 개선했습니다. 따라서 이 부분은 프롬프트 (Prompt)만의 문제가 아니라, 출력 형식을 고정하는 메커니즘의 유무에 의존하고 있다고 생각됩니다.
  • Builder를 통해 내부 orchestrator가 구성되기 때문에, 이용자 측 코드만으로는 국소적인 수정이 어려운 구조입니다. 설령 선언 주변이 원인이라 하더라도, 샘플 측의 prompt를 조금 수정하는 것만으로는 해결하기 어려울 가능성이 있습니다.

이번 현상은 당초 구성에서 Structured Output 없이 제어용 JSON을 반환하게 함으로써 발생한 불안정성과, framework 측의 구현 의존성이 겹쳐서 일어나고 있다고 보는 것이 자연스러워 보였습니다.

적어도 미들웨어에서 Structured Output을 설정함으로써 제어용 JSON은 원활하게 반환되게 되었습니다.

따라서 남은 문제는 JSON 생성 그 자체보다는, workflow 측이 그 결과를 어떻게 다루느냐 하는 부분으로 기울어 있는 것 같습니다.

이 부분은 GitHub Copilot의 조사 결과도 포함하여, 시간을 내어 조금 더 자세히 추적해 보려고 합니다.

요약

Magentic은 Manager가 계획을 세우고 필요에 따라 인간의 검토 (Human Review)를 거치며 다음 담당 에이전트를 선택하여 진행하는 오케스트레이션 (Orchestration)임을 알 수 있었습니다.

Microsoft Agent Framework에서는 Builder를 통해 설정을 모아서 선언할 수 있으므로, 사용법 자체는 상당히 파악하기 쉽게 되어 있습니다.

이번 검증에서는 최종 답변이 표시되지 않았지만, fact sheet 생성, 역할 분담 계획, Human Review와 같은 중요한 단계는 확인할 수 있었습니다.

시험적인 릴리스 (Release)인 만큼 제대로 동작하지 않은 점은 아쉽지만, 얻은 지식은 유익했습니다.

소스

Program.cs

using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Agents.AI.Workflows.Specialized.Magentic;
...

LM Studio 로그

요청/응답

2026-05-09 15:43:52 [DEBUG]
요청 수신: /v1/chat/completions로 POST 요청, 바디 내용 {
"messages": [
...
```json\n{\n "is_request_satisfied": true,\n "reason": "사용자의 요청은 무엇을 가져갈지, 시간을 어떻게 보낼지, 그리고 주의 사항을 제안하기 전에 현재 날짜/시간, 도쿄의 일기 예보, 그리고 도쿄역 주변의 방문 가능한 장소들에 대한 확인을 명확히 요구하고 있습니다.",\n "is_in_loop": false,\n "is_progress_being_made": false,\n "next_speaker": "LocalGuideAgent",\n "instruction_or_question": "現在の天気予報と東京駅周辺でおすすめできる立ち寄り先を教えてください。"\n}\n",
"reasoning": "사용자는 요청이 충족되었는지 알고 싶어 합니다. 우리는 is_request_satisfied, is_in_loop, is_progress_being_made, next_speaker, instruction_or_question 키를 가진 JSON 형식으로 답변해야 합니다. 불리언 (Boolean) 값과 이유 (reason) 문자열을 제공하십시오.\n\n증거를 찾기 위해 원래 요청을 검토해야 합니다. 요청에는 다음이 포함되어 있습니다: \"今日の午後に東京駅周辺へ行きます。現在日時、東京の天気、立ち寄り先候補を確認したうえで、持ち物・過ごし方・注意点をまとめて提案してください.\" 따라서 필요한 사실은 다음과 같습니다: 현재 날짜/시간, 도쿄의 일기 예보, 도쿄역 주변의 방문 가능한 장소.\n\n이제 JSON을 생성합니다.",
"tool_calls": []
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 2758,
"completion_tokens": 531,
"total_tokens": 3289,
"completion_tokens_details": {
"reasoning_tokens": 139
}
},
"stats": {},
"system_fingerprint": "openai/gpt-oss-20b"
}
2026-05-09 15:44:06 [DEBUG]
LlamaV4: 서버가 작업 14658에 슬롯 3을 할당했습니다.
2026-05-09 15:44:06 [DEBUG]
요청 수신: /v1/chat/completions로 POST 요청, 바디 내용 {
"messages": [
{
"role": "system",
"content": "당신은 여러 전문 에이전트 (Agent)를 총괄하는 매니저입니다. 사용자의 목적을 달성하기 위해 필요한 전문가에게 의뢰하고, 결과를 통합하여 일본어로 최종 답변을 정리하십시오."
},
{
"role": "user",
"content": "Below I will present you a request.\n\nBefore we beg... <로그에서 생략됨> ...NOT list next steps or plans until asked to do so."
},
{
"role": "assistant",
"content": "**1. GIVEN OR VERIFIED FACTS** \n- The user will v... <로그에서 생략됨> ...xpect higher foot traffic in those windows."

---
{
"name": "Manager"
},
{
"role": "user",
"content": "환상적입니다. 이 요청을 처리하기 위해 우리는 조립... <로그에서 생략됨> ...이 작업에는 특정 전문 지식이 필요하지 않을 수도 있습니다."
},
{
"role": "assistant",
"content": "- **TimeAgent**: 취득 항목 
 - 오늘의 정확한 일시 (타임존은 일본 표준... <로그에서 생략됨> ...를 통합하여 '오늘 오후에 도쿄역 주변으로 가기' 위한 준비물, 활동 방법, 주의사항을 정리한 제안을 작성합니다.",
"name": "Manager"
},
{
"role": "user",
"content": "우리는 다음 사용자 요청을 처리하기 위해 노력하고 있습니다... <로그에서 생략됨> ...를 통합하여 '오늘 오후에 도쿄역 주변으로 가기' 위한 준비물, 활동 방법, 주의사항을 정리한 제안을 작성합니다."
},
{
"role": "user",
"content": "우리가 다음 요청을 작업 중임을 상기하십시오:

지금... <로그에서 생략됨> ...
 "answer": string,
 "reason": string
}
}
"
},
],
"model": "openai/gpt-oss-20b",
"max_completion_tokens": 5000
}
2026-05-09 15:44:09 [INFO]
[openai/gpt-oss-20b] Generated prediction: {
"id": "chatcmpl-m2oyhpiwcm3s07mqe9zh3",
"object": "chat.completion",
"created": 1778309046,
"model": "openai/gpt-oss-20b",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{
 "is_request_satisfied": {
 "answer": false,
 "reason": ""
 },
 "is_in_loop": {
 "answer": false,
 "reason": ""
 },
 "is_progress_being_made": {
 "answer": false,
 "reason": ""
 },
 "next_speaker": {
 "answer": "LocalGuideAgent",
 "reason": "사용자가 도쿄역 주변의 방문지에 대한 현지 제안을 구체적으로 필요로 하므로, 인근 명소 및 물류에 대한 이 에이전트(Agent)의 전문 지식이 가장 관련이 높습니다."
 }
}",
"reasoning": "JSON 스키마(schema)로 응답해야 합니다. 설문에는 네 가지 섹션이 있습니다: 주어진 사실 또는 확인된 사실(GIVEN OR VERIFIED FACTS), 찾아봐야 할 사실(FACTS TO LOOK UP), 도출해야 할 사실(FACTS TO DERIVE), 추측(EDUCATED GUESSES).

요청을 기반으로 내용을 채워보겠습니다:

1. 주어진 사실 또는 확인된 사실(GIVEN or Verified facts): 사용자 메시지로부터: "오늘 오후에 도쿄역 주변으로 갑니다. 현재 일시, 도쿄의 날씨, 방문 후보지를 확인한 후, 준비물, 활동 방법, 주의사항을 정리하여 제안해 주세요."

따라서 주어진 사실은 다음과 같습니다: 그들은 오후에 도쿄역 주변을 방문할 것입니다; 현재 일시, 날씨, 후보 방문지가 필요합니다.

2."

조회할 사실: 현재 날짜/시간 (시스템으로부터). 도쿄의 일기 예보 (출처: 일본 기상청 (JMA)). 도쿄역 주변의 후보지 ("도쿄도청"과 같은 공식 관광 사이트 또는 여행 가이드에서 가져올 수 있음). 요청 사항에 "공식 관광 사이트"를 언급할까요? 명시되어 있지는 않지만 JMA, Hyperdia를 사용할 수 있습니다.

3. 도출할 사실: 기온 및 강수 확률에 따른 복장; 대략적인 도보 시간; 일반적인 평일 오후 교통량을 고려한 특정 지점의 예상 인파 수준.

4. 추론된 추측: 만약 10월 중순이라면, 도쿄의 평균 낮 기온은 18-23°C, 낮거나 보통 수준의 강수량, 보통 수준의 습도(~70%)입니다. 또한 통근 교통량이 16-17시경에 정점에 도달하므로, 늦은 오후에는 유동 인구가 더 많을 것으로 예상됩니다.

이에 따라 JSON을 출력하겠습니다.",
"tool_calls": []
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 2758,
"completion_tokens": 428,
"total_tokens": 3186,
"completion_tokens_details": {
"reasoning_tokens": 301
}
},
"stats": {},
"system_fingerprint": "openai/gpt-oss-20b"
}
2026-05-09 15:44:09 [DEBUG]
Received request: POST to /v1/chat/completions with body {
"messages": [
{
"role": "system",
"content": "당신은 여러 전문 에이전트 (Agent)를 총괄하는 매니저입니다. 사용자의 목적을 달성하기 위해 필요한 전문가에게 의뢰하고, 결과를 통합하여 일본어로 최종 답변을 정리해 주세요."
},
{
"role": "user",
"content": "아래에 요청 사항을 제시하겠습니다.\n\n시작하기 전에... <로그에서 생략됨> ...요청받기 전까지 다음 단계나 계획을 나열하지 마십시오."
},
{
"role": "assistant",
"content": "**1. 주어진 또는 확인된 사실** \n- 사용자는 v... <로그에서 생략됨> ...해당 시간대에 더 높은 유동 인구를 예상합니다. \n\n---",
"name": "Manager"
},
{
"role": "user",
"content": "훌륭합니다. 이 요청을 처리하기 위해 우리는 모았습니다... <로그에서 생략됨> ...특정 전문 지식은 이 작업에 필요하지 않을 수도 있습니다."
},
{
"role": "assistant",
"content": "- **TimeAgent**: 취득 항목 \n - 오늘의 정확한 일시 (타임존은 일본 표준..."}

...를 통합하여 「오늘 오후에 도쿄역 주변으로 간다」를 위한 준비물, 보내는 방법, 주의사항을 정리한 제안을 작성합니다.",
"name": "Manager"
},
{
"role": "user",
"content": "We are working to address the following user reque... <Truncated in logs> ...를 통합하여 「오늘 오후에 도쿄역 주변으로 간다」를 위한 준비물, 보내는 방법, 주의사항을 정리한 제안을 작성합니다."
},
{
"role": "user",
"content": "Recall we are working on the following request:

今... <Truncated in logs> ...
 "answer": string,
 "reason": string
}
}
"
},
],
"model": "openai/gpt-oss-20b",
"max_completion_tokens": 5000
}
2026-05-09 15:44:11 [INFO]
[openai/gpt-oss-20b] Generated prediction: {
"id": "chatcmpl-0gze4n715and3v2phqcf487",
"object": "chat.completion",
"created": 1778309049,
"model": "openai/gpt-oss-20b",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{\"next_speaker\":\"TimeAgent\",\"instruction_or_question\":\"오늘 오후에 도쿄역 주변으로 갈 예정이시므로, 우선 현재 일시를 확인한 후 날씨 정보와 방문 후보지를 체크하겠습니다. 준비물, 보내는 방법, 주의사항에 대해 통합된 제안을 정리하겠습니다.\"}",
"reasoning": "We need to produce JSON with keys: is_request_satisfied, is_in_loop, is_progress_being_made, next_speaker, instruction_or_question. The user asked: \"Below I will present you a request...\". They want a short bullet-point plan for addressing the

AI 자동 생성 콘텐츠

본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0