
Plan 모드와 Todo 관리에 대응하는 Agent를 만들자 - Microsoft Agent Framework (C#)
요약
Microsoft Agent Framework v1.14.0에서 HarnessAgent가 정식 기능으로 출시되었습니다. 파일 시스템 액세스, Todo 관리, 플랜 모드 등 고성능 에이전트 구축에 필요한 핵심 기능들을 제공합니다.
핵심 포인트
- HarnessAgent의 정식 출시 및 주요 기능(파일 액세스, Todo 관리 등) 소개
- Context Window 관리 및 LoopEvaluators 등 실험적 기능 포함
- Azure.AI.Projects 및 Microsoft.Extensions.AI.OpenAI를 활용한 구현 방법
- HarnessAgentOptions를 통한 간편한 에이전트 설정 및 생성
서론
Microsoft Agent Framework v1.14.0에서 개인적으로 주목하고 있던 HarnessAgent가 Experimental 플래그가 해제되어 정식으로 제공되었습니다. 프리뷰 기능으로 구현된 직후에 이 기사에서도 다루었지만, 그 이후 API의 파괴적 변경(Breaking Changes) 등이 있었기 때문에, 출시된 버전으로 다시 시도해 보려고 합니다.
HarnessAgent
이 Agent Framework에 있는 HarnessAgent는 파일 시스템 액세스, Todo 관리, 플랜 모드(Plan mode), 채팅 이력 압축, 셸(Shell) 실행, 스킬(Skill) 대응, OpenTelemetry 대응 등 고성능 Agent를 만들고 싶을 때 필요한 기능들을 미리 갖춘 Agent입니다.
이 외에도 몇 가지 기능이 더 있지만, 해당 기능들은 아직 Experimental 상태입니다.
현재 Experimental 기능
Context Window관리 (최대 컨텍스트 윈도우, 출력 토큰, 이력의 컴팩트화)LoopEvaluators- AI Agent의 LLM 호출, 도구 실행 등의 사이에 평가를 수행하여 개선이 필요하다면, 다시 한번 피드백(feedback)을 첨부하여 AI를 호출하는 등의 작업이 가능함- 파일 메모리 스토어(File memory store) 커스터마이징
- 파일 액세스 스토어(File access store) 커스터마이징
- 백그라운드 에이전트 (아마도 이는 서브 에이전트 호출일 것입니다)
기본적인 기능은 GA(General Availability) 되었지만, 세부적인 커스터마이징 등을 수행하는 부분은 아직 Experimental 기능이므로, 그러한 기능을 사용하고 싶다면 파괴적 변경이나 버그를 각오하고 사용할 필요가 있다고 생각합니다.
사용해 보기
그럼 HarnessAgent를 사용해 봅시다.
HarnessAgent를 사용하기 위해서는 다음 패키지들이 필요합니다.
Microsoft.Agents.AI
Microsoft.Agents.AI.Harness
이 기사를 작성하는 시점에는 v1.15.0이 최신 버전이었으므로 그것을 사용하고 있습니다. 그리고 이번에는 LLM으로 Microsoft Foundry의 gpt-5.4를 사용합니다. OpenAI 패키지를 사용해도 되지만, Agent Framework 프로젝트에서도 Azure.AI.Projects 패키지를 사용하고 있으므로 그것을 추가하였고, OpenAI 클라이언트를 IChatClient로 만들기 위해 MEAI의 OpenAI 패키지도 추가합니다.
Azure.AI.Projects
Microsoft.Extensions.AI.OpenAI
Azure.AI.Projects는 2.0.1이 최신이었으므로 그것을 사용했습니다. MEAI.OpenAI는 10.8.1을 사용했습니다.
이러한 패키지들을 사용하여 모델을 호출하려면 다음 세 가지만 있으면 됩니다.
- Microsoft Foundry의 프로젝트 엔드포인트(Project endpoint)
- Microsoft Foundry에 배포된 모델명
- Foundry User 역할을 가진 계정 (개발 시에는 Azure CLI에 로그인된 계정, 운영 시에는 Managed ID)
꽤 간편하네요.
다음은 코드를 작성하여 HarnessAgent를 만들어 보겠습니다. HarnessAgent 생성 자체는 간단하며, IChatClient에 대해 AsHarnessAgent를 호출하기만 하면 됩니다. AsHarnessAgent의 인자로는 HarnessAgentOptions 클래스를 전달합니다. 여기서 이름이나 인스트럭션(Instruction) 및 각종 기능 설정을 수행합니다.
단순한 에이전트를 만들어 실행하는 것이라면 다음과 같은 코드가 됩니다.
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Extensions.AI;
...
AsHarnessAgent의 인자에서 DisableWebSearch를 true로 설정한 이유는, ChatCompletions API
에서는 Web Search 도구가 지원되지 않기 때문입니다. 이를 사용하려면 Responses API를 사용해야 합니다. 이를 실행하면 다음과 같은 결과가 나옵니다. 제대로 작동하고 있네요.
こんにちはにゃん!今日は何をお手伝いするにゃん?
이 HarnessAgent에는 몇 가지 편리한 기능이 기본적으로 활성화되어 있습니다. 그중에서 우선 사용하고 싶은 기능은 Plan 모드와 Todo 관리입니다. 이것은 AIContextProvider로 구현되어 있으며, 이를 사용하면 임의의 도구를 Agent에 제공하거나 Instructions를 추가하는 등의 처리를 추가할 수 있습니다. AIContextProvider는 재사용 가능한 AI Agent의 컨텍스트 (Context)를 제공하기 위한 부품입니다.
HarnessAgent는 Plan 모드를 제공하는 AgentModeProvider와 TodoProvider라는 두 가지 AIContextProvider를 사용하여 구현됩니다. 엄밀히 말하면 AgentModeProvider만 있어도 되지만, 플랜을 세울 때 대개 세트로 TodoProvider가 사용됩니다.
그럼, 날씨를 묻는 시나리오에서 Plan 모드를 사용해 봅시다. 날씨를 조사하기 위한 도구를 HarnessAgent에 추가합니다. 도구의 추가는 ChatOptions 파라미터의 Tools에서 지정합니다. 이 부분은 MEAI의 기능입니다.
var harnessAgent = chatClient.AsHarnessAgent(new()
{
Name = "CatAgent",
...
GetWeather 메서드는 다음과 같이 정의했습니다. 일단 전 세계가 맑아지는 평화로운 메서드입니다.
[Description("指定した場所の天気を返す")]
string GetWeather(
[Description("天気を取得する都市名")]
...
AgentModeProvider와 TodoProvider는 옵션으로 비활성화할 수도 있습니다. 이번에는 하지 않겠지만, 다음과 같이 DisableAgentModeProvider와 DisableTodoProvider 프로퍼티에 true를 설정함으로써 비활성화할 수 있습니다.
// HarnessAgent を作成する
var harnessAgent = chatClient.AsHarnessAgent(new()
{
...
AIContextProvider는 Agent의 GetService 메서드로 가져올 수 있습니다. 다음과 같은 느낌입니다.
// プロバイダーは Agent の GetService で取得出来る
var agentModeProvider = harnessAgent.GetService<AgentModeProvider>() ?? throw new InvalidOperationException();
var todoProvider = harnessAgent.GetService<TodoProvider>() ?? throw new InvalidOperationException();
그리고 AIContextProvider는 AgentSession에 상태를 유지하므로, AgentModeProvider나 TodoProvider를 사용하는 경우에는 AgentSession을 만듭시다. 뭐, 보통 Plan 모드를 사용할 때는 여러 턴의 대화가 이루어지므로 AgentSession은 어느 쪽이든 필수적이겠네요.
// AIContextProvider は AgentSession にステータスを保持するため AgentSession が必須
var session = await harnessAgent.CreateSessionAsync();
이것으로 준비가 끝났으므로, 플랜을 세우고 실행하는 흐름을 실행할 수 있습니다. 플랜을 세우는 듯한 지시를 요청한 후에 execute 모드로 변경하여 실행합시다. 다음과 같은 코드가 됩니다.
// 초기 상태인 plan 모드에서 실시 플랜을 작성함
Console.WriteLine($"현재 모드: {await agentModeProvider.GetModeAsync(session)}");
var response = await harnessAgent.RunAsync("도쿄와 히로시마와 교토의 날씨를 테이블 형식으로 정리해서 보여줘", session);
...
먼저, 날씨를 조사하는 플랜을 세우는 듯한 말을 걸어 TODO를 나열하고 있습니다. 그리고 다음에 execute 모드로 변경하여 실행을 요청한 뒤 TODO를 나열합니다. 실행하면 다음과 같은 결과가 나옵니다.
현재 모드: plan
다음 계획으로 진행할게냥.
1. 도쿄·히로시마·교토의 날씨를 가져올게냥.
...
TODO 리스트가 만들어진 후에 처리가 실행되고 있다는 것을 알 수 있습니다. 이런 것을 만들고 싶지만 은근히 귀찮기 때문에 미리 준비되어 있는 것은 참 고맙네요.
참고로 AgentMode는 기본적으로 plan과 execute 두 가지가 준비되어 있지만, 이는 커스터마이징이 가능합니다. 다음 기사 정도에서 쓸 수 있다면 써보도록 하겠습니다.
참고 삼아 이번 최종 버전 코드의 전체 모습은 다음과 같습니다.
사실 처음에는 luna로 진행했었는데, plan 모드임에도 실행해 버리는 등 약간 불안정했기 때문에 sol로 바꾸어 보았습니다.
사용 측에서 궁리한다면 아마 luna로도 가능하겠지만, 이번에는 모델로 해결해 버렸습니다.
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
...
요약
이렇게 해서 Microsoft Agent Framework에서 GA(General Availability)된 HarnessAgent를 사용해 보았습니다.
이전에 프리뷰(Preview) 단계에서 사용했을 때와는 API가 바뀌어 있기도 하지만, 대체로 할 수 있는 일은 같다고 생각합니다.
이번에는 가장 이해하기 쉬운 Plan 모드와 TODO 관리 기능을 사용했지만, 처음에 설명한 대로 그 외의 기능들도 가지고 있습니다.
하지만 일단 이번에는 여기까지 힘이 다했으므로, 다른 기능들은 향후 기사로 미루도록 하겠습니다!
Discussion

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