AIエージェント入門

【2026年最新】LangGraph 1.1完全ガイド|v2移行手順

【2026年最新】LangGraph 1.1完全ガイド|v2移行手順

この記事の結論

LangGraph 1.1の最大変更点「version="v2"」を徹底解説。StreamPart型安全ストリーミング・GraphOutput・Pydantic連携をコード例つきで全公開。v1.0からの移行手順も完全網羅。

この記事でわかること: LangGraph 1.1(2026年3月10日リリース)の最大変更点は version="v2" の導入です。ストリーミング出力が強く型付けされた StreamPart を返すようになり、invoke()GraphOutput オブジェクトを返します。既存コードへの影響はゼロ(デフォルトは version="v1")、段階的に移行できます。

  • v1.0→v1.1の変更点と version="v2" の使い方をコード例つきで解説
  • StateGraph定義からPydantic連携・型安全ストリーミングまでの完全実装手順
  • CrewAI・Pydantic AI・OpenAI Agents SDKとの用途別比較と選定基準

対象読者: LangGraph v1.0を使っているPython開発者。v2への移行を検討しているエンジニア。

今日やること: pip install langgraph --upgrade で1.1に更新し、この記事の移行コードを手元で動かす。

「ストリーミングの戻り値を型チェックしようとしたら、タプルのアンパックが面倒で諦めた」

LangGraph v1.0を使い込んでいる開発者から、特によく聞く悩みです。stream() が返す (stream_mode, data) タプルは柔軟である反面、型アノテーションをきちんとつけようとすると途端に記述量が増える。エディタの補完も効きにくい。Pydanticで定義した状態スキーマが、出力ではただの dict になって返ってくる——。

LangGraph 1.1は、この問題に対する明確な答えを持っています。version="v2" という1つのオプションを渡すだけで、ストリーム出力が強く型付けされた StreamPart に変わります。invoke() の戻り値も GraphOutput オブジェクトになり、Pydanticモデルで定義した状態がそのまま型付きで返ってきます。

この記事では、1.1の全変更点をコピペ可能なコード例とともに解説します。移行の「どこから手をつけるか」も含め、順を追って説明します。

LangGraphの設計思想や基本的なグラフ構造については、AIエージェント構築完全ガイドで詳しくまとめています。

まず試したい「5分即効」セットアップ3選

即効テクニック1:1.1へのアップグレードと動作確認

まずインストールして、バージョンを確認します。

# アップグレード
pip install langgraph --upgrade

# バージョン確認
python -c "import langgraph; print(langgraph.__version__)"
# → 1.1.x が表示されればOK

次に、既存コードが壊れていないことを確認します。version パラメータを渡さなければ、動作は完全に従来通りです。

"""
動作環境: Python 3.10+, langgraph>=1.1.0, langchain-anthropic>=0.3.0
必要パッケージ: pip install langgraph langchain-anthropic python-dotenv
注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
"""
from typing import TypedDict, Annotated
import operator
from langgraph.graph import StateGraph, END

# 状態スキーマ(TypedDict形式 — v1.0と同じ書き方)
class AgentState(TypedDict):
    messages: Annotated[list, operator.add]
    step_count: int

def process_node(state: AgentState) -> AgentState:
    return {
        "messages": [f"処理済み: ステップ{state['step_count']}"],
        "step_count": state["step_count"] + 1
    }

builder = StateGraph(AgentState)
builder.add_node("process", process_node)
builder.set_entry_point("process")
builder.add_edge("process", END)
graph = builder.compile()

# v1 呼び出し(デフォルト — 既存コードはそのまま動く)
result = graph.invoke({"messages": [], "step_count": 0})
print(result)  # {'messages': ['処理済み: ステップ0'], 'step_count': 1}

動作環境: Python 3.10+, langgraph 1.1.0
最終確認日: 2026-03-16

即効テクニック2:version=”v2″ でGraphOutputを受け取る

version="v2" を渡すだけで、戻り値が GraphOutput オブジェクトに変わります。.value に出力、.interrupts に中断情報が格納されます。

"""
動作環境: Python 3.10+, langgraph>=1.1.0
必要パッケージ: pip install langgraph
注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
"""
from langgraph.types import GraphOutput

# version="v2" を渡すだけ
result_v2 = graph.invoke(
    {"messages": [], "step_count": 0},
    version="v2"  # ← これだけ追加
)

# GraphOutput オブジェクトが返ってくる
assert isinstance(result_v2, GraphOutput)

# 出力値
print(result_v2.value)
# → {'messages': ['処理済み: ステップ0'], 'step_count': 1}

# 割り込み情報(Human-in-the-loop等で使用)
print(result_v2.interrupts)
# → ()  通常は空タプル

# Pydantic モデルの場合は自動で型変換される(後述)

ポイント: GraphOutput は後方互換のため dict-style アクセス(result_v2["messages"])も一応できますが、v3.0で廃止予定です。今から .value / .interrupts を使う習慣をつけておきましょう。

即効テクニック3:型安全ストリーミング(StreamPart)

ストリーミングでも同様に version="v2" を渡すと、各チャンクが StreamPart 型になります。part["type"] でモードを判別できるため、エディタ補完と型チェックが完全に機能します。

"""
動作環境: Python 3.10+, langgraph>=1.1.0
必要パッケージ: pip install langgraph
注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
"""
from langgraph.types import ValuesStreamPart, UpdatesStreamPart

for part in graph.stream(
    {"messages": [], "step_count": 0},
    stream_mode=["values", "updates"],
    version="v2"  # ← 型付きStreamPartが返ってくる
):
    # part["type"] でモードを判別(discriminated union)
    if part["type"] == "values":
        # ValuesStreamPart: グラフ状態全体のスナップショット
        print(f"状態: {part['data']}")
    elif part["type"] == "updates":
        # UpdatesStreamPart: ノードの差分更新
        print(f"更新: {part['data']}")

# v1との比較(参考)
# v1: for mode, data in graph.stream(..., stream_mode=["values", "updates"]):
# v2: for part in graph.stream(..., version="v2"):  → part["type"]で判別

ポイント: langgraph.types から ValuesStreamPartUpdatesStreamPartMessagesStreamPart 等を個別にインポートできます。型チェッカー(mypy/pyright)との相性が大幅に改善されます。

v1.0→v1.1の変更点を3つの切り口で整理する

LangGraph 1.1の変更は大きく3つに分類できます。

変更カテゴリ v1.0の動作 v1.1の追加(version=”v2″) 後方互換性
invoke() の戻り値 dict GraphOutput(.value + .interrupts) あり(v1デフォルト継続)
stream() の出力型 (mode, data) タプル or data 型付き StreamPart(discriminated union) あり(version=”v1″継続)
Pydantic/dataclass出力 常に dict に変換 宣言した型のまま返す あり(opt-in)
Interrupt管理 dict["__interrupt__"] GraphOutput.interrupts(タプル) あり(dict-accessは非推奨)
バグ修正: time travel サブグラフ復元に不具合あり 修正済み(RESUME値の再利用を防止) 影響なし(バグ修正)

Pydanticモデルを使った型安全グラフの実装例

v1.1の恩恵が最も大きいのは、状態スキーマにPydanticモデルを使っているケースです。TypedDict だと invoke() の結果が常に dict で返ってきましたが、version="v2" を使うと宣言した型のまま返ってきます。

Pydanticモデルで状態スキーマを定義する

"""
動作環境: Python 3.10+, langgraph>=1.1.0, pydantic>=2.0
必要パッケージ: pip install langgraph pydantic langchain-anthropic
注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
"""
from typing import Annotated
import operator
from pydantic import BaseModel, Field
from langgraph.graph import StateGraph, END
from langgraph.types import GraphOutput

# Pydanticモデルで状態スキーマを定義
class AnalysisState(BaseModel):
    query: str
    steps: Annotated[list[str], operator.add] = Field(default_factory=list)
    final_answer: str = ""
    confidence: float = 0.0

def analyze_node(state: AnalysisState) -> dict:
    # ノードはdictを返すだけでOK(LangGraphが型変換を処理)
    return {
        "steps": [f"クエリ分析: {state.query}"],
        "confidence": 0.85
    }

def summarize_node(state: AnalysisState) -> dict:
    return {
        "final_answer": f"分析完了: {state.query}(信頼度{state.confidence:.0%})",
        "steps": ["要約生成完了"]
    }

builder = StateGraph(AnalysisState)
builder.add_node("analyze", analyze_node)
builder.add_node("summarize", summarize_node)
builder.set_entry_point("analyze")
builder.add_edge("analyze", "summarize")
builder.add_edge("summarize", END)
graph = builder.compile()

# version="v2" を使うと AnalysisState 型のまま返ってくる
result: GraphOutput = graph.invoke(
    AnalysisState(query="LangGraph 1.1の新機能を教えて"),
    version="v2"
)

# result.value は AnalysisState インスタンス(dict ではない!)
state_out: AnalysisState = result.value
print(f"回答: {state_out.final_answer}")
print(f"信頼度: {state_out.confidence}")
print(f"ステップ数: {len(state_out.steps)}")

# エディタ補完・型チェッカーが完全に機能する

ポイント: ノード関数は従来通り dict を返すだけでOKです。LangGraphが AnalysisState への変換を自動で行います。型の整合性チェックはPydanticが担当するため、フィールドの型ミスが実行前に検出できます。

非同期ストリーミングの型安全実装

"""
動作環境: Python 3.10+, langgraph>=1.1.0
必要パッケージ: pip install langgraph
注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
"""
import asyncio
from langgraph.types import MessagesStreamPart

async def stream_agent():
    async for part in graph.astream(
        AnalysisState(query="AIエージェントのベストプラクティスは?"),
        stream_mode="messages",
        version="v2"
    ):
        if part["type"] == "messages":
            # MessagesStreamPart 型が保証される
            for msg_chunk in part["data"]:
                print(msg_chunk.content, end="", flush=True)
        elif part["type"] == "values":
            # 状態スナップショット
            current_state: AnalysisState = part["data"]
            print(f"n[状態更新] 信頼度: {current_state.confidence}")

asyncio.run(stream_agent())

Human-in-the-Loopとinterruptsの扱いが変わる

v1.0では invoke() が中断するとき、戻り値の dict["__interrupt__"] キーに割り込み情報が入っていました。v1.1の version="v2" では GraphOutput.interrupts として明示的に分離されます。

"""
動作環境: Python 3.10+, langgraph>=1.1.0
必要パッケージ: pip install langgraph
注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
"""
from langgraph.types import interrupt, GraphOutput

def review_node(state: AgentState) -> AgentState:
    # Human-in-the-Loopの中断ポイント
    user_input = interrupt("この内容で送信してよいですか?(yes/no)")
    if user_input == "no":
        return {"messages": ["送信をキャンセルしました"]}
    return {"messages": ["送信しました"]}

# v1.0 の中断確認方法(非推奨になる予定)
result_v1 = graph.invoke(state)
if "__interrupt__" in result_v1:
    print("中断あり:", result_v1["__interrupt__"])

# v1.1(version="v2")の中断確認方法(推奨)
result_v2: GraphOutput = graph.invoke(state, version="v2")
if result_v2.interrupts:
    # タプル型で型安全に扱える
    for intr in result_v2.interrupts:
        print(f"中断: {intr.value}")

LangGraph vs 競合フレームワーク — 2026年の用途別選定基準

観点 LangGraph 1.1 CrewAI(45,900+ stars) Pydantic AI OpenAI Agents SDK v0.10.2
設計思想 グラフ制御フロー ロールベースマルチエージェント 型安全ファースト シンプル4プリミティブ
向いているユースケース 複雑な制御フロー、Human-in-the-Loop 複数エージェントの協調・役割分担 型安全が最重要な本番システム OpenAIエコシステム完結
学習コスト 中〜高(グラフ概念の理解が必要) 低〜中(直感的なAPI) 中(Pydantic知識が前提) 低(4プリミティブのみ)
型安全性(v1.1) v2で大幅強化 中程度 非常に高い 中程度
LangChain統合 ネイティブ 対応あり 独立 独立
月次ダウンロード(2026年3月時点) 約3,900万(LangGraph本体) 非公開 急成長中 OpenAI公式SDK経由

選定の目安:

  • LangGraph 1.1: ステートフルなマルチステップ処理、承認フロー入り自動化、LangChain既存資産の活用
  • CrewAI: 複数のAIエージェントに異なる役割を持たせて協調させたい
  • Pydantic AI: 型安全性を最優先にした小〜中規模の本番エージェント
  • OpenAI Agents SDK: OpenAIモデル中心の手軽なエージェント構築

各フレームワークの詳細な比較は、CrewAI vs LangGraph vs AutoGen比較記事も参照してください。

よくある移行エラーと解決策

エラー1:GraphOutputをdictとして扱おうとしてKeyError

version="v2" に切り替えた直後に最もよく踏む落とし穴です。

result = graph.invoke(state, version="v2")

# ❌ よくある間違い(v1スタイルのdictアクセス)
messages = result["messages"]  # KeyError!

# ⭕ 正しいアクセス方法
messages = result.value["messages"]  # dictの場合
# または状態がPydanticモデルの場合
messages = result.value.messages

なぜこれが重要か: GraphOutput は後方互換のため dict-style アクセスをサポートしていますが、deprecation警告が出ます。今のうちに .value 経由に統一しておくことで、v3.0への移行コストを最小化できます。

エラー2:stream_mode未指定でStreamPartのtypeが想定外

# ❌ stream_modeを指定しないとデフォルト"values"のみ
for part in graph.stream(state, version="v2"):
    print(part["type"])  # "values" だけ返ってくる

# ⭕ 複数モードを取得したい場合は明示的にリストで指定
for part in graph.stream(
    state,
    stream_mode=["values", "updates", "messages"],
    version="v2"
):
    if part["type"] == "values":
        ...
    elif part["type"] == "updates":
        ...
    elif part["type"] == "messages":
        ...

エラー3:Pydanticモデルの状態でノード関数がdictではなくインスタンスを返している

# ❌ ノード関数でPydanticインスタンスを返すとマージエラー
def bad_node(state: AnalysisState) -> AnalysisState:
    return AnalysisState(query=state.query, confidence=0.9)  # NG

# ⭕ ノード関数は更新フィールドのdictだけを返す
def good_node(state: AnalysisState) -> dict:
    return {"confidence": 0.9}  # LangGraphが自動マージ

なぜこれが重要か: LangGraphの状態管理は「差分マージ」が基本です。インスタンス全体を返すと、指定していないフィールドが上書きされてしまいます。

エラー4:langgraph-prebuilの非互換(既知の問題)

# langgraph 1.1 + 古いlanggraph-prebuilt が原因でエラーになる場合
pip install langgraph --upgrade langgraph-prebuilt --upgrade

# バージョン確認
pip show langgraph langgraph-prebuilt
# langgraph >= 1.1.0
# langgraph-prebuilt >= 0.1.x (対応バージョン)

langgraph-prebuilt==1.0.2 以前には、バージョン制約が適切に設定されていない問題がありました(Issue #6363)。アップグレード後に動作がおかしい場合は、langgraph-prebuilt も合わせてアップデートしてください。

段階的移行のロードマップ(30-60-90日)

v1.1への移行は一気にやる必要はありません。以下のステップで段階的に進めましょう。

時期 やること 優先度
今日(30分) pip install langgraph --upgrade → テスト環境で既存コードが動くことを確認 必須
今週(2-4時間) 新規コードから version="v2" を使い始める。GraphOutput.value / .interrupts に慣れる 推奨
今月(継続作業) 状態スキーマをPydanticに移行。既存の dict["__interrupt__"]GraphOutput.interrupts に置き換え。mypy/pyrightでの型チェックを追加 任意

セキュリティと運用上の注意点

LangGraph 1.1を本番導入するにあたって、押さえておくべき安全設計のポイントをまとめます。

プロンプトインジェクション対策

"""
動作環境: Python 3.10+, langgraph>=1.1.0
注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
"""
import re

def sanitize_input(user_text: str) -> str:
    """ユーザー入力のサニタイゼーション"""
    # システムプロンプトを上書きしようとするパターンをブロック
    dangerous_patterns = [
        r"ignore previous instructions",
        r"you are now",
        r"system:",
        r"",  # EOS トークンの挿入を防ぐ
    ]
    for pattern in dangerous_patterns:
        if re.search(pattern, user_text, re.IGNORECASE):
            raise ValueError(f"不正な入力が検出されました: {pattern}")
    return user_text[:2000]  # 入力長の上限設定

def input_node(state: AgentState) -> dict:
    safe_input = sanitize_input(state["messages"][-1])
    return {"messages": [safe_input]}

APIキーの安全な管理

"""
APIキーはハードコードせず、環境変数またはSecretsManagerを使う
"""
import os
from dotenv import load_dotenv

load_dotenv()  # .env ファイルから読み込み

# ❌ NG: ハードコード
# ANTHROPIC_API_KEY = "sk-ant-..."

# ⭕ 推奨: 環境変数
ANTHROPIC_API_KEY = os.environ.get("ANTHROPIC_API_KEY")
if not ANTHROPIC_API_KEY:
    raise EnvironmentError("ANTHROPIC_API_KEY が設定されていません")

コスト管理:再帰制限の設定

config = {
    "recursion_limit": 25,      # ノードの最大実行回数(デフォルト25)
    "configurable": {
        "thread_id": "session-001"  # チェックポイント管理用
    }
}

result = graph.invoke(state, config=config, version="v2")

再帰制限を超えると GraphRecursionError が発生します。無限ループの防止とコスト管理の両方に機能します。本番では25〜50が一般的な設定値です。

参考・出典

まとめ:今日から始める3つのアクション

LangGraph 1.1の最大のポイントは「既存コードを壊さずに型安全性を追加できる」設計です。version="v2" というたった1つのパラメータで、ストリーム出力が型付きになり、Pydanticモデルの状態がそのまま返ってきます。

  1. 今日: pip install langgraph --upgrade で1.1に更新し、テスト環境で既存コードが動くことを確認する。動作確認には即効テクニック1のコードをそのまま使えます。
  2. 今週中: 新規に書くコードから version="v2" を使い始める。result.value / result.interrupts のアクセスパターンに慣れる。
  3. 今月中: 状態スキーマをPydanticモデルに移行し、mypyまたはpyrightで型チェックを通す環境を整える。Human-in-the-Loopの __interrupt__ アクセスを GraphOutput.interrupts に置き換える。

あわせて読みたい:


著者: 佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。X(@SuguruKun_ai)フォロワー10万人超。
100社以上の企業向けAI研修・導入支援。著書累計3万部突破。
SoftBank IT連載7回執筆(NewsPicks最大1,125ピックス)。

ご質問・ご相談は お問い合わせフォーム からお気軽にどうぞ。

関連記事: Agents SDKか、LangGraphか|2026年のフレームワーク選定指針

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年3月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事