コンテンツにスキップ

05. Multi-agent / Subgraph

ゴール

  • 単一エージェントの限界を理解する
  • 専門家エージェントを組み合わせるパターンを2つ覚える: SupervisorHandoff (Swarm)
  • Subgraph で再利用可能な単位を作る

なぜ Multi-agent か

  • システムプロンプトが肥大化して LLM が指示を取りこぼす
  • ツールが20個を超えると LLM が選択ミスを起こす(Anthropic の調査 で言及)
  • ドメインごとに責務を分けた方が評価とデバッグが楽

パターン1: Supervisor(中央集権型)

「上司エージェント」が下位エージェントを呼び分ける。

        ┌─────────────┐
        │ supervisor  │
        └─────────────┘
         /     |     \
        ▼      ▼      ▼
   [researcher] [coder] [writer]
from langgraph.graph import StateGraph, START, END

def supervisor_node(state):
    """次にどの専門家を呼ぶか、または END するか決める"""
    resp = supervisor_llm.invoke(state["messages"] + [
        ("system", "次の担当を選んで: researcher / coder / writer / FINISH")
    ])
    return {"next": resp.content.strip()}

def researcher_node(state):
    return {"messages": [researcher_llm.invoke(state["messages"])]}

# ...同様に coder_node, writer_node

def route(state):
    return state["next"] if state["next"] != "FINISH" else END

builder = StateGraph(State)
builder.add_node("supervisor", supervisor_node)
builder.add_node("researcher", researcher_node)
builder.add_node("coder", coder_node)
builder.add_node("writer", writer_node)

builder.add_edge(START, "supervisor")
builder.add_conditional_edges("supervisor", route)
for name in ["researcher", "coder", "writer"]:
    builder.add_edge(name, "supervisor")

graph = builder.compile()

強み: 制御が明示的、ロギングが楽 弱み: supervisor がボトルネック、毎ターン LLM 呼び出しが増える

パターン2: Handoff / Swarm(分散型)

各エージェントが 自分で次の担当を指名する。

from langgraph.types import Command

def researcher_node(state) -> Command:
    resp = researcher_llm.invoke(state["messages"])
    if "needs_code" in resp.content:
        return Command(goto="coder", update={"messages": [resp]})
    return Command(goto=END, update={"messages": [resp]})

公式の langgraph-swarm ライブラリがこのパターン。

強み: 各 agent の自律性が高い、軽量 弱み: 制御フローが追いづらい、無限ループのリスク

パターン3: Subgraph(再利用可能な単位)

複雑なグラフを「グラフの中にグラフ」として埋め込む。

# 専門家サブグラフ
research_builder = StateGraph(ResearchState)
research_builder.add_node("search", search_node)
research_builder.add_node("summarize", summarize_node)
research_builder.add_edge(START, "search")
research_builder.add_edge("search", "summarize")
research_builder.add_edge("summarize", END)
research_graph = research_builder.compile()

# 親グラフに subgraph として組み込む
parent = StateGraph(MainState)
parent.add_node("research", research_graph)  # サブグラフをノード扱い
parent.add_node("write", write_node)
parent.add_edge(START, "research")
parent.add_edge("research", "write")

State の型が違う場合は変換関数で繋ぐ:

def research_subgraph_node(state: MainState) -> dict:
    sub_input = {"query": state["topic"]}
    result = research_graph.invoke(sub_input)
    return {"research_result": result["summary"]}

設計判断: いつ multi-agent にするか

状況 推奨
ツールが5個以下、ドメインが1つ single agent で十分
ツールが20個超 役割で分割(research / write / review)
並列処理したい(複数ソース調査) supervisor で fan-out / fan-in
エージェントごとに違うモデルを使いたい multi-agent(Sonnet で計画、Haiku で実行など)
評価・改善を独立にやりたい subgraph で切り出す

注意: 「multi-agent にすると賢くなる」は半分嘘。通信のオーバーヘッドで逆に劣化することも多い。 Anthropic の "Building effective agents" は「まずは単一 agent で十分か検討せよ」と言っている。

Try

  1. 「Web 調査 → 要約 → ブログ記事化」の3段 supervisor を組む
  2. 同じものを subgraph 構成で書き直し、コードの再利用性を比較
  3. researcher だけ Haiku に変えて、コスト/速度を測る
  4. langgraph-swarm を入れて handoff パターンの公式実装を読む

学んだこと

  • Multi-agent の主要パターンは Supervisor / Handoff / Subgraph
  • まずは single agent。複雑さに見合うコストかを毎回問う
  • Subgraph は再利用可能な単位を作る基本道具
  • Anthropic は「simple > complex」の立場

次は最終章 06_temporal_integration。Temporal の Activity の中で LangGraph を呼ぶ。


作成: 2026-05-16 / 最終更新: 2026-05-16