動作確認環境
本記事のコマンドは Ubuntu 24.04 LTS(Noble Numbat)と Python 3.12 で検証しています。Ubuntu 22.04 でも動作しますが、デフォルト Python が 3.10 系になるため、仮想環境の作り方が若干異なります。
LLMを使ったAIアプリを作っていると、「会話の流れをグラフ構造で管理したい」「エージェントが条件に応じて処理を分岐させたい」という場面が出てきます。そんなときに使いたいのが LangGraph です。
LangGraphはPythonライブラリで、AIエージェントの処理フローを「ノード」と「エッジ」からなる有向グラフとして定義できます。会話の状態(State)をグラフ上に乗せて引き回すため、マルチターンの会話やループ処理、条件分岐を自然に実装できます。本記事では、Ubuntu 24.04 + Python 3.12 の環境で実際にインストールし、ステートフルAIエージェントを動かすところまでを実測データ付きで解説します。
この記事のポイント
- LangGraph 1.2.5 を Ubuntu 24.04 / Python 3.12 の仮想環境にインストールする手順(実測ログ付き)
StateGraphでノード・エッジを定義し、基本的なエージェントグラフを実装するadd_conditional_edgesで「条件付き分岐ループ」を実装するMemorySaverによるスレッドID単位の状態永続化を実測で確認- よくあるインストールエラーと解決策
目次
- LangGraph とは何か
- 動作確認済み環境
- インストール手順
- 最初の StateGraph を作る
- 条件付き分岐を実装する
- MemorySaver で状態を永続化する
- よくあるエラーと解決策
- まとめ
LangGraph とは何か
LangGraphは LangChain が開発しているOSSのPythonライブラリで、AIエージェントの処理フローを有向グラフ(DAG)として定義・実行するフレームワークです。
従来の LangChain の Chain は「直線的な処理」しか表現できませんでした。LangGraphでは、処理の流れをノードとエッジで構造化することで、次のようなケースを自然に実装できます。
- LLMの出力に応じて次のノードを切り替える(条件分岐)
- 「考える→行動→評価→考え直す」というループ処理
- マルチエージェント(複数のLLMが協調して働く)アーキテクチャ
- スレッドIDごとに会話状態を保持するチェックポイント機能
LangGraphの核となる概念は3つです。
| 概念 | 役割 | 実装方法 |
|---|---|---|
| State | グラフ全体で共有されるデータ構造 | TypedDict で型定義 |
| Node | State を受け取り、加工して返す処理単位 | Python 関数 |
| Edge | ノード間の接続(固定 or 条件付き) | add_edge / add_conditional_edges |

動作確認済み環境
| 項目 | バージョン | 備考 |
|---|---|---|
| OS | Ubuntu 24.04.4 LTS (Noble Numbat) | Docker公式イメージ ubuntu:24.04 で実測 |
| Python | 3.12.13 | python:3.12-slim イメージ(apt デフォルトは 3.12.3) |
| pip | 25.0.1 | |
| langgraph | 1.2.5 | 2026-06-13 時点の最新安定版 |
| langchain-core | 1.4.7 | langgraph の依存パッケージとして自動インストール |
| langgraph-checkpoint | 4.1.1 | MemorySaver 等の Checkpointer を含む |
インストール手順
手順1:Python仮想環境を作成する
LangGraphはいくつかの依存パッケージを引き込むため、システムのPythonを汚さないよう仮想環境を使うことを強くおすすめします。Ubuntu 24.04 には python3-venv が標準で入っています。
Python 3.12.3
$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv) $
プロンプトの先頭に (.venv) が付いたら仮想環境が有効化されています。
注意
python3-venv が入っていない場合は sudo apt install python3-venv でインストールしてください。Ubuntu 24.04 ではデフォルトで含まれています。
手順2:LangGraphをインストールする
仮想環境内で pip install langgraph を実行します。
Collecting langgraph
Downloading langgraph-1.2.5-py3-none-any.whl (122 kB)
Collecting langchain-core>=0.3.27
Collecting langgraph-checkpoint>=4.0.0
Collecting langgraph-sdk>=0.1.42
Collecting pydantic>=2.7.4
Successfully installed langgraph-1.2.5 langchain-core-1.4.7 …
インストール後に pip show langgraph でバージョンを確認します。
Name: langgraph
Version: 1.2.5
Summary: Building stateful, multi-actor applications with LLMs
License-Expression: MIT
Requires: langchain-core, langgraph-checkpoint, langgraph-prebuilt, pydantic

Version: 1.2.5 が表示されれば準備完了です。依存パッケージとして langchain-core 1.4.7・langgraph-checkpoint 4.1.1・pydantic 2.13.4 が自動で入ります。
最初の StateGraph を作る
LangGraphの基本的な使い方を、シンプルな3ノードグラフで確認します。「StateGraph」はLangGraphの中心的なクラスで、グラフの構造を定義し、コンパイルして実行します。
①ステート(State)を定義する
まず処理全体で共有するデータ構造 State を TypedDict で定義します。
from langgraph.graph import StateGraph, END
import operator
class AgentState(TypedDict):
messages: Annotated[list, operator.add] # メッセージリスト(累積)
counter: int # ループカウンター
Annotated[list, operator.add] は「この値を更新するときは append ではなく operator.add(リスト結合)を使う」という LangGraph 向けの宣言です。複数のノードからメッセージを追加していく際に便利です。
②ノード関数を定義する
各ノードは「State を受け取り、更新した State を返す」Python 関数です。
return {“messages”: [“[init] エージェント初期化完了”], “counter”: 1}
def node_process(state: AgentState) -> AgentState:
return {“messages”: [f”[process] 処理 {state[‘counter’]} 回目”], “counter”: state[“counter”] + 1}
def node_end(state: AgentState) -> AgentState:
return {“messages”: [“[end] 完了”], “counter”: state[“counter”]}
③グラフを組み立てて実行する
builder.add_node(“init”, node_init)
builder.add_node(“process”, node_process)
builder.add_node(“end”, node_end)
builder.set_entry_point(“init”)
builder.add_edge(“init”, “process”)
builder.add_edge(“process”, “end”)
builder.add_edge(“end”, END)
graph = builder.compile()
result = graph.invoke({“messages”: [], “counter”: 0})
print(result[“messages”])
条件付き分岐を実装する
LangGraphの真価は 条件付きエッジ(conditional_edges) を使ったループ処理にあります。「思考→実行→評価→思考」という ReAct パターンや、LLMの出力に基づく動的ルーティングを実現できます。
実際に実行した結果を見てみましょう。think ノードが counter < 3 の間はループし、3に達したら act ノードに遷移します。

from langgraph.graph import StateGraph, END
import operator
class AgentState(TypedDict):
messages: Annotated[list, operator.add]
counter: int
def node_init(state: AgentState) -> AgentState:
return {“messages”: [“[init] エージェント初期化完了”], “counter”: 1}
def node_think(state: AgentState) -> AgentState:
return {“messages”: [f”[think] 思考ステップ {state[‘counter’]} 実行”],
“counter”: state[“counter”] + 1}
def node_act(state: AgentState) -> AgentState:
return {“messages”: [“[act] アクション実行 → 結果を返す”], “counter”: state[“counter”]}
def should_continue(state: AgentState) -> str:
if state[“counter”] < 3:
return “think” # ループ継続
return “act” # ループ終了 → act へ
builder = StateGraph(AgentState)
builder.add_node(“init”, node_init)
builder.add_node(“think”, node_think)
builder.add_node(“act”, node_act)
builder.set_entry_point(“init”)
builder.add_edge(“init”, “think”)
builder.add_conditional_edges(“think”, should_continue,
{“think”: “think”, “act”: “act”})
builder.add_edge(“act”, END)
graph = builder.compile()
result = graph.invoke({“messages”: [], “counter”: 0})
実行してみると、次の出力が得られます。
LangGraph version: 1.2.5
==================================================
[init] エージェント初期化完了
[think] 思考ステップ 1 実行
[think] 思考ステップ 2 実行
[act] アクション実行 → 結果を返す
最終カウンター: 3
==================================================

think ノードが counter=1→2→3 と2回ループし、3になった時点で should_continue 関数が "act" を返して act ノードに遷移しているのがわかります。
また、グラフ構造は graph.get_graph().draw_mermaid() で確認できます。
graph TD;
__start__ –> init;
init –> think;
think -.–> act; <!– 条件付きエッジは点線で表示 –>
act –> __end__;
think -.–> think; <!– ループエッジ –>

MemorySaver で状態を永続化する
LangGraphのもう一つの重要機能が「チェックポイント(Checkpointer)」です。スレッドID単位でグラフの状態(State)を保存・復元でき、マルチターンの会話継続が可能になります。
最もシンプルな実装として MemorySaver があります。その名の通りメモリ上に保存するため、プロセス再起動で消えますが、開発・テスト用途では十分です。
checkpointer = MemorySaver()
graph = builder.compile(checkpointer=checkpointer) # compileにcheckpointerを渡す
# thread_id を指定して invoke する
config = {“configurable”: {“thread_id”: “session-001”}}
# 1回目の呼び出し
r1 = graph.invoke({“messages”: [“こんにちは”]}, config=config)
# 2回目(同じ thread_id → 状態が継続される)
r2 = graph.invoke({“messages”: [“次の質問です”]}, config=config)
print(f”メッセージ数: {len(r2[‘messages’])} 件”)
実際に実行して確認しました。
=== 1回目の呼び出し ===
こんにちは
エージェント: 「こんにちは」を受け取りました。処理中…
=== 2回目の呼び出し(同一スレッド・履歴継続) ===
メッセージ数: 4 件(前回の2件 + 今回の2件)
こんにちは
エージェント: 「こんにちは」を受け取りました。処理中…
次の質問です
エージェント: 「次の質問です」を受け取りました。処理中…
✓ MemorySaver による状態永続化確認完了
langgraph-checkpoint: 4.1.1

2回目の invoke 時に1回目のメッセージ(2件)が保持され、合計4件になっていることが確認できました。thread_id を変えると別セッションとして扱われ、履歴は引き継がれません。
よくあるエラーと解決策
①ModuleNotFoundError: No module named ‘langgraph’
仮想環境を source .venv/bin/activate で有効化した状態で pip install langgraph を実行してください。(.venv) がプロンプトに表示されていない場合、システムの Python にインストールされている可能性があります。
②TypeError: TypedDict with mutable default values
State に list や dict をそのまま書くとエラーになる場合があります。LangGraph の State では Annotated でリデューサー(更新方法)を明示的に指定するのが正しい書き方です。
✅ messages: Annotated[list, operator.add] # operator.add でリスト結合を指定
③InvalidUpdateError: Expected dict, got …
ノード関数の戻り値は必ず dict(State の一部または全体)を返す必要があります。state を直接 mutate して return state するのではなく、更新したいキーだけを含む新しい dict を返してください。
✅ return {“messages”: [“新メッセージ”]} # 更新したいキーだけ返す
まとめ
本記事では Ubuntu 24.04 + Python 3.12 環境に LangGraph 1.2.5 をインストールし、次のことを実測で確認しました。
- 仮想環境への
pip install langgraphで langchain-core・langgraph-checkpoint を含む依存パッケージが自動インストールされる StateGraphで TypedDict のステートを定義し、ノードとエッジを組み合わせてグラフを構築できるadd_conditional_edgesで Python 関数ベースの動的分岐・ループが実現できる(実測: think ノードが counter=1→2→3 とループし、3で act に遷移)MemorySaver+thread_idでセッション間の状態継続が動作する(実測: 2回目 invoke で前回の2件が保持され合計4件)
LangGraph はまだ v1 系で API の変更も多いライブラリですが、StateGraph のコアな設計は安定しています。本番では MemorySaver の代わりに SqliteSaver や PostgresSaver で永続化し、VPS 上にデプロイするのが一般的な流れです。
実際にVPSでLLMエージェントを動かす場合は、GPU付きのサーバーを選ぶと快適です。参考に下記もチェックしてみてください。



コメント