0Pricing
AI Engineering Academy · レッスン

LangGraphでマルチエージェントパイプラインを構築する

LangGraphでエージェントノード、条件付きエッジ、共有状態を有向グラフとして定義し、ループ、分岐、人間参加型のチェックポイントを備えた複雑なマルチエージェントワークフローを実現します。

「LangGraphでマルチエージェントパイプラインを構築する」はCoddyKit上の無料AI Engineering Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Engineering Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Engineering Academyコースには全4レッスンが含まれています。

LangGraphとは

LangGraphはLangChain上に構築されたライブラリで、マルチエージェントのワークフローを有向グラフとして定義できます。グラフのノードはエージェントまたは処理ステップを表し、エッジはノード間の状態の流れを表します。また、条件付きエッジを使うと、現在の状態に基づいて動的にルーティングできます。LangGraphは、実行エンジン、状態の永続化、人間参加型のチェックポイントを処理します。

# pip install langgraph
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator

# Define your shared state schema
class AgentState(TypedDict):
    messages: Annotated[list, operator.add]  # append-only list
    research: str
    draft: str
    status: str

LangGraphで状態を定義する

LangGraphのすべてのワークフローは、すべてのノードが読み書きできる共有状態オブジェクト上で動作します。状態は、グラフ内でデータを受け渡す型付き辞書(TypedDict)です。ノードが実行されると、現在の状態を受け取り、処理を行い、状態にマージする更新内容の辞書を返します。この共有状態モデルにより、エージェント同士を直接結合せずに通信できます。

from typing import TypedDict

class ResearchState(TypedDict):
    query: str           # input from user
    research_notes: str  # filled by researcher node
    written_draft: str   # filled by writer node
    review_feedback: str # filled by reviewer node
    final_output: str    # filled by synthesizer node
    iteration_count: int # tracks how many revision loops occurred

# Each node returns a PARTIAL update - only the keys it modifies
def researcher_node(state: ResearchState) -> dict:
    notes = do_research(state['query'])
    return {'research_notes': notes}  # only update this key

エージェントノードの作成

LangGraphでは、各エージェントは現在の状態を受け取り、LLMの呼び出しとツールの実行を行い、状態の更新内容を返すノード関数です。ノードは純粋関数であり、内部状態を保持しません。すべての状態が共有グラフ状態オブジェクトに格納されるため、ワークフローの確認、再開、デバッグが容易になります。

from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage

llm = ChatOpenAI(model='gpt-4o')

def researcher_node(state: ResearchState) -> dict:
    messages = [
        SystemMessage(content='You are a research specialist. Find accurate information.'),
        HumanMessage(content=f'Research this topic: {state["query"]}')
    ]
    response = llm.invoke(messages)
    return {'research_notes': response.content}

def writer_node(state: ResearchState) -> dict:
    messages = [
        SystemMessage(content='You are a technical writer. Write clear, engaging prose.'),
        HumanMessage(content=f'Write a draft using these notes:\n{state["research_notes"]}')
    ]
    response = llm.invoke(messages)
    return {'written_draft': response.content}

StateGraphでグラフを構築する

ノード関数を定義したら、StateGraphでそれらを接続します。graph.add_node()でノードを追加し、graph.add_edge()でノード間にエッジを追加し、graph.set_entry_point()でエントリーポイントを設定して、graph.compile()でグラフを実行可能な形式にコンパイルします。コンパイル済みグラフは、初期状態を受け取り、最終状態を返すRunnableです。

from langgraph.graph import StateGraph, END

# Build the graph
workflow = StateGraph(ResearchState)

# Add nodes
workflow.add_node('researcher', researcher_node)
workflow.add_node('writer', writer_node)
workflow.add_node('reviewer', reviewer_node)

# Add edges (sequential pipeline)
workflow.set_entry_point('researcher')
workflow.add_edge('researcher', 'writer')
workflow.add_edge('writer', 'reviewer')
workflow.add_edge('reviewer', END)

# Compile into an executable
app = workflow.compile()

# Run it
result = app.invoke({'query': 'What is RAG?', 'iteration_count': 0})
print(result['written_draft'])

動的ルーティングのための条件付きエッジ

条件付きエッジを使うと、現在の状態に基づいてグラフから別のノードへルーティングできます。固定されたエッジの代わりに、状態を調べて次のノード名を返すルーティング関数を指定します。これにより、改訂ループ、品質ゲート、人間による承認ステップ、エージェントの出力内容に基づく分岐を実現できます。

def should_revise(state: ResearchState) -> str:
    '''Router function: returns the name of the next node.'''
    if state['iteration_count'] >= 3:
        return 'finalize'  # Too many revisions - accept as is
    if 'insufficient' in state.get('review_feedback', '').lower():
        return 'researcher'  # Need more research
    if 'rewrite' in state.get('review_feedback', '').lower():
        return 'writer'  # Needs rewriting
    return 'finalize'  # Looks good

# Add conditional edge from reviewer
workflow.add_conditional_edges(
    'reviewer',                    # from node
    should_revise,                 # routing function
    {
        'researcher': 'researcher', # route name -> node name
        'writer': 'writer',
        'finalize': 'finalizer'
    }
)

LangGraphでのループと反復

LangGraphはループを標準でサポートしており、エージェントを複数回実行できます。これは、改訂サイクル、失敗時の再試行パターン、反復的な改善に不可欠です。無限ループを防ぐため、状態に必ずループの終了条件(反復回数のカウンターや品質スコアのしきい値など)を含め、条件付きエッジのルーターでその条件を適用してください。

def researcher_node(state: ResearchState) -> dict:
    notes = do_research(state['query'])
    return {
        'research_notes': notes,
        'iteration_count': state['iteration_count'] + 1  # always increment
    }

def should_continue_research(state: ResearchState) -> str:
    # Terminate loop after 3 iterations regardless of quality
    if state['iteration_count'] >= 3:
        return END
    # Continue if research is incomplete
    if len(state.get('research_notes', '')) < 500:
        return 'researcher'  # loop back
    return 'writer'  # proceed to next stage

ノードの並列実行

LangGraphでは、ノード内でRunnableParallelを使用するか、複数のノードへ分岐することで並列ブランチを利用できます。独立したサブタスクを同時に実行する必要がある場合は、1つのノードから複数の並列ノードへのファンアウトを作成し、その後、すべての処理を待って結果を共有状態に統合するファンインノードを配置できます。

# Fan-out: one node triggers multiple parallel ones
workflow.add_edge('planner', 'researcher_a')
workflow.add_edge('planner', 'researcher_b')
workflow.add_edge('planner', 'researcher_c')

# Fan-in: aggregator waits for all three
workflow.add_edge('researcher_a', 'aggregator')
workflow.add_edge('researcher_b', 'aggregator')
workflow.add_edge('researcher_c', 'aggregator')
workflow.add_edge('aggregator', 'writer')

# Aggregator merges parallel results
def aggregator_node(state: ResearchState) -> dict:
    combined = state.get('notes_a', '') + '\n' + state.get('notes_b', '') + '\n' + state.get('notes_c', '')
    return {'research_notes': combined}

チェックポイントと人間参加型処理

LangGraphは、チェックポインターのバックエンド(SQLite、Redis、PostgreSQL)と統合することでチェックポイントをサポートします。チェックポイントを有効にすると、各ノードの実行後にグラフの状態が永続化されます。これにより、長時間実行されるワークフローを一時停止して確認し、再開できます。また、特定のノードでグラフを一時停止し、人間が承認または入力を行ってから続行する人間参加型のパターンも利用できます。

from langgraph.checkpoint.sqlite import SqliteSaver

# Use SQLite for persistent checkpoints
checkpointer = SqliteSaver.from_conn_string(':memory:')
app = workflow.compile(checkpointer=checkpointer, interrupt_before=['human_review'])

# First run - pauses at human_review node
thread = {'configurable': {'thread_id': 'my-workflow-1'}}
result = app.invoke({'query': 'Analyze competitors'}, config=thread)
# result.next == 'human_review' -- waiting for human input

# Human provides feedback and resumes
app.update_state(thread, {'review_feedback': 'Good research, proceed with writing'})
final = app.invoke(None, config=thread)  # resume from checkpoint

LangGraphの出力をストリーミングする

LangGraphはストリーミングモードをサポートしており、ワークフロー全体の完了を待たずに、各ノードの完了時点で中間状態の更新を出力します。これは、ユーザーに進捗の一部を表示したい長いパイプラインで役立ちます。app.stream()を使用すると、各ステップの状態スナップショットを反復処理するイテレーターを取得できます。

# Stream intermediate results as each node completes
for event in app.stream({'query': 'What is RAG?'}):
    for node_name, node_output in event.items():
        print(f'Node completed: {node_name}')
        if 'research_notes' in node_output:
            print('Research done:', node_output['research_notes'][:100])
        if 'written_draft' in node_output:
            print('Draft done:', node_output['written_draft'][:100])

グラフを可視化する

LangGraphでは、グラフを描画してMermaid図にできます。これは、多数のノードや条件付きエッジを含む複雑なワークフローを理解するうえで非常に役立ちます。app.get_graph().draw_mermaid_png()を呼び出すとPNG画像を取得でき、app.get_graph().draw_mermaid()を呼び出すと、任意のMermaidレンダラーに貼り付けられるMermaid構文を取得できます。

# Visualize the workflow graph
graph_image = app.get_graph().draw_mermaid_png()
with open('workflow.png', 'wb') as f:
    f.write(graph_image)

# Or print Mermaid syntax
print(app.get_graph().draw_mermaid())
# Outputs:
# graph TD
#    __start__ --> researcher
#    researcher --> writer
#    writer --> reviewer
#    reviewer -->|Good| finalize
#    reviewer -->|Needs work| researcher

LangGraphエージェントのエンドツーエンド例

ここまでの内容をまとめると、完全なLangGraphマルチエージェントパイプラインでは、TypedDict状態を定義し、各エージェント用のノード関数を作成し、StateGraphで接続し、改訂ループ用の条件付きエッジを追加し、チェックポインター付きでコンパイルして、初期状態で呼び出します。これにより、最小限の定型コードで、堅牢で可観測性があり、再開可能なマルチエージェントワークフローを構築できます。

簡単な確認

このレッスンで学んだLangGraphのマルチエージェントパイプラインについて、理解度を確認しましょう。

レッスンのまとめ

このレッスンでは、LangGraphがマルチエージェントのワークフローを、ノードをエージェント、エッジを処理の流れとする有向グラフとして表現すること、条件付きエッジによって現在の状態に基づく動的ルーティング、ループ、改訂サイクルを実現できること、そしてチェックポイントによって長時間実行されるワークフローを一時停止・再開し、人間参加型の承認を組み込めることを学びました。次は、共有メモリとエージェント間通信について学びます。

よくある質問

「LangGraphでマルチエージェントパイプラインを構築する」レッスンは無料ですか?

はい。「LangGraphでマルチエージェントパイプラインを構築する」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Engineering Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Engineering Academyコースには全4レッスンが含まれています。

「LangGraphでマルチエージェントパイプラインを構築する」で何を学びますか?

LangGraphでエージェントノード、条件付きエッジ、共有状態を有向グラフとして定義し、ループ、分岐、人間参加型のチェックポイントを備えた複雑なマルチエージェントワークフローを実現します。 ブラウザで直接実行するハンズオンコードでAI Engineering Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

AI Engineering Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAI Engineering Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「LangGraphでマルチエージェントパイプラインを構築する」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAI Engineering Academyレッスンでコードを書いて実行できますか?

はい。すべてのAI Engineering Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 単一エージェントが行き詰まる理由
  2. オーケストレーター・サブエージェントパターン
  3. LangGraphでマルチエージェントパイプラインを構築する
  4. 共有メモリとエージェント間通信
← AI Engineering Academyに戻る