
AI 에이전트 개론 - 정의부터 아키텍처, 실전 운용을 고려한 설계까지
요약
AI 에이전트의 정의, 아키텍처, 그리고 실전 운용을 위한 설계 방법론을 다룹니다. 기존 챗봇 및 워크플로우와의 차이점을 분석하고, LLM의 발전이 에이전트의 자율성을 어떻게 실현했는지 설명합니다.
핵심 포인트
- AI 에이전트는 목표 달성을 위해 자율적으로 태스크를 실행하는 시스템임
- 워크플로우와 달리 에이전트는 LLM이 프로세스와 도구 사용을 동적으로 제어함
- ReAct 프레임워크(생각-행동-관찰)를 통한 반복적 거동이 핵심임
- 최신 LLM의 계획 유지 및 도구 호출 능력 향상이 에이전트 실용화의 핵심 동력임
AI 에이전트를 둘러싼 기술은 나날이 진보하고 있으며, 실전 운용을 고려한 HowTo(방법론)도 보이기 시작했다.
실제로 AI 에이전트 개발에 참여하고, AI 에이전트 스터디를 개최하는 과정에서 AI 에이전트의 정의, 개발 방법, 아키텍처 및 운용을 정리하고 싶어 본 기사를 집필하게 되었다.
기존 챗봇(Chatbot)과의 차이점이나, AI 에이전트가 주목받게 된 배경에 대하여.
AI 에이전트의 정의에는 여러 설이 있으나, 본 기사에서는 "목표 달성을 위해 자율적으로 태스크(Task)를 실행하는 AI 시스템"으로 정의한다.
"자율적"이라는 것이 무엇인지 잘 표현되어 있다고 생각한 것이 Anthropic의 2024년 12월 기사인 Building effective agents로, 워크플로우(Workflow)와 에이전트(Agent)의 대비 속에서 다음과 같이 표현하고 있다.
Workflows are systems where LLMs and tools are orchestrated through predefined code paths.
Agents, on the other hand, are systems where LLMs dynamically direct their own processes and tool usage, maintaining control over how they accomplish tasks. (워크플로우란 LLM과 도구가 사전에 정의된 코드 경로를 통해 오케스트레이션되는 시스템이다. 반면, 에이전트란 LLM이 자신의 프로세스와 도구 사용을 동적으로 지시하며, 태스크를 완수하는 방법을 스스로 제어하는 시스템이다.)
AI 에이전트의 거동은 "생각한다 → 행동한다 → 결과를 관찰한다 → 생각한다"의 반복(ReAct 프레임워크)이며, 상술한 Anthropic의 에이전트 정의는 "자율적" = 행동 계획과 실행 결과에 따른 계획 수정을 LLM이 판단한다는, 구현을 보면 검증 가능한 형태로 되어 있다.
컴퓨터 사이언스(Computer Science) 분야에서 AI 에이전트의 개념이 탄생한 것은 1950년대이며, 아이디어 자체는 오래전부터 존재했지만 범용성이나 자연어 지시가 실현되어 실용화될 수 있게 된 것은 LLM의 능력이 향상된 2024년경이다.
과거 연구의 예로, 1995년 Michael Wooldridge 등의 논문 "Intelligent Agents: Theory and Practice" [1]에서는 AI 에이전트의 정의가 다음과 같이 정리되어 있다.
광의의 의미: 자율성, 사회성, 반응성, 능동성의 4가지 성질을 가진 시스템
(AI 연구자가 사용하는 듯한) 협의의 의미: 4가지 성질에 더해 인간과 같은 속성을 부여한 시스템
광의의 의미는 현대의 AI 에이전트 시스템적 프레임워크로, 협의의 의미는 BDI 아키텍처(인간의 마음의 움직임을 모델로 한 AI 에이전트 설계 사상)로 계승되었다.
오랫동안 이론에 머물러 있던 AI 에이전트가 실용 수준에 도달한 배경에는 주로 3가지 진화가 있다고 생각한다.
모델 능력 향상: 긴 태스크를 탈선하지 않고 수행할 수 있는 모델(Claude, GPT, Gemini의 각 최신 세대)이 등장했다. 특히 "여러 단계에 걸쳐 계획을 유지하며 도구를 정확하게 구분하여 호출하는" 능력이 실용 수준에 도달한 것이 크다.
이 진보는 2023년경의 에이전트(AutoGPT 등)와 대비하면 이해하기 쉽다. 당시의 에이전트는 목표 달성 판정을 자연어에 의한 자기 평가에 의존하고 있었으며, 판정 기준이 일관되지 않은 채 태스크를 계속 반복하여 작업이 끝나지 않는 현상이 다수 보고되었다.
(참고) AutoGPT Planning Failures - Infinite Loops & Resource Depletion (2023)
Yang, Yue, & He (2023) [2]의 연구에서는 WebShop 벤치마크에서 GPT-4를 사용한 Auto-GPT형 에이전트의 성공률이 0.24(24%)에 그치고 있다. 또한, 성능이 낮은 다른 모델의 의견을 도입함으로써 GPT-4의 퍼포먼스가 향상되었다는 결과도 나와 있어, 당시의 모델은 "단독으로 일관된 방침을 유지하며 계획을 유지하는" 능력이 낮았음을 알 수 있다.
LLM의 능력 향상은 현재 AI 에이전트 보급의 큰 요인 중 하나라고 할 수 있을 것이다.
표준 프로토콜의 성립: MCP를 통해 도구 연결이 표준화되고 에코시스템(Ecosystem)이 폭발적으로 확대됨에 따라, AI 에이전트가 할 수 있는 범위도 크게 넓어졌다. (MCP에 대해서는 §4.1에서 상세히 기술)
단순히 Anthropic 주도의 하나의 프로토콜에 머물지 않고, OpenAI나 Google 등 경쟁 벤더를 포함한 각 기업이 자사 제품에 잇따라 채택하면서 "도구를 하나 만들면 각사의 에이전트에서 사용할 수 있게" 되어 통합 비용이 극적으로 낮아졌다.
2025년 12월에는 MCP가 Linux Foundation 산하의 Agentic AI Foundation으로 이관되었으며, Anthropic, Block, OpenAI가 공동 설립자로, AWS, Google, Microsoft, Cloudflare, Bloomberg 등이 지원 멤버로 이름을 올리며 오픈 스탠다드(Open Standard)로서 정비가 진행되고 있다.
(참고) Zuplo - One Year of MCP
IDE 통합형 에이전트의 등장: 코딩/개발 에이전트(Claude Code, Cursor, Kiro 등)와 같이 IDE에 통합된 에이전트도 등장했다. 채팅 기반으로 에이전트에게 지시를 내릴 수 있는 접근성 또한 진입 장벽을 낮추는 데 한몫하고 있다고 생각한다.
LLM 성능의 향상, 프로토콜의 표준화, 에이전트를 다루기 쉬운 도구의 등장 등 AI 에이전트 보급을 위한 토대는 마련되었다.
PoC를 넘어 실용화로 나아가기 위해서는 평가, 보안, 운용을 어떻게 설계하고 구현할지가 앞으로의 과제이다.
| 개념 | 하는 일 | LLM이 제어 흐름(Control Flow)을 결정하는가 |
|---|---|---|
| 챗봇 | 1문 1답식의 대화 | ✕ (단발성 생성만 수행) |
| RAG | 검색 결과를 문맥에 넣어 답변 | ✕ (검색 $\rightarrow$ 생성의 고정된 흐름) |
| 워크플로 (LLM 체인) | 사전 정의된 절차에 따라 LLM을 여러 번 호출 | ✕ (흐름은 인간이 설계) |
| AI 에이전트 | 목표를 향해 도구를 자율적으로 사용 | ◯ (LLM이 다음 행동을 결정) |
미리 인간이 정한 경로를 따라가는 "워크플로(Workflow)"와 달리, 상황 변화에 따라 LLM 스스로 경로를 다시 선택하며 목표를 향해 나아가는 시스템이 "AI 에이전트"이다.
"에이전트"라는 단어로는 실체를 파악하기 어렵지만, 뇌(모델, 메모리)와 팔다리(도구)가 있고 그곳에 지시를 내린다는 이미지로 이해하면 된다. 여기서는 에이전트를 안전하게 사용하기 위해 실행 환경과 가드레일(Guardrail)도 포함했다.
OpenAI의 "A practical guide to building agents"에서는 에이전트의 핵심 요소로 모델, 지시(Instructions), 도구 세 가지를 꼽고 있다.
여기서는 그 세 가지에 더해, 에이전트 실행 시 필요해지는 **메모리(Memory)**와 폭주를 방지하는 실행 환경 및 가드레일을 더한 5가지 요소로 생각한다.
에이전트의 LLM 이외의 구성 요소를 합쳐 하네스(Harness)라고 부르기도 한다.
루프의 각 단계에서 "다음에 무엇을 해야 할지"를 판단한다.
에이전트 용도에서는 지시 이행 능력(Instruction Following), 도구 호출 정확도, 긴 컨텍스트에서의 일관성이 중요하다.
작업 품질과 비용 및 레이턴시(Latency)의 균형을 맞추기 위해 단계별로 모델을 구분하여 사용하는 것도 검토한다.
(예: 계획 수립이나 최종 리뷰와 같이 난이도가 높은 태스크에는 고성능 모델을, 도구 호출과 같이 난이도가 낮은 태스크에는 경량화된 저비용 모델을 할당)
매번 수행할 일이 정해져 있는 태스크라면 LLM이 아닌 프로그램으로 실행하는 것이 더 나은 경우도 있다.
"에이전트에게 무엇을, 어떻게 시킬 것인가"를 정의하는 텍스트.
챗봇이라면 페르소나나 답변의 톤을 설정하는 경우가 많지만, 에이전트에서는 여기에 더해 완료 정의, 정보가 부족하거나 모순될 때 어떻게 움직일지, 인간에게 승인이나 질문을 할 타이밍 등 판단 기준을 정의해 주는 것이 중요하다.
| 주관적인 판단 기준 | 검증 가능한 판단 기준 |
|---|---|
| "출력이 고품질이 되면 멈춘다" | "테스트 커버리지가 80%를 넘으면 멈춘다 (임계값)" |
| ... |
최근 모델들은 눈치가 빠르다고 해야 할지, 알아서 완료를 판단해 주는 경우도 많지만,
true/false로 판단 가능하며 주관적인 추론의 여지가 없는 조건을 주는 편이 더 안전하다.
내가 직접 AI 에이전트를 사용해 본 경험으로는, 클라우드 환경 구축 시 트러블슈팅 과정에서 "에러를 해결해 줘"라고 통째로 맡겨버리면 막다른 길에 빠져 미궁 속에서 계속 명령어를 입력하기만 하는 경우가 있다. 그래서 "이 에러의 원인을 조사해 줘"와 같이 완료 조건을 조정하고 있다.
도구(Tool)의 실체는 모델에게 보여주는 함수의 설명서와 같으며, 「이름」, 「설명문」, 「입력 스키마 (JSON 등)」의 3종 세트로 구성되어 있다. 이것이 통째로 프롬프트 (Prompt)의 일부로서 모델에게 전달된다.
MCP가 표준화한 것은 바로 이 「이름·설명문·스키마」이며, MCP 서버를 구축한다는 것은 실질적으로 이것들을 표준 형식으로 공개하는 것을 의미한다.
「도구를 부여한다」는 것은 배후에서 새로운 코드를 주입하는 것이 아니라, 「이러한 함수를 호출할 수 있습니다」라는 텍스트를 컨텍스트 (Context)에 추가하는 것에 불과하다. 설명문은 프롬프트의 일부로서 읽히며, LLM에 의해 사용할 도구가 판단된다.
또한, LLM 자체는 도구를 「실행」하는 것이 아니라 다음과 같이 「요청」하고 있다.
- 모델이 「이 도구를 이 인자(Argument)로 호출하고 싶다」라는 구조화된 텍스트를 출력한다.
- 그것을 받은 애플리케이션이 실제 처리를 실행한다.
- 실행 결과를 「도구 결과」로서 대화 이력에 추가한다.
- 모델은 그 결과를 읽고 다음에 무엇을 할지 다시 판단한다.
(따라서 반환값(Return value)도 LLM이 읽고 판단할 수 있는 형식이어야 한다.)
이러한 분리가 있기 때문에, 중간에 인간의 승인이 들어가는 플로우 (Flow)에서 「모델을 멈추지 않고 실행만 멈추는 것」이 가능하며, 만에 하나 LLM이 폭주하더라도 앱 측에서 허가하지 않은 조작 (API)은 실행할 수 없다는 가드레일 (Guardrail)이 작동한다.
도구는 제공처에 따라 3가지 종류로 나뉜다.
| 종류 | 설명 | 예 |
|---|---|---|
| 빌트인 도구 (Built-in Tool) | 모델 제공자가 준비하며, 제공자의 인프라에서 실행됨 | 웹 검색, 코드 실행 샌드박스 (Sandbox) |
| 커스텀 함수 도구 (Custom Function Tool) | 개발자가 직접 정의하며, 자신의 인프라에서 실행함 | 사내 API 호출, DB 업데이트 |
| MCP 도구 (MCP Tool) | 표준 프로토콜로 외부 서버가 공개하며, 대응하는 어떤 에이전트로부터도 호출 가능 | GitHub 조작, Slack 게시 |
LLM 자체는 상태를 가지지 않으며, 경과를 매번 컨텍스트로서 다시 제공받는다.
에이전트에서는 정보를 어디에, 얼마 동안 유지할지에 따라 3가지 패턴으로 나누어 생각하는 경우가 많다.
| 종류 | 구현 방법 | 용도 |
|---|---|---|
| 단기 기억 | 컨텍스트 윈도우 (Context Window) | 현재 태스크의 경과 |
| ... |
장시간 태스크에서는 단기 기억의 컨텍스트가 넘치기 때문에, 컨텍스트 압축이나 서브 에이전트 (Sub-agent) 분할을 검토한다.
프로젝트의 전제 지식 등은 파일로 분리해 두는 것이 좋다. (Claude Code라면 CLAUDE.md)
이 분야는 「컨텍스트 엔지니어링 (Context Engineering)」이라 불리며, 프롬프트 엔지니어링 (Prompt Engineering)이 「무엇을 지시할 것인가」의 최적화였다면, 컨텍스트 엔지니어링은 「한정된 컨텍스트 안에서 각 단계에 무엇을 보여줄 것인가」를 최적화하는 것이다.
도구를 실제로 실행하는 환경 (컴퓨팅, 권한 제어 등)이나 폭주를 방지하는 메커니즘.
가드레일은 단일 메커니즘이 아니라 여러 계층을 겹쳐서 설계한다.
| 가드레일의 종류 | 목적 | 구체적인 예 |
|---|---|---|
| 관련성 체크 | 태스크와 무관한 입출력을 차단 | 주제에서 벗어난(Off-topic) 지시를 무시함 |
| ... |
(참고) "A practical guide to building agents"
최근 Loop Engineering이라는 수법(인간이 직접 AI 에이전트에게 지시를 내리는 것이 아니라, AI 에이전트가 태스크를 실행하는 사이클을 설계하는 것)이 등장했는데, 그 이름처럼 AI가 사이클을 계속 돌리는 수법이므로 폭주를 방지하는 가드레일의 중요도는 더욱 높아질 것이다.
전장에서 정리한 5가지 구성 요소를 바탕으로, 본장에서는 「실제 에이전트를 어떻게 설계하고 구현으로 옮길 것인가」의 구체적인 모습을 살펴본다.
처음에는 단순한 구성부터 시작하여, 부족하면 에이전트나 도구를 추가해 나가는 것을 추천한다.
(단, 프로그램이나 워크플로우 (Workflow)로 대응할 수 있다면 억지로 에이전트를 사용할 필요는 없다.)
에이전트의 미니멀한 정의를 코드로 옮기면 다음과 같다.
(llm.call()은 특정 SDK의 실제 구문이 아니라, LLM 프로바이더의 API 호출을 추상화한 것이다.)
messages = [{"role": "user", "content": task}]
while True: # 루프
response = llm.call(messages, tools=TOOLS) # LLM 호출
...
위 코드에서 고정되어 있는 것은 '묻는다 → 움직인다 → 다시 묻는다'의 형태뿐이며, 무엇을, 언제 할지는 모델에게 맡겨져 있다. (자율적)
이런 것은 자율적이지 않다.
plan = llm.call("이 태스크를 서브 태스크(subtask)로 분해해줘", output_schema=PLAN_SCHEMA) # 1회만 호출
results = [worker_llm.call(subtask) for subtask in plan.subtasks] # 병렬 실행
summary = llm.call("이 결과들을 통합해줘", results) # 1회만 호출
에이전트 연동 프로토콜은 MCP(에이전트 - 도구) 와 A2A(에이전트 간) 두 가지로 크게 나뉜다.
MCP
유명한 서비스들은 MCP 서버를 공개하고 있는 경우가 많으므로, 이를 활용하면 직접 통합 코드를 작성하지 않고도 서비스 연동을 할 수 있다.
도구(tool)의 설명문은 프롬프트의 일부로서 읽히기 때문에, 악의적인 설명문이 심어지는 툴 포이즈닝(tool poisoning)이나 토큰 소비량 증가에는 주의가 필요하다.
MCP에 국한된 이야기는 아니지만, 무엇이든 무작정 연결하는 것은 재고해봐야 한다.
자체 서비스나 도구를 에이전트가 사용하게 하고 싶을 때도, MCP 서버로서 하나만 공개하면 에이전트 프레임워크마다 여러 개를 만들 필요가 없어진다.
하나의 에이전트 내에서 완결되는 단순한 도구(본인만 사용하는 쉘 스크립트 등) 정도라면, MCP 서버로 만들지 않고 함수로서 도구를 직접 정의해도 무방하다.
A2A
에이전트 연동 시, 신뢰 경계(trust boundary)를 넘는 경우(인증·인가를 거치는 경우)에 사용한다.
예를 들어, 자사의 고객 지원 에이전트가 결제 처리는 별도 팀(혹은 별도 회사)이 운용하는 전문 에이전트에게 위임하고 싶은 케이스가 있다고 가정하자. 이 경우 인증·인가가 필요하게 된다.
A2A에서는 상대 에이전트가 무엇을 어디까지 할 수 있는지를 Agent Card(에이전트의 능력을 기술한 서명된 메타데이터)를 통해 사전에 확인하고, 인증·인가를 거쳐 태스크를 전달한다.
반대로 하나의 애플리케이션이 관리하는 범위 내에서 에이전트끼리 연동하는 것이라면, 프레임워크 내부의 위임 메커니즘으로 구현할 수 있다.
A2A에서는 Agent Card를 통한 사칭이나 과장으로 인해 가짜 에이전트에게 태스크를 넘기게 하는 공격이 가능하므로, Agent Card의 신원 및 내용 검증은 사용자 측에서 직접 구현해야 한다.
단일 에이전트로 구성할지, 혹은 여러 에이전트로 구성할지에 따라, 그리고 여러 개로 구성할 경우 어떻게 연동할지에 따라 다양한 변형이 존재한다.
| 패턴 | 내용 | 적합한 상황 |
|---|---|---|
| 싱글 에이전트 (Single Agent) | 하나의 모델이 도구군을 가지며, 목표를 향해 스스로 도구를 계속 선택함 | 처음에는 이 구성을 시도함 |
| 서브 에이전트 (계층형 멀티 에이전트) | 오케스트레이터(Orchestrator)가 전문 에이전트에게 위임함 | 컨텍스트를 분리하고 싶은 조사형 태스크 |
| 대화형 멀티 에이전트 | 에이전트끼리 서로 토론·비평함 | 여러 관점에서의 리뷰나 브레인스토밍 등 |
여러 에이전트를 조합하는 멀티 에이전트(Multi-agent) 구성을 취함으로써 작업을 병렬화하거나, 스킬셋이 크게 다른 에이전트를 루프(loop) 안에 포함시킬 수 있다. 반면, 토큰 소비량이 늘어나기 쉽고 에이전트 간 정보 전달 시의 손실(loss) 등이 발생하는 단점도 있다.
싱글 에이전트로 충분하다면, 굳이 멀티 에이전트 구성으로 만들 필요는 없다.
Anthropic의 "Building Effective Agents"에서는 다음과 같이 언급하고 있다.
Start with simple prompts, optimize them with comprehensive evaluation, and add multi-step agentic systems only when simpler solutions fall short.
(처음에는 단순한 프롬프트로 시작하여, 포괄적인 평가를 통해 최적화하고, 더 단순한 솔루션이 부족할 때만 멀티 스텝 에이전트 시스템을 추가하세요)
주요 프레임워크의 특징(설계 사상·특기 영역)은 다음과 같다.
(학습 비용은 프레임워크를 구성하는 개념·기능의 양과 이해 난이도를 주관적이고 상대적으로 판단한 것이다.)
| 프레임워크 | 제공처 | 지원 언어 | 특징 | 특기 영역 | 학습 비용 |
|---|---|---|---|---|---|
| AG2 (구 AutoGen의 커뮤니티 후계) | 커뮤니티 (Apache 2.0) | Python | 이벤트 주도형 액터 모델 (메시지를 트리거로 에이전트가 병렬적으로 자율 구동) | 다중 에이전트에 의한 토론, 자율적인 코드 실행·수정 루프 | 높음 (비동기 이벤트 설계 및 대화 제어 프롬프트 조정의 난이도가 높음) |
| Claude Agent SDK | Anthropic | Python / TypeScript | Claude Code와 동일한 하네스(Harness)를 SDK로 제공, bash 및 파일 시스템을 도구로 이용 | 장시간 코딩 태스크, 컴퓨터 조작 | 중간 (코드는 심플하지만 배워야 할 개념의 수가 많음) |
| CrewAI | CrewAI | Python | 결정론적 Flows와 역할 기반의 에이전트 그룹인 Crews의 2층 구조 | 조직을 모사한 태스크, PoC 구축 | 낮음 (직관적으로 개념을 이해하기 쉬움) |
| Dify | LangGenius | 노코드 (GUI), 확장은 Python / JavaScript | LLM 앱 구축 특화 노코드 플랫폼 (RAG·워크플로우·프롬프트 관리 통합) | 챗봇·RAG 앱 구축, 비엔지니어에 의한 LLM 프로토타이핑 | 낮음 (블록을 연결하여 플로우를 생성할 수 있음) |
| Google ADK | Python / TypeScript / Go / Java / Kotlin | Google Cloud 에코시스템·A2A의 네이티브 통합 | Gemini의 거대 컨텍스트를 활용한 멀티모달 처리, 조직 간 에이전트 연계 | 중간~높음 (Google Cloud의 IAM 및 인프라 지식이 필요) | |
| LangGraph | LangChain | Python / TypeScript | Graph를 통한 결정론적 제어와 상태 관리 (State Management) | Human-in-the-loop, 방대한 이력 관리 | 높음 (Graph가 다소 접근하기 어려울 수 있음) |
| Mastra | Kepler Software | TypeScript | TypeScript-first·타입 안전(Type-safe) 설계, Evals(평가)를 독립된 컴포넌트로 보유 | Web·프론트엔드 계열 팀 주도의 개발, AI 기능의 재사용성, 확장 패턴의 철저함 (composable한 프리미티브 설계) | 낮음 (TypeScript의 타입 시스템을 따름) |
| Microsoft Agent Framework | Microsoft | Python / .NET (C#) / Go | Semantic Kernel 에코시스템에 통합된 엔터프라이즈용 견고한 에이전트 기반 | 승인 기능 등 엔터프라이즈용 보안 | 중간~높음 (기능이 풍부하며 Microsoft 에코시스템의 이해가 필요) |
| n8n | n8n GmbH | 노코드 (GUI), 커스텀 노드는 JavaScript/Python | 자동화된 워크플로우의 일부로 AI 에이전트 노드를 배치, 연결 가능한 도구 종류가 풍부 | 도구 간 데이터 연계, AI를 자동화 플로우의 한 단계로 포함 | 낮음 (드래그 앤 드롭으로 플로우를 생성할 수 있음) |
| OpenAI Agents SDK | OpenAI | Python / TypeScript (신기능은 Python 우선) | 경량·심플, 핸드오프 (Handoff, 대화 인계) 메커니즘, 샌드박스 실행 지원 | OpenAI 스택에 대한 최속 추종, 핸드오프를 통한 에이전트 연계 | 낮음~중간 (코드와 개념 모두 심플함) |
| Strands SDK | AWS | Python / TypeScript (TypeScript는 퍼블릭 프리뷰, 멀티 에이전트 기능은 미지원) | 모델 주도 (Model-driven, 절차를 인간이 설계하지 않고 모델이 실행 시점에 매번 구성), 인프라와 오케스트레이션의 분리 (모델 비의존 설계) | 사전에 절차를 확정할 수 없는 탐색적 태스크, 모델 비의존적 운용 | 중간 (익혀야 할 개념이 다소 많음) |
선택할 때는 각 프레임워크의 특기 영역과 목적(PoC를 빠르게 돌리고 싶은지, 운영 환경에서 복잡한 상태 관리·재시도(Retry)가 필요한지, 특정 벤더의 에코시스템에서 구동할 것인지……)이 부합하는지를 고려해야 한다.
경량 프레임워크는 구축 시의 학습 비용이 낮지만, 래핑(Wrapping)된 영역이 많은 만큼 트러블슈팅(Troubleshooting) 시 어디가 원인인지 파악하기 어려울 때도 있다. 반대로 유연성이 높아 사용자 측에서 여러 가지를 정의해야 하는 프레임워크는 어떤 일이 일어나고 있는지 파악하기 쉬운 면이 있다.
벤더(Vendor)가 제공하는 프레임워크라 하더라도, 실행 환경이나 호출할 모델을 유연하게 선택할 수 있는 것도 있다.
에이전트를 만드는 것 자체는 AI를 사용하면 금방 할 수 있지만, PoC(Proof of Concept) 단계를 넘어 실무(Production)에서도 사용할 수 있는 것을 만들기 위해서는 기준을 정하고 평가하는 것이 필요하다.
AI 에이전트의 평가는 챗봇에서 측정하는 것과 같은 답변의 좋고 나쁨, 레이턴시(Latency), 토큰 소비량에 더해, 도구 호출(Tool Calling)·계획(Planning)·핸드오프(Handoff), 안전성(챗봇에서도 물론 중요하지만, AI 에이전트는 에코시스템이 확장되기 쉬움) 등도 살펴볼 필요가 있어 대상이 광범위하다.
본 기사 2장의 에이전트 5요소(모델·지시·도구·메모리·가드레일)에 평가할 내용과 대표적인 지표·수법을 매핑한다.
| 평가할 요소(§2.1) | 평가할 내용 | 지표·수법의 예 |
|---|---|---|
| (1) 모델 | 출력 형식이 올바른가, 금지 단어·내용이 포함되어 있지 않은가. 모델의 선택·판단이 타당한가. 레이턴시·토큰 소비량이 허용 범위 내인가. | 어서션(Assertion), 참조 기반 평가, 레이턴시(TTFT, TPOT, 처리량) |
| (2) 지시 | 태스크(Task) 해석이 사용자의 의도와 어긋나지 않는가. 출력 내용이 논리적으로 파탄 나지 않았는가. 완료 조건이 충족되었는가. 불필요한 단계를 밟고 있지는 않은가. | LLM-as-a-Judge, Task Success Rate, 단계 수, 중복 액션율 |
| (3) 도구 | 적절한 도구를 적절한 인자(Argument)와 순서로 호출했는가 | Tool Correctness, 트레이스(Trace) 검사 |
| (4) 메모리 | 컨텍스트(Context)가 적절하게 관리되고 있는가 | LongMemEval, MemoryAgentBench |
| (5) 실행 환경·가드레일 | 가드레일이 각각 의도대로 작동했는가. 실행 환경의 사이징(Sizing)이 적절한가 (사용자 측에서 준비하는 경우) | 정밀도(Precision), 재현율(Recall), F1, 허위 양성률(False Positive Rate), 리소스 사용률 |
| (전체) 신뢰성 | 1회뿐만 아니라 매번 안정적으로 성공하는가 | pass^k (k회 연속으로 실행하여 k회 모두 성공할 확률) |
| (전체) 비용 | 태스크가 성공할 때까지 드는 비용 | Cost per (successful) task |
최종 출력을 확인하는 것도 중요하지만, AI 에이전트는 목표에 도달하기까지의 프로세스가 복잡하고 블랙박스화되기 쉽기 때문에, 결과는 좋더라도 중간에 불필요한 행동을 하고 있지는 않은지(토큰을 낭비하고 있는지), 위험한 조작을 하고 있지는 않은지(백업 없이 파괴적인 조작을 하고 있는 등), 프로세스(트레이스)도 평가해야 한다고 생각한다.
LLM은 동일한 입력이라도 출력이 다르기 때문에, 동일한 테스트 케이스를 여러 번 실행하여 성공이 우연이 아닌지도 확인하고 싶다. (pass^k 지표)
실무 환경의 외부 API나 RAG의 검색 결과가 바뀌면 에이전트의 평가도 흔들릴 수 있으므로, 에이전트의 추론·판단에 관한 테스트 케이스는 모킹(Mocking)을 검토한다.
AI 에이전트가 읽어들이는 것은 인간이 직접 입력하는 프롬프트(Prompt)에 국한되지 않고, MCP의 도구 설명이나 A2A의 에이전트 카드(Agent Card) 등 다방면에 걸쳐 있으며, 이것들이 오염되어 있으면 의도하지 않은 동작을 할 가능성이 있다. (간접 프롬프트 인젝션 (Indirect Prompt Injection))
또한, 메모리가 오염되면 향후 세션에 걸쳐 악의적인 지시가 지속될 수도 있다.
도구를 엄선하거나 세션 간에 가능한 것은 분리(클린업)하는 등의 대책도 유효하지만, 만일 악의적인 지시가 심겨졌을 때 피해를 최소한으로 줄일 수 있도록 각 에이전트의 권한 설계를 엄격히 하는 것이 매우 중요하다.
권한의 최소화: 에이전트에게 부여하는 인가는 태스크에 필요한 최소한으로 제한한다. '신뢰할 수 없는 데이터의 읽기', '중요 정보에 대한 액세스', '외부 전송 수단' 이 세 가지를 동시에 갖지 않도록 설계하는 것이 중요하다.
비가역적인 조작에 대한 인간의 승인 (Human-in-the-Loop): 메일 전송, 데이터 삭제, 상품 구매, 실무 배포 등 부작용을 동반하는 조작에는 반드시 인간의 승인 프로세스를 거친다.
샌드박스(Sandbox)에서의 실행: 코드 실행이나 파일 조작은 컨테이너 등의 격리 환경(샌드박스)에서 수행하고, 실행 결과만을 메인 시스템에 전달한다.
만든 후에도 지속적인 모니터링이 중요하다는 점은 AI 에이전트(AI Agent)에만 국한된 이야기가 아니지만, 연동된 도구(Tool)나 RAG, 모델의 영향을 받는다는 전제하에 설계하고 싶다.
트레이스(Trace) 취득: 입력·출력 결과뿐만 아니라 사고 과정, 도구 호출(Tool Call)의 인자(Argument), 사고 시간(Thinking 토큰) 등 모든 단계의 실행 궤적(Trace)을 기록하여, "왜 그런 행동을 했는지", "어디에서 사고가 막혔는지(Stack)"를 추적할 수 있도록 한다.
※ 응답 본문을 트레이스에 출력할 때는 비밀 정보가 평문으로 출력되지 않도록 마스킹(Masking) 등의 처리를 한다. OpenTelemetry는 기본 설정에서는 프롬프트(Prompt) 및 출력 내용을 출력하지 않는다.
(참고 과거 기사) OpenTelemetry의 LLM 트레이싱 표준 「GenAI Semantic Conventions」
예산 상한 설정: 자율 루프(Autonomous Loop)나 여러 번의 시도로 인해 예상보다 많은 토큰을 소비하게 되는 경우나, Denial of Wallet 공격(종량제 과금 방식을 악용하여 서비스의 가용성이 아닌 예산을 공격하는 행위)에 대한 대책.
태스크(Task) 단위·사용자 단위의 최대 스텝 수 상한(Max Iterations)이나 토큰 예산 상한을 설정해 두고, 초과할 것 같거나 초과했을 경우 알림(Alert)을 보낸다. 또한, 무한 루프나 비정상적인 사고 토큰 소비 등 긴급성이 높은 경우, 시스템 측에서 강제로 처리를 분리하는 서킷 브레이커(Circuit Breaker)를 구현한다.
서킷 브레이커는 토큰 소비량이 일정 수준을 넘으면 처리를 중단하도록 코드에 판정 로직을 넣거나, 툴킷(Toolkit)을 넣는 방식 등으로 구현 가능하다.
(Toolkit 예시) Microsoft - agent-governance-toolkit
레질리언스(Resilience) 설계: 외부 API의 장애, 네트워크 지연, 컨텍스트 오버플로(Context Overflow)로 인한 중단에 대비하여, 단계(Step)마다 상태를 외부 스토리지에 기록해 둔다. (많은 프레임워크가 상태 저장 메커니즘을 표준으로 갖추고 있다.)
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기