본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 30. 22:55

Agent Harness 설명: Microsoft Agent Framework를 사용하여 프로덕션급 AI 에이전트 구축하기

요약

Microsoft Agent Framework의 Agent Harness 패턴을 활용하여 프로덕션급 AI 에이전트를 구축하는 방법을 다룹니다. 도구 호출, 메모리 관리, 컨텍스트 압축 등 에이전트 운영의 복잡성을 해결하는 아키텍처와 구현 기술을 상세히 설명합니다.

핵심 포인트

  • Agent Harness를 통한 에이전트 인프라 복잡성 해결
  • Microsoft Agent Framework의 핵심 구성 요소 분석
  • 컨텍스트 압축 및 이력 지속성 관리 방법
  • OpenTelemetry를 활용한 에이전트 관찰 가능성 확보
  • 실제 Python 코드를 통한 단계별 구현 워크스루

Meta Description: Agent Harness가 무엇인지, 왜 프로덕션 AI 시스템에서 중요한지, 그리고 Microsoft Agent Framework의 create_harness_agent를 사용하여 실제 Python 코드, 아키텍처 다이어그램, 심층적인 기술 워크스루와 함께 단계별로 구현하는 방법을 배워보세요.

목차

  1. 서론 -- 숨겨진 복잡성 비용 (The Hidden Complexity Tax)
  2. Agent Harness란 무엇인가?
    • 수동 배선 문제 (The Manual Wiring Problem)
    • Harness vs. DIY 에이전트
  3. Microsoft Agent Framework 심층 분석
    • 아키텍처 개요 (Architecture Overview)
    • 패키지 생태계 (The Package Ecosystem)
  4. create_harness_agent의 해부
    • 함수 호출 레이어 (Function Invocation Layer)
    • 이력 지속성 (History Persistence)
    • 압축 (Compaction)
    • TodoProvider
    • AgentModeProvider -- 계획/실행 워크플로우 (Plan/Execute Workflow)
    • MemoryContextProvider
    • SkillsProvider
    • OpenTelemetry 통합
  5. 전체 구현 워크스루
    • 사전 요구 사항 및 설치
    • 최소 기능 Harness 에이전트
    • 전체 리서치 에이전트 -- 라인별 분석
    • 스트리밍 및 도구 관찰 (Streaming & Tool Observation)
    • 기능 커스터마이징 및 비활성화
  6. 에이전트 실행 및 테스트
  7. 프로덕션 고려 사항
  8. 결론

1. 서론 -- 숨겨진 복잡성 비용 (The Hidden Complexity Tax)

당신은 유능한 LLM을 가지고 있습니다. 명확한 유스케이스(Use case)도 있습니다. Python으로 20줄 정도의 채팅 루프를 작성하면 잘 작동합니다. 하지만 컨텍스트 윈도우(Context window)가 가득 차서 에이전트가 맥락을 놓치기 전까지는 말이죠. 혹은 도구를 호출했지만 두 턴 뒤에 그 결과를 잊어버리기도 합니다. 아니면 세 가지 일을 동시에 시작해놓고 어떤 것이 완료되었는지 추적할 방법이 없기도 합니다. 또는 프로덕션 환경에서 무엇이 잘못되었는지 흔적도 없이 충돌(Crash)하기도 합니다.

이것이 바로 **AI 에이전트의 숨겨진 복잡성 비용 (hidden complexity tax of AI agents)**입니다. 모든 프로덕션급 에이전트에는 다음과 같은 요소가 필요합니다: 도구 호출 루프(Tool-calling loop), 대화 이력 관리(Conversation history management), 컨텍스트 윈도우 압축(Context-window compaction), 계획 메커니즘(Planning mechanism), 내구성 있는 메모리(Durable memory), 기술 확장성(Skill extensibility), 그리고 관찰 가능성(Observability). 만약 이 각각의 요소를 직접 배선(Wire)한다면, 실제 지능을 구현하는 것보다 인프라 구축에 더 많은 시간을 소비하게 됩니다. 그리고 그중 하나라도 고장 나면, 전체 에이전트가 디버깅이 거의 불가능한 방식으로 실패하게 됩니다.

이러한 문제를 해결하는 것이 바로 agent harness 패턴입니다. 이 패턴은 모든 구성 요소를 단일하고 테스트 가능하며 설정 가능한 파이프라인으로 미리 조립하여 제공합니다. 따라서 사용자는 에이전트가 무엇을 하는지에만 집중할 수 있고, 그것을 어떻게 계속 실행하게 할지에 대한 걱정은 덜 수 있습니다.

본 심층 분석에서는 다음 내용을 학습하게 됩니다:

  • agent harness가 정확히 무엇인지, 그리고 어떤 문제를 해결하기 위해 설계되었는지
  • **Microsoft Agent Framework (MAF)**가 create_harness_agent를 사용하여 harness 패턴을 어떻게 구현하는지
  • harness가 조립하는 모든 하위 시스템의 구성 요소별 분석
  • 공식 MAF 저장소에서 가져온 실제 Python 코드를 사용한 완전하고 프로덕션 준비가 된 Research Agent 구현

지속 가능한 무언가를 만들어 봅시다.

2. Agent Harness란 무엇인가?

'Harness'라는 용어는 두 가지 확립된 소프트웨어 패턴에서 유래했습니다. 테스트 엔지니어링(test engineering) 분야에서 테스트 harness는 테스트 대상 시스템을 구성하고, 계측하며, 해체하는 스캐폴딩 역할을 합니다. 따라서 테스트 작성자는 테스트 로직만 작성하면 되고, 설정 코드는 작성할 필요가 없습니다. 의존성 주입(dependency injection) 분야에서는 DI 컨테이너가 와이어링 harness입니다. 이는 컴포넌트를 해결하고 연결하여 애플리케이션 코드가 new를 직접 호출하는 것을 방지합니다.

Agent harness는 AI 에이전트에도 동일한 사고방식을 적용합니다. 즉, 다음과 같습니다:

필요한 모든 인프라 컴포넌트(히스토리, 도구, 메모리, 관찰 가능성(observability), 계획 등)를 단일하고 선언적인 설정 지점에서 조립하여 완전히 연결되고 실행 준비가 된 에이전트를 구성하는 팩토리 또는 컨테이너.

핵심 통찰은 **관심사 분리(separation of concerns)**입니다. 에이전트의 명령어는 에이전트가 무엇을 해야 하는지를 정의하고, harness는 그 의도가 어떻게 안정적으로 실행되고, 영속화되며, 관찰되는지를 정의합니다.

아키텍처 참고: harness를 프로덕션급 Kubernetes 배포와 docker run으로 컨테이너를 수동 실행하는 것과 비교해 보세요. 둘 다 코드를 실행하지만, 전자는 재시작, 리소스 제한, 네트워킹, 로깅 및 스케일링을 자동으로 처리합니다.

2.1 수동 와이어링 문제

하네스 (Harness)가 무엇을 제거하는지 이해하려면, 실제 에이전트를 위해 수동으로 구축해야 하는 작업들을 고려해 보십시오:

구성 요소수동 작업 책임
도구 호출 루프 (Tool Calling Loop)도구 호출 감지, 디스패치 (dispatch), 결과 수집, 모델 재호출, 종료 조건 설정
...

이 모든 것을 올바르게 작성하고, 테스트하며, LLM 제공업체가 API를 업데이트할 때마다 작동하도록 유지하는 것은 상당한 엔지니어링 노력이 필요합니다. 하네스 패턴은 이러한 노력을 한 번만 패키징하므로, 귀하와 팀의 모든 개발자가 이를 반복할 필요가 없습니다.

2.2 하네스 (Harness) vs. DIY 에이전트

그 차이는 코드에서 즉시 확인할 수 있습니다. 다음은 도구 호출 루프만을 처리하는 최소한의 하지만 현실적인 "수동" 에이전트 예시입니다:

# ? DIY 방식 -- 이것은 단지 도구 루프일 뿐이며, 메모리, 압축(compaction) 또는 텔레메트리(telemetry)는 포함되지 않았습니다.
import json

...

이제 위에서 언급한 모든 기능에 더해 히스토리, 압축 (compaction), 계획 (planning), 메모리 및 텔레메트리 (telemetry)까지 수행하는 하네스 방식의 대응 코드를 보겠습니다:

# ? 하네스 방식 -- 4줄로 완성된 전체 프로덕션 파이프라인
from agent_framework import create_harness_agent
from agent_framework.foundry import FoundryChatClient
...

결과는 동일합니다. 하지만 버그가 발생할 수 있는 표면적 (surface area)은 수십 배 더 적습니다.

3. Microsoft Agent Framework 심층 분석

**Microsoft Agent Framework (MAF)**는 AI 에이전트 및 멀티 에이전트 워크플로 (multi-agent workflows)를 구축하기 위한 Microsoft의 오픈 소스 프로덕션급 프레임워크입니다. 이는 AutoGen과 Semantic Kernel의 직접적인 후속작으로, AutoGen의 단순하고 조합 가능한 에이전트 추상화와 Semantic Kernel의 엔터프라이즈 기능(세션 기반 상태 관리, 타입 안정성 (type safety), 미들웨어 파이프라인, 포괄적인 텔레메트리)을 결합한 것입니다.

MAF는 다음을 지원합니다:

  • 다중 언어 (Multi-language) -- Python과 C#/.NET 간의 완전한 동등성(parity) 제공
  • 다중 제공자 (Multi-provider) -- Azure AI Foundry, OpenAI, Azure OpenAI, Anthropic (Claude), Google Gemini, Amazon Bedrock, Mistral, Ollama, GitHub Copilot SDK 등 지원
  • 다중 패턴 (Multi-pattern) -- 단일 에이전트 (Single agents), 순차적 워크플로우 (sequential workflows), 병렬 워크플로우 (concurrent workflows), 핸드오프 패턴 (handoff patterns), 그룹 채팅 패턴 (group-chat patterns), 인간 참여형 (human-in-the-loop)
  • 다중 배포 (Multi-deployment) -- 로컬 개발 (Local dev), Azure Functions, Foundry Hosted Agents (컨테이너화된 Micro VMs), Durable Task

3.1 아키텍처 개요 (Architecture Overview)

MAF의 중심에는 Agent 기본 클래스 (base class)가 있습니다. 모든 에이전트 유형은 이 공통 기본 클래스를 상속하며, 이는 멀티 에이전트 오케스트레이션 (multi-agent orchestration)을 위한 일관된 인터페이스를 정의합니다.

**기본 에이전트 런타임 실행 모델 (default agent runtime execution model)**은 결정론적 루프 (deterministic loop)를 따릅니다:

User Message
    ?
    ?
...

이 루프는 모든 agent.run() 호출 시 투명하게 실행됩니다. Harness는 6개 단계가 모두 채워지고 올바른 순서로 배치되도록 보장합니다.

3.2 패키지 생태계 (The Package Ecosystem)

MAF의 Python 구현은 조합 가능한 패키지들로 나뉩니다. 최상위 agent-framework 메타 패키지를 통해 모든 패키지를 설치할 수 있습니다:

pip install agent-framework
패키지목적
coreAgent 기본 클래스, 세션 관리, 미들웨어, 컨텍스트 제공자
...

4. create_harness_agent의 구조 (Anatomy of create_harness_agent)

create_harness_agent는 팩토리 함수 (factory function)입니다. 즉, 단 한 번의 호출로 완전히 작동하는 에이전트를 구축하고 연결합니다. 전체 시그니처 (signature)를 살펴본 후, 이 함수가 조립하는 모든 구성 요소를 세부적으로 분석해 보겠습니다:

from agent_framework import create_harness_agent

agent = create_harness_agent(
...

이 단일 호출은 **8개의 하위 시스템 (sub-systems)**을 자동으로 조립합니다. 각 시스템에 대한 상세 내용은 다음과 같습니다.

4.1 함수 호출 계층 (Function Invocation Layer)

이것은 에이전트의 **에이전틱 루프 엔진 (agentic loop engine)**입니다. 에이전트가 단순히 응답하는 것을 넘어 실제로 무언가를 수행하게 만드는 구성 요소입니다.

모델이 도구 호출 (tool calls)을 포함한 응답을 반환하면, FunctionInvocationLayer 미들웨어는:

  1. 모델의 응답에서 도구 호출 (tool call) 요청을 감지 (Detects) 합니다.
  2. 각 호출을 등록된 도구 함수로 전달 (Dispatches) 합니다.
  3. 결과를 수집 (Collects) 하여 메시지 기록 (message history)으로 다시 직렬화 (serialize) 합니다.
  4. 업데이트된 기록과 함께 모델을 재호출 (Re-invokes) 합니다.
  5. 모델이 최종 텍스트 응답을 반환할 때까지 이 과정을 반복 (Repeats) 합니다.
  6. 무한 루프를 방지하기 위해 최대 반복 제한을 강제 (Enforces) 합니다.

도구 함수는 타입 어노테이션 (type-annotated) 시그니처를 가진 일반 Python 호출 가능 객체 (callables)로 등록됩니다. 프레임워크는 이 어노테이션으로부터 JSON 스키마 (JSON schema)를 자동으로 생성합니다:

async def search_database(query: str, limit: int = 10) -> list[dict]:
    """일치하는 항목을 찾기 위해 제품 데이터베이스를 검색합니다.

...

4.2 기록 지속성 (History Persistence)

InMemoryHistoryProvider는 에이전트 세션의 대화 기록 (conversation history) 을 관리합니다. 이것이 일반적인 메시지 리스트와 다른 점은 지속성 (persistence) 이 발생하는 시점 입니다. 즉, 에이전트의 턴이 끝날 때뿐만 아니라, 개별 모델 서비스 호출이 발생할 때마다 지속성이 이루어집니다.

이는 신뢰성 측면에서 매우 중요합니다. 한 번의 턴에서 에이전트가 세 번의 도구 호출을 수행한다고 가정해 봅시다. 호출당 지속성이 없다면, 세 번째 호출에서 충돌 (crash)이 발생했을 때 첫 번째와 두 번째 호출의 작업 내용이 모두 손실됩니다. 호출당 지속성을 사용하면 에이전트는 마지막으로 성공한 상태에서 재개할 수 있습니다.

# 기록을 격리하기 위해 대화별로 세션이 생성됩니다
session = agent.create_session()

...

프로세스 재시작 후에도 기록이 유지되어야 하는 프로덕션 배포의 경우, MAF는 InMemoryHistoryProvider를 내구성이 있는 백엔드(durable backends)인 Azure Cosmos DB, Redis 또는 IHistoryProvider 인터페이스를 통한 모든 커스텀 구현체로 교체하는 것을 지원합니다.

4.3 압축 (Compaction)

컨텍스트 윈도우 (Context-window) 초과(overflow)는 장기 실행 에이전트에서 발생하는 가장 흔한 프로덕션 장애 중 하나입니다. CompactionProvider는 두 가지 전략을 통해 이 문제를 해결합니다:

슬라이딩 윈도우 (Sliding Window): 총 토큰 수가 max_context_window_tokens에 도달하면 오래된 메시지들을 정리 (prune) 합니다. 시스템 프롬프트 (system prompt) 와 가장 최근의 N개 메시지는 항상 보존됩니다.

도구 결과 압축 (Tool Result Compaction): 도구 결과는 종종 장황합니다. 예를 들어 웹 검색 결과는 수천 개의 토큰을 반환할 수 있습니다. 압축 (compaction) 레이어는 토큰 압박 (token pressure)이 발생할 때 도구 결과를 지능적으로 요약하여, 사용량을 줄이면서도 필수적인 정보는 유지합니다.

# 토큰 예산 계산:
# available_context = max_context_window_tokens - max_output_tokens - system_prompt_tokens
# 압축은 하드 한계치(hard limit)에 도달하기 직전에 실행됩니다.
...

4.4 TodoProvider

TodoProvider는 에이전트의 자체 컨텍스트 내에 **구조화된 작업 추적 시스템 (structured task-tracking system)**을 제공합니다. 에이전트가 자신의 진행 상황을 암묵적으로 기억하는 것에 의존하는 대신, TodoProvider는 에이전트가 명시적인 할 일 목록 (todo list)을 관리하기 위해 호출할 수 있는 도구 함수들을 노출합니다:

  • create_todo(title, description) -- 새로운 작업 항목 생성
  • complete_todo(id) -- 항목 완료 표시
  • list_todos() -- 모든 대기 중인 항목 가져오기
  • update_todo(id, status) -- 항목 상태 업데이트

이는 보기보다 매우 강력합니다. 에이전트는 복잡한 작업을 명시적인 작업 항목으로 분해하고, 완료 상태를 추적하며, 단계를 건너뛰는 것을 방지할 수 있습니다. 이 모든 과정은 에이전트 자신의 추론 (reasoning)에 의해 구동됩니다.

사용자: "상위 5개 AI 에이전트 프레임워크를 조사하고 비교해 주세요."

에이전트 (TodoProvider를 사용한 내부 추론):
...

4.5 AgentModeProvider -- 계획/실행 워크플로우 (Plan/Execute Workflow)

AgentModeProvider는 숙련된 전문가가 복잡한 작업에 접근하는 방식과 유사한 **2단계 워크플로우 (two-phase workflow)**를 구현합니다:

1단계 -- 계획 모드 (Plan Mode, 대화형)

계획 모드에서 에이전트는 _협력적 (collaborative)_입니다:

  • 모호함을 줄이기 위해 사용자에게 명확한 질문을 던집니다.
  • 의도한 접근 방식을 개략적으로 보여주는 상세한 할 일 목록을 생성합니다.
  • 인간의 검토를 위해 계획을 제시합니다.
  • 진행하기 전에 명시적인 승인을 기다립니다.

이것이 바로 인간 참여형 게이트 (human-in-the-loop gate)입니다. 사용자는 자율적인 작업이 시작되기 전에 계획을 수정하거나 방향을 완전히 바꿀 수 있습니다.

2단계 -- 실행 모드 (Execute Mode, 자율형)

승인이 완료되면, 에이전트는:

  • 할 일 목록(todo list)을 독립적으로 수행합니다.
  • 도구 호출(tool calls), 웹 검색, 메모리 쓰기를 수행합니다.
  • 각 작업이 완료될 때마다 할 일을 완료 상태로 표시합니다.
  • 진행 상황을 사용자에게 실시간으로 스트리밍(streaming)합니다.
  • 차단 요소가 되는 모호함(blocking ambiguity)에 직면하면 다시 계획 모드(plan mode)로 돌아갑니다.

이 패턴은 프로덕션 환경에서 에이전트를 신뢰할 수 있게(trustworthy) 만드는 핵심 요소입니다. 즉, 인간이 계획을 확인하고 승인하면, 에이전트는 이를 충실히 실행합니다.

4.6 MemoryContextProvider

MemoryContextProvider는 **파일 기반의 지속성 메모리(file-based durable memory)**를 제공합니다. 이는 에이전트가 세션(session)과 압축(compaction) 이벤트 전반에 걸쳐 읽고 쓸 수 있는 영구 저장소입니다.

이는 순수 인컨텍스트 메모리(in-context memory)의 치명적인 공백을 해결합니다. 압축이 발생하면 오래된 정보는 삭제됩니다. 만약 에이전트가 50개의 메시지 이전에 연구 결과를 작성했다면, 해당 정보는 더 이상 컨텍스트(context) 내에 남아있지 않을 수 있습니다. 하지만 에이전트가 이를 메모리 저장소에 저장했다면, MemoryContextProvider는 모든 컨텍스트 조립(context assembly) 사이클의 시작 시점에 해당 정보를 다시 주입합니다.

import tempfile
from pathlib import Path

...

4.7 SkillsProvider

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0