この記事でわかること: 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 から ValuesStreamPart、UpdatesStreamPart、MessagesStreamPart 等を個別にインポートできます。型チェッカー(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が一般的な設定値です。
参考・出典
- LangGraph Releases(GitHub) — langchain-ai/langgraph(参照日: 2026-03-16)
- LangGraph 1.0 is now generally available — LangChain Changelog(参照日: 2026-03-16)
- langgraph · PyPI — PyPI公式パッケージページ(参照日: 2026-03-16)
- Breaking Change in langgraph-prebuilt==1.0.2 · Issue #6363 — langchain-ai/langgraph(参照日: 2026-03-16)
- StreamPart | langgraph_sdk — LangChain Reference(参照日: 2026-03-16)
まとめ:今日から始める3つのアクション
LangGraph 1.1の最大のポイントは「既存コードを壊さずに型安全性を追加できる」設計です。version="v2" というたった1つのパラメータで、ストリーム出力が型付きになり、Pydanticモデルの状態がそのまま返ってきます。
- 今日:
pip install langgraph --upgradeで1.1に更新し、テスト環境で既存コードが動くことを確認する。動作確認には即効テクニック1のコードをそのまま使えます。 - 今週中: 新規に書くコードから
version="v2"を使い始める。result.value/result.interruptsのアクセスパターンに慣れる。 - 今月中: 状態スキーマをPydanticモデルに移行し、mypyまたはpyrightで型チェックを通す環境を整える。Human-in-the-Loopの
__interrupt__アクセスをGraphOutput.interruptsに置き換える。
あわせて読みたい:
- AIエージェント構築完全ガイド — LangGraphを含む設計パターンの全体像
- CrewAI vs LangGraph vs AutoGen比較 — 用途別フレームワーク選定ガイド
著者: 佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。X(@SuguruKun_ai)フォロワー10万人超。
100社以上の企業向けAI研修・導入支援。著書累計3万部突破。
SoftBank IT連載7回執筆(NewsPicks最大1,125ピックス)。
ご質問・ご相談は お問い合わせフォーム からお気軽にどうぞ。