LangGraph : Prebuilt エージェント : マルチエージェント

単一のエージェントでは、複数のドメインに特化したり多くのツールを管理する必要がある場合、対応が難しいかもしれません。これに対処するには、エージェントを小さい、独立したエージェントに分割してマルチエージェント・システムに構成することができます。

LangGraph : Prebuilt エージェント : マルチエージェント

作成 : クラスキャット・セールスインフォメーション
作成日時 : 06/15/2025

* 本記事は langchain-ai.github.io の以下のページを独自に翻訳した上で、補足説明を加えてまとめ直しています :

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

LangGraph : Get started : Prebuilt エージェント : マルチエージェント

単一のエージェントでは、複数のドメインに特化したり多くのツールを管理する必要がある場合、対応が難しいかもしれません。これに対処するには、エージェントを小さい、独立したエージェントに分割して マルチエージェント・システム に構成することができます。

マルチエージェント・システムでは、エージェントはお互いに通信する必要があります。それらは ハンドオフ 経由でこれを行います – どのエージェントに制御を渡すか、そのエージェントに送信するペイロードを記述するプリミティブです。

最もポピュラーなマルチエージェント・アーキテクチャの 2 つは :

  • スーパーバイザー (supervisor) – 個々のエージェントは中央のスーパーバイザー・エージェントにより調整されます (coordinated)。スーパーバイザーはすべての通信フローとタスク委任を制御し、現在のコンテキストとタスク要件に基づいてどのエージェントを呼び出すか決定します。

  • swarm (群れ) – エージェントそれらの専門性に基づいて別のエージェントに制御を動的に渡します。システムはどのエージェントが最後にアクティブであったか記憶し、続くインタラクションでは、会話はそのエージェントから再開されることを保証します。

 

スーパーバイザー

langgraph-supervisor ライブラリを使用してスーパーバイザー・マルチエージェント・システムを作成します :

pip install langgraph-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 マルチエージェント・システムを作成します :

pip install langgraph-swarm
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")

 

ハンドオフ

マルチエージェント・インタラクションの一般的なパターンは ハンドオフ です、そこでは一つのエージェントが別のエージェントに制御を渡します。ハンドオフは以下を指定することを可能にします :

  • destination : 移動先のターゲットエージェント

  • payload : そのエージェントに渡す情報

これは langgraph-supervisor (スーパーバイザーが個々のエージェントにハンドオフ) と langgraph-swarm (個々のエージェントが他のエージェントにハンドオフ) の両方で使用されます。

create_react_agent でハンドオフを実装するには、以下が必要です :

  1. 制御を別のエージェントに移せる特別なツールを作成する
    def transfer_to_bob():
        """Transfer to bob."""
        return Command(
            # name of the agent (node) to go to
            goto="bob",
            # data to send to the agent
            update={"messages": [...]},
            # indicate to LangGraph that we need to navigate to
            # agent node in a parent graph
            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)
        ...
    )
    

これをまとめると、2 つのエージェント – フライト予約アシスタントとホテル予約アシスタント – を持つ単純なマルチエージェント・システムを実装する方法は以下のようなものです :

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], 
        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(  
            goto=agent_name,  
            update={"messages": state["messages"] + [tool_message]},  
            graph=Command.PARENT,  
        )
    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")

 

以上