원문: https://langchain-ai.github.io/langgraph/agents/multi-agent/
개요
단일 에이전트는 여러 도메인을 전문화하거나 많은 도구를 관리해야 할 때 어려움을 겪을 수 있습니다. 이를 해결하기 위해 에이전트를 더 작고 독립적인 에이전트로 분리하여 멀티 에이전트 시스템으로 구성할 수 있습니다.
멀티 에이전트 시스템에서 에이전트는 서로 통신해야 합니다. 이들은 핸드오프(Handoff) 를 통해 통신합니다. 핸드오프는 제어권을 넘겨줄 에이전트와 해당 에이전트에게 전송할 페이로드를 설명하는 프리미티브입니다.
가장 인기 있는 두 가지 멀티 에이전트 아키텍처는 다음과 같습니다:
슈퍼바이저

langgraph-supervisor 라이브러리를 사용하여 슈퍼바이저 멀티 에이전트 시스템을 만들 수 있습니다:
pip install langgraph-supervisorfrom langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from langgraph_supervisor import create_supervisor
def book_hotel(hotel_name: str):
"""호텔 예약"""
return f"Successfully booked a stay at {hotel_name}."
def book_flight(from_airport: str, to_airport: str):
"""항공편 예약"""
return f"Successfully booked a flight from {from_airport} to {to_airport}."
flight_assistant = create_react_agent(
model="openai:gpt-4o",
tools=[book_flight],
prompt="You are a flight booking assistant",
name="flight_assistant"
)
hotel_assistant = create_react_agent(
model="openai:gpt-4o",
tools=[book_hotel],
prompt="You are a hotel booking assistant",
name="hotel_assistant"
)
supervisor = create_supervisor(
agents=[flight_assistant, hotel_assistant],
model=ChatOpenAI(model="gpt-4o"),
prompt=(
"You manage a hotel booking assistant and a"
"flight booking assistant. Assign work to them."
)
).compile()
for chunk in supervisor.stream(
{
"messages": [
{
"role": "user",
"content": "book a flight from BOS to JFK and a stay at McKittrick Hotel"
}
]
}
):
print(chunk)
print("\n")스웜(Swarm)

langgraph-swarm 라이브러리를 사용하여 스웜 멀티 에이전트 시스템을 만들 수 있습니다:
pip install langgraph-swarmfrom langgraph.prebuilt import create_react_agent
from langgraph_swarm import create_swarm, create_handoff_tool
transfer_to_hotel_assistant = create_handoff_tool(
agent_name="hotel_assistant",
description="Transfer user to the hotel-booking assistant.",
)
transfer_to_flight_assistant = create_handoff_tool(
agent_name="flight_assistant",
description="Transfer user to the flight-booking assistant.",
)
flight_assistant = create_react_agent(
model="anthropic:claude-3-5-sonnet-latest",
tools=[book_flight, transfer_to_hotel_assistant],
prompt="You are a flight booking assistant",
name="flight_assistant"
)
hotel_assistant = create_react_agent(
model="anthropic:claude-3-5-sonnet-latest",
tools=[book_hotel, transfer_to_flight_assistant],
prompt="You are a hotel booking assistant",
name="hotel_assistant"
)
swarm = create_swarm(
agents=[flight_assistant, hotel_assistant],
default_active_agent="flight_assistant"
).compile()
for chunk in swarm.stream(
{
"messages": [
{
"role": "user",
"content": "book a flight from BOS to JFK and a stay at McKittrick Hotel"
}
]
}
):
print(chunk)
print("\n")핸드오프
멀티 에이전트 상호작용의 일반적인 패턴은 핸드오프로, 한 에이전트가 제어권을 다른 에이전트에게 넘깁니다. 핸드오프를 통해 다음을 지정할 수 있습니다:
- 목적지: 이동할 대상 에이전트
- 페이로드: 해당 에이전트에게 전달할 정보
이것은 langgraph-supervisor(슈퍼바이저가 개별 에이전트에게 핸드오프)와 langgraph-swarm(개별 에이전트가 다른 에이전트에게 핸드오프) 모두에서 사용됩니다.
create_react_agent로 핸드오프를 구현하려면 다음을 수행해야 합니다:
1. 제어권을 다른 에이전트로 전송할 수 있는 특수 도구 생성
def transfer_to_bob():
"""bob에게 전송"""
return Command(
# 이동할 에이전트(노드)의 이름
goto="bob",
# 에이전트에게 전송할 데이터
update={"messages": [...]},
# LangGraph에게 부모 그래프의 에이전트 노드로
# 이동해야 함을 나타냄
graph=Command.PARENT,
)2. 핸드오프 도구에 접근할 수 있는 개별 에이전트 생성
flight_assistant = create_react_agent(
..., tools=[book_flight, transfer_to_hotel_assistant]
)
hotel_assistant = create_react_agent(
..., tools=[book_hotel, transfer_to_flight_assistant]
)3. 개별 에이전트를 노드로 포함하는 부모 그래프 정의
from langgraph.graph import StateGraph, MessagesState
multi_agent_graph = (
StateGraph(MessagesState)
.add_node(flight_assistant)
.add_node(hotel_assistant)
...
)완전한 구현 예제
이를 종합하여 항공편 예약 어시스턴트와 호텔 예약 어시스턴트라는 두 에이전트가 있는 간단한 멀티 에이전트 시스템을 구현하는 방법은 다음과 같습니다:
from typing import Annotated
from langchain_core.tools import tool, InjectedToolCallId
from langgraph.prebuilt import create_react_agent, InjectedState
from langgraph.graph import StateGraph, START, MessagesState
from langgraph.types import Command
def create_handoff_tool(*, agent_name: str, description: str | None = None):
name = f"transfer_to_{agent_name}"
description = description or f"Transfer to {agent_name}"
@tool(name, description=description)
def handoff_tool(
state: Annotated[MessagesState, InjectedState], # (1) 런타임에 상태 주입
tool_call_id: Annotated[str, InjectedToolCallId],
) -> Command:
tool_message = {
"role": "tool",
"content": f"Successfully transferred to {agent_name}",
"name": name,
"tool_call_id": tool_call_id,
}
return Command( # (2) Command 객체 반환
goto=agent_name, # (3) 이동할 에이전트
update={"messages": state["messages"] + [tool_message]}, # (4) 상태 업데이트
graph=Command.PARENT, # (5) 부모 그래프로 이동
)
return handoff_tool
# 핸드오프 도구 생성
transfer_to_hotel_assistant = create_handoff_tool(
agent_name="hotel_assistant",
description="Transfer user to the hotel-booking assistant.",
)
transfer_to_flight_assistant = create_handoff_tool(
agent_name="flight_assistant",
description="Transfer user to the flight-booking assistant.",
)
# 간단한 에이전트 도구
def book_hotel(hotel_name: str):
"""호텔 예약"""
return f"Successfully booked a stay at {hotel_name}."
def book_flight(from_airport: str, to_airport: str):
"""항공편 예약"""
return f"Successfully booked a flight from {from_airport} to {to_airport}."
# 에이전트 정의
flight_assistant = create_react_agent(
model="anthropic:claude-3-5-sonnet-latest",
tools=[book_flight, transfer_to_hotel_assistant],
prompt="You are a flight booking assistant",
name="flight_assistant"
)
hotel_assistant = create_react_agent(
model="anthropic:claude-3-5-sonnet-latest",
tools=[book_hotel, transfer_to_flight_assistant],
prompt="You are a hotel booking assistant",
name="hotel_assistant"
)
# 멀티 에이전트 그래프 정의
multi_agent_graph = (
StateGraph(MessagesState)
.add_node(flight_assistant)
.add_node(hotel_assistant)
.add_edge(START, "flight_assistant")
.compile()
)
# 멀티 에이전트 그래프 실행
for chunk in multi_agent_graph.stream(
{
"messages": [
{
"role": "user",
"content": "book a flight from BOS to JFK and a stay at McKittrick Hotel"
}
]
}
):
print(chunk)
print("\n")참고
이 핸드오프 구현은 다음을 가정합니다:
- 각 에이전트가
MessagesState를 사용합니다- 핸드오프는 부모 그래프의 노드 간에 발생합니다
- 도구 메시지가 상태의 메시지 목록에 추가됩니다
LangGraph 슈퍼바이저 및 스웜 문서를 확인하여 핸드오프를 사용자 정의하는 방법을 알아보세요.
주요 개념
Command 객체
Command 객체는 제어 흐름과 상태 업데이트를 동시에 처리할 수 있게 해줍니다:
goto: 이동할 대상 노드(에이전트)update: 상태에 적용할 업데이트graph: 이동할 그래프 지정(Command.PARENT는 부모 그래프를 의미)
InjectedState
InjectedState 어노테이션을 사용하면 런타임에 도구 함수에 현재 그래프 상태를 주입할 수 있습니다. 이를 통해 도구가 현재 상태에 접근하여 의사결정을 내리거나 상태를 업데이트할 수 있습니다.
에이전트 간 통신
멀티 에이전트 시스템에서 에이전트는 다음과 같은 방식으로 통신합니다:
- 직접 핸드오프: 에이전트가 핸드오프 도구를 호출하여 다른 에이전트로 직접 제어권을 넘김
- 슈퍼바이저를 통한 라우팅: 슈퍼바이저가 다음에 실행할 에이전트를 결정
- 메시지 공유: 모든 에이전트가 공유 메시지 목록을 통해 컨텍스트를 공유