Multi-agent¶
单个代理可能难以胜任需要专精多个领域或管理多种工具的任务。为了解决这个问题,你可以将你的代理分解成更小、更独立的代理,并将它们组合成一个 multi-agent system。
在多代理系统中,代理之间需要进行通信。它们通过 handoffs 进行通信——这是一个原始操作,用于描述将控制权交给哪个代理以及要发送给该代理的载荷(payload)。
两种最流行的多代理架构是:
- supervisor — 单个代理由一个集中的 supervisor 代理协调。Supervisor 控制所有通信流程和任务委派,并根据当前上下文和任务要求决定调用哪个代理。
- swarm — 代理根据其专长动态地将控制权交给彼此。系统会记住哪个代理是最后活动的,以确保在后续交互中,会话能与该代理恢复。
Supervisor¶
使用 langgraph-supervisor
库来创建 supervisor 多代理系统:
API Reference: ChatOpenAI | create_react_agent | create_supervisor
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from langgraph_supervisor import create_supervisor
def book_hotel(hotel_name: str):
"""Book a hotel"""
return f"Successfully booked a stay at {hotel_name}."
def book_flight(from_airport: str, to_airport: str):
"""Book a flight"""
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
库来创建 swarm 多代理系统:
API Reference: create_react_agent | create_swarm | create_handoff_tool
from 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")
Handoffs¶
多代理交互中的一个常见模式是 handoffs,即一个代理将控制权“交接”给另一个代理。Handoffs 允许你指定:
- destination: 要导航到的目标代理
- payload: 要传递给该代理的信息
langgraph-supervisor
(supervisor 交接给单个代理)和 langgraph-swarm
(单个代理可以交接给其他代理)都使用此模式。
要使用 create_react_agent
实现 handoffs,你需要:
-
创建一个可以转移控制权给另一个代理的特殊工具
-
创建具有 handoff 工具访问权限的单个代理:
-
定义一个包含单个代理作为节点的父图:
综上所述,你可以通过以下方式实现一个简单的多代理系统,包含两个代理——一个航班预订助手和一个酒店预订助手:
API Reference: tool | InjectedToolCallId | create_react_agent | InjectedState | StateGraph | START | Command
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)!
goto=agent_name, # (3)!
update={"messages": state["messages"] + [tool_message]}, # (4)!
graph=Command.PARENT, # (5)!
)
return handoff_tool
# Handoffs
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.",
)
# Simple agent tools
def book_hotel(hotel_name: str):
"""Book a hotel"""
return f"Successfully booked a stay at {hotel_name}."
def book_flight(from_airport: str, to_airport: str):
"""Book a flight"""
return f"Successfully booked a flight from {from_airport} to {to_airport}."
# Define agents
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"
)
# Define multi-agent graph
multi_agent_graph = (
StateGraph(MessagesState)
.add_node(flight_assistant)
.add_node(hotel_assistant)
.add_edge(START, "flight_assistant")
.compile()
)
# Run the multi-agent graph
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")
- Access agent's state
- The
Command
primitive allows specifying a state update and a node transition as a single operation, making it useful for implementing handoffs. - Name of the agent or node to hand off to.
- Take the agent's messages and add them to the parent's state as part of the handoff. The next agent will see the parent state.
- Indicate to LangGraph that we need to navigate to agent node in a parent multi-agent graph.
Note
This handoff implementation assumes that:
- each agent receives overall message history (across all agents) in the multi-agent system as its input
- each agent outputs its internal messages history to the overall message history of the multi-agent system
Check out LangGraph supervisor and swarm documentation to learn how to customize handoffs.