LeanX

랭그래프 맛보기: 멀티 에이전트 패턴

랭그래프는 AI 워크플로우를 노드와 엣지의 흐름도로 설계하는 라이브러리이며, 에이전트가 많아지면 Router(분류·배분), Subagents(감독자-부하), Handoffs(담당자 교체) 패턴 중 상황에 맞는 것을 골라 조합합니다.

에이전트 하나로 모든 일을 시키면 어떻게 될까요? 도구 20개를 든 만능 직원은 오히려 실수가 잦아집니다. 실제 회사처럼 '전문가 여러 명 + 업무 분담'이 답입니다. 랭그래프(LangGraph)는 이런 멀티 에이전트 시스템을 만드는 랭체인 팀의 라이브러리로, 앞서 배운 create_agent도 내부적으로 랭그래프로 만들어져 있습니다.

랭그래프 = 업무 흐름도를 코드로

체인이 일직선 조립라인이라면, 랭그래프는 화이트보드에 그리는 업무 흐름도입니다. 동그라미(노드)는 작업 단계, 화살표(엣지)는 이동 경로입니다. '조건에 따라 갈림길로 가기', '이전 단계로 되돌아가기(루프)', '중간에 사람 승인 받기'처럼 일직선 체인으로는 못 만드는 흐름을 그릴 수 있습니다.

  • 노드(Node): 작업 하나. LLM 호출, 함수 실행, 에이전트 등
  • 엣지(Edge): 다음에 어디로 갈지 정하는 화살표. 조건 분기 가능
  • 상태(State): 모든 노드가 공유하는 작업 기록판. 대화 내용 등이 쌓임

가장 작은 그래프: 분기가 있는 고객상담 흐름

# pip install langgraph
from langgraph.graph import StateGraph, MessagesState, START, END
from langchain.chat_models import init_chat_model

model = init_chat_model('openai:gpt-4o-mini', temperature=0)

# 노드 1: 문의 유형을 분류합니다
def classify(state: MessagesState):
    question = state['messages'][-1].content
    result = model.invoke(
        f'다음 문의가 환불 관련이면 refund, 아니면 general이라고만 답해: {question}'
    )
    # 분류 결과를 상태에 기록 (다음 분기에서 사용)
    return {'messages': [result]}

# 노드 2, 3: 유형별 담당 답변
def refund_desk(state: MessagesState):
    answer = model.invoke('환불 절차를 친절히 안내해줘: 7일 이내, 영수증 필요')
    return {'messages': [answer]}

def general_desk(state: MessagesState):
    answer = model.invoke('일반 문의에 친절히 답해줘: ' + state['messages'][0].content)
    return {'messages': [answer]}

# 갈림길: 분류 결과에 따라 다음 노드를 결정
def route(state: MessagesState) -> str:
    return 'refund_desk' if 'refund' in state['messages'][-1].content else 'general_desk'

# 흐름도 그리기
builder = StateGraph(MessagesState)
builder.add_node('classify', classify)
builder.add_node('refund_desk', refund_desk)
builder.add_node('general_desk', general_desk)
builder.add_edge(START, 'classify')
builder.add_conditional_edges('classify', route)  # 조건 분기!
builder.add_edge('refund_desk', END)
builder.add_edge('general_desk', END)

graph = builder.compile()
result = graph.invoke({'messages': [{'role': 'user', 'content': '환불하고 싶어요'}]})
print(result['messages'][-1].content)

멀티 에이전트 3대 패턴

에이전트가 여러 명이 되면 '누가 언제 일할지'를 정하는 조직 구조가 필요합니다. 랭체인 공식 문서가 정리한 대표 패턴은 세 가지입니다.

1. Router: 콜센터 안내원

가장 단순한 구조입니다. 안내원(분류기)이 문의를 듣고 적절한 부서로 한 번에 연결해 줍니다. 위 예제 코드가 바로 Router 패턴입니다. 요청 유형이 명확히 나뉠 때(환불/배송/일반 등) 빠르고 저렴합니다.

2. Subagents: 팀장과 팀원

감독자(supervisor) 에이전트가 전문 부하 에이전트들을 '도구처럼' 호출하는 구조입니다. 팀장이 과제를 쪼개 리서치 담당, 작성 담당에게 나눠 주고 결과를 모아 최종 보고하는 모습과 같습니다. 대화 맥락은 팀장이 관리하고 팀원은 맡은 일만 합니다.

3. Handoffs: 상담원 교체

에이전트끼리 대화 바통을 직접 넘기는 구조입니다. 일반 상담원이 '이건 기술 문제네요' 하며 기술 상담원에게 전화를 통째로 넘기는 것과 같습니다. 넘겨받은 에이전트가 대화의 주도권을 가지며, 랭그래프에서는 노드가 Command 객체를 반환해 '다음은 네 차례'를 지정하는 방식으로 구현합니다.

패턴구조 비유언제 쓰나
Router콜센터 안내원요청 유형이 명확히 나뉠 때, 속도·비용 중시
Subagents팀장 + 팀원여러 전문 작업을 모아 하나의 결과로 합칠 때
Handoffs상담원 교체대화 주도권 자체를 전문가에게 넘겨야 할 때

Subagents 패턴 미니 예제: 감독자가 부하를 도구로 사용

from langchain.agents import create_agent
from langchain_core.tools import tool

# 부하 에이전트 1: 리서치 담당
researcher = create_agent(
    model='openai:gpt-4o-mini',
    tools=[],  # 실전에서는 웹검색 도구 장착
    system_prompt='주제에 대한 핵심 사실을 3줄로 정리하는 리서처야.',
)

@tool
def research(topic: str) -> str:
    '''주제를 조사해 핵심 사실 3줄을 반환합니다.'''
    result = researcher.invoke(
        {'messages': [{'role': 'user', 'content': topic}]}
    )
    return result['messages'][-1].content

# 감독자 에이전트: 부하(research 도구)를 부려서 일합니다
supervisor = create_agent(
    model='openai:gpt-4o-mini',
    tools=[research],
    system_prompt='필요하면 research 도구로 조사한 뒤 블로그 서두를 써줘.',
)

result = supervisor.invoke({
    'messages': [{'role': 'user', 'content': 'RAG 기술로 블로그 서두 써줘'}]
})
print(result['messages'][-1].content)

처음부터 멀티 에이전트로 설계하지 마세요. 에이전트 하나 + 도구 몇 개로 시작하고, 도구가 10개를 넘거나 역할이 뚜렷이 갈릴 때 분리하는 것이 정석입니다. 단순한 구조가 디버깅도 비용도 유리합니다.

에이전트가 많아질수록 LLM 호출 횟수가 늘어 비용과 지연이 급증합니다. 특히 Subagents는 결과가 감독자를 한 번 더 거치므로 호출이 추가됩니다. LangSmith 같은 추적 도구로 호출 흐름을 눈으로 확인하며 개발하세요.

축하합니다! 체인, 프롬프트, RAG 3부작, 에이전트, 랭그래프까지 — LLM 앱 개발의 뼈대를 모두 훑었습니다. 다음 단계로는 지금까지의 부품을 조합해 '내 문서로 답하는 RAG 챗봇 + 웹검색 에이전트'를 직접 만들어 보시길 추천합니다.