【제6회】Microsoft Agent Framework으로 배우는 AI 에이전트 설계 원칙: HandoffBuilder를 이용한 라우팅
요약
본 글은 AI 에이전트 설계 시 라우팅 문제를 다루며, 기존의 `if/elif` 문을 사용한 직접적인 라우팅 방식이 개방-폐쇄 원칙(OCP)을 위반함을 지적합니다. Microsoft Agent Framework의 HandoffBuilder를 활용하면, 각 Agent의 `description`을 기반으로 LLM이 스스로 다음 인계 대상을 판단하게 하여 OCP를 준수하는 '핸드오프형 멀티 에이전트'를 구성할 수 있습니다. 또한, HandoffBuilder와 GroupChatBuilder의 차이점을 비교하며 적절한 사용 사례를 제시합니다.
핵심 포인트
- AI 에이전트 라우팅 시 `if/elif` 문을 직접 사용하는 것은 개방-폐쇄 원칙(OCP) 위반이다.
- HandoffBuilder는 Agent가 자신의 `description`을 기반으로 다음 인계 대상을 LLM이 판단하게 하여 OCP를 준수한다.
- HandoffBuilder는 분산형 토폴로지를 가지며, 문의 대응이나 승인 플로우처럼 담당 결정이 명확한 태스크에 적합하다.
- GroupChatBuilder는 중앙 집권형 토폴로지이며, 조사나 리뷰 등 여러 Agent가 협력하는 태스크에 더 적합하다.
서론
지난 회차까지는 Agent를 분할하고, Middleware를 통해 횡단 관심사 (Cross-cutting Concerns)를 집약하는 방법을 배웠습니다.
분할된 Agent를 어떻게 "배분할 것인가"가 다음 설계 과제입니다.
제6회의 테마는 개방-폐쇄 원칙 (OCP: Open/Closed Principle) 입니다.
잘못된 코드: if문으로 라우팅을 직접 구현하는 경우
고객 지원 시스템을 예로 들어 생각해보겠습니다. 문의 내용에 따라 담당 Agent를 전환하고 싶다는 요구사항은 자주 등장합니다.
import asyncio
from agent_framework.openai import OpenAIChatClient
client = OpenAIChatClient()
...
"작동하는" 코드입니다. 하지만, 이것을 보고 무언가 느껴지는 점이 있나요?
무엇이 문제인가: 개방-폐쇄 원칙 위반
**개방-폐쇄 원칙 (OCP: Open/Closed Principle)**은 "모듈은 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 한다"는 원칙입니다. [1]
Agent Framework에서의 해결책: HandoffBuilder
Microsoft Agent Framework의 HandoffBuilder를 사용하면, Agent 스스로가 어느 Agent에게 인계할지를 판단하는 "핸드오프형 멀티 에이전트 (Handoff-type Multi-agent)"를 구성할 수 있습니다.
개선 후의 코드
import asyncio
from agent_framework.openai import OpenAIChatClient
from agent_framework.orchestrations import HandoffBuilder
...
무엇이 개선되었는가
| 관점 | ❌️ 개선 전 | ⭕️ 개선 후 |
|---|---|---|
| Agent 추가 | route 함수에 elif를 추가 | participants에 추가하기만 하면 됨 |
| 라우팅 판단 | 키워드 매칭 (문자열 의존) | Agent의 LLM 판단 (description 참조) |
| OCP 준수 | 확장을 할 때마다 기존 코드를 수정 | 기존 코드를 수정하지 않고 Agent를 추가할 수 있음 |
HandoffBuilder의 포인트
- 각 Agent의
description이 핸드오프의 판단 근거가 된다. LLM이description을 읽고 인계 대상을 판단한다. - 기본적으로 모든 Agent가 모든 Agent에게 핸드오프 가능하다 (메시 토폴로지 (Mesh Topology)).
add_handoff(source, targets)로 라우팅을 명시적으로 제한할 수 있다.with_start_agent(agent)로 워크플로의 입구가 되는 Agent를 지정한다.
라우팅의 명시적인 제한
기본 메시 토폴로지는 Agent 수가 늘어나면 예상치 못한 라우팅이 발생할 가능성이 있습니다. add_handoff를 통해 인계 대상을 제한할 수 있습니다.
workflow = (
HandoffBuilder(participants=[triage_agent, return_agent, billing_agent])
.with_start_agent(triage_agent)
...
GroupChatBuilder와의 차이점
HandoffBuilder와 유사한 메커니즘으로 GroupChatBuilder가 있습니다. 양자의 차이점을 정리합니다.
| 구분 | HandoffBuilder | GroupChatBuilder |
|---|---|---|
| 토폴로지 (Topology) | 분산형 | 중앙 집권형 |
| 인계의 명시성 | Agent가 도구 호출 (Tool Call)을 통해 명시적으로 지명 | 오케스트레이터 (Orchestrator)가 내부에서 판단 (각 Agent는 다음 단계를 모름) |
| 적합한 케이스 | 문의 대응·승인 플로 등 담당이 일의적으로 결정되는 태스크 | 조사·집필·리뷰 등 여러 Agent가 협조하는 태스크 |
요약
if/elif
라우팅은 OCP 위반이며, Agent 추가 시마다 기존 코드를 수정해야 합니다. 키워드 매칭을 통한 라우팅은 LLM의 출력 변동성(Output Fluctuation)으로 인해 깨지기 쉽습니다.
- Agent Framework의 HandoffBuilder를 사용하면, Agent 스스로가
description을 바탕으로 인계 대상을 판단하여 라우팅 로직을 제거할 수 있습니다.
다음 회차에서는 "상태를 전역 변수로 관리하는" 문제와 WorkflowContext에 대해 해설합니다.
- SOLID 원칙의 O에 해당합니다. "Software entities should be open for extension, but closed for modification." (소프트웨어 엔티티는 확장에는 열려 있어야 하지만, 수정에는 닫혀 있어야 한다.) ↩︎
AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기