에이전틱 AI (Agentic AI) 디자인 패턴: 도구 사용, 멀티 에이전트, RAG 및 계획
요약
에이전틱 AI 시스템을 구축하는 데 필요한 핵심 디자인 패턴인 도구 사용, 멀티 에이전트, RAG, 계획 및 성찰에 대해 설명합니다. 각 패턴의 사용 시점과 구조를 분석하고 Python 스타일의 코드 스케치를 통해 실질적인 구현 방식을 제시합니다.
핵심 포인트
- 에이전틱 AI는 도구 사용, 멀티 에이전트, RAG 등 직교하는 패턴의 결합으로 구축됨
- 도구 사용 패턴은 실시간 데이터 접근과 비즈니스 로직 보안에 필수적임
- 모델에게 도구 스키마를 제공하고 실행 결과를 다시 전달하는 루프 구조가 핵심임
- 프레임워크에 종속되지 않는 범용적인 Python 코드 구조를 제안함
에이전틱 AI (Agentic AI) 디자인 패턴: 도구 사용, 멀티 에이전트, RAG 및 계획
핵심 에이전틱 패턴
에이전틱 AI (Agentic AI) 시스템은 대부분 결합 가능한 소수의 재사용 가능한 패턴들로 구축됩니다: 도구 사용 (tool-use), 멀티 에이전트 (multi-agent), RAG, 계획/추론 (planning/reasoning), 그리고 성찰/자기 수정 (reflection/self-correction)입니다. 이러한 패턴들은 서로 직교(orthogonal)합니다. 즉, "진정한" 에이전트는 종종 여러 패턴을 동시에 사용합니다. 아래에서는 각 패턴에 대해 다음과 같은 내용을 다룹니다: 사용 시점, 핵심 구조, 그리고 최소한의 실질적인 코드 스케치 (Python 스타일, 프레임워크에 종속되지 않음).
메시지와 선택적 도구를 입력받는 일반적인 llm.chat() 함수가 있고, 도구 호출(tool calls)은 코드 내에서 함수 호출로 표현된다고 가정합니다.
도구 사용 (Tool-use) 패턴 (API 및 데이터베이스)
사용 시점
실시간 데이터(API, DB, 검색, 내부 시스템)가 필요한 경우.
비즈니스 로직과 보안이 모델이 아닌 코드 내에 유지되어야 하는 경우.
모델이 URL이나 SQL을 임의로 만들어내는 대신 구조화된 호출(예: JSON)을 원하는 경우.
핵심 구조
도구를 스키마(schema)를 가진 일반 함수로 정의합니다.
모델에게 도구 정의(이름, 인자, 설명)를 제공합니다.
매 턴(turn)마다:
LLM에게 도구를 호출할지 여부를 묻습니다.
만약 호출한다면, 코드에서 도구(들)를 실행하고 그 결과를 다시 모델에 전달합니다.
그렇지 않다면, 최종 답변을 반환합니다.
예시: HTTP API + SQL DB를 사용하는 LLM
python
from typing import List, Dict, Any
import requests
import sqlite3
- 도구 (Tools) -
def fetch_weather(city: str) -> Dict[str, Any]:
여기에 실제 HTTP 호출을 래핑합니다
r = requests.get("https://api.example.com/weather", params={"q": city})
r.raise_for_status()
return r.json()
def query_orders(user_id: str) -> List[Dict[str, Any]]:
conn = sqlite3.connect("orders.db")
cur = conn.cursor()
cur.execute("SELECT id, total, status FROM orders WHERE user_id = ?", (user_id,))
rows = cur.fetchall()
conn.close()
return [
{"id": r, "total": r, "status": r}
for r in rows
]
TOOLS = [
{
"name": "fetch_weather",
"description": "도시 이름을 통해 현재 날씨를 가져옵니다.",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
{
"name": "query_orders",
"description": "사용자 ID를 통해 해당 사용자의 최근 주문 내역을 가져옵니다.",
"parameters": {
"type": "object",
"properties": {"user_id": {"type": "string"}},
"required": ["user_id"],
},
},
]
- 오케스트레이터 루프 (Orchestrator loop) -
def call_tool(tool_name: str, args: Dict[str, Any]) -> Any:
if tool_name == "fetch_weather":
return fetch_weather(**args)
if tool_name == "query_orders":
return query_orders(**args)
raise ValueError(f"알 수 없는 도구 {tool_name}")
def agent_turn(user_message: str) -> str:
messages = [{"role": "user", "content": user_message}]
# 첫 번째 호출: 모델에게 도구 사용 여부를 질문합니다.
response = llm.chat(messages=messages, tools=TOOLS)
...
핵심 아이디어:
실행 권한은 사용자에게 있으며, LLM은 도구로 가는 "경로(route)"만 지정합니다.
보안 및 관찰 가능성(Observability)을 위해 도구 호출을 로그로 남기고 가드레일(guard)을 설정할 수 있습니다.
동일한 패턴을 모든 API/DB에 적용할 수 있으며, 단순히 함수로 래핑(wrap)하기만 하면 됩니다.
멀티 에이전트 패턴 (Multi-agent pattern, 전문화된 에이전트)
사용 시점
작업이 자연스럽게 전문적인 역할(기획자, 조사관, 코더, 검토자)로 분해될 때.
도구 세트가 방대하거나 이질적(heterogeneous)일 때; 에이전트당 좁은 컨텍스트(context)를 유지하고 싶을 때.
역할별로 분리된 로그를 통해 더 명확한 디버깅(debugging)을 원할 때.
전형적인 변형들:
오케스트레이터 + 서브 에이전트 (sub-agents가 도구로서 호출됨).
중앙 컨트롤러가 없는 피어 투 피어 스웜 (Peer-to-peer swarm, 관리가 더 복잡함).
출력이 다음 에이전트로 전달되는 파이프라인 / 그래프 (Pipeline / graph).
예시: 전문가를 도구로 호출하는 감독 에이전트 (supervisor agent)
python
class Agent:
def init(self, name: str, system_prompt: str):
self.name = name
self.system_prompt = system_prompt
def run(self, task: str, context: str = "") -> str:
msgs = [
{"role": "system", "content": self.system_prompt},
...
researcher = Agent(
"researcher",
"당신은 사실에 기반하며 인용(citation)에 집중하는 연구 보조원입니다."
)
coder = Agent(
"coder",
"당신은 시니어 소프트웨어 엔지니어입니다. 당신은 명확하고 작동하는 코드를 작성합니다."
)
reviewer = Agent(
"reviewer",
"당신은 솔루션의 정확성, 엣지 케이스 (edge cases), 그리고 단순성을 검토합니다."
)
Rizwan Saleem | https://rizwansaleem.co
출처 (Sources)
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기