LangChain エージェント実装ガイド 2026 — 本番運用までの技術解説

2026年6月20日
14分で読めます

2026年6月20日
14分で読めます
LangChain エージェントHover to explore質問に答えるだけの LLM も役には立ちます。しかし 実際に動く LLM——データベースを検索し、Slack にメッセージを送り、返金処理を実行し、その結果を報告する——になると、それはプロダクトです。2026年、このループを組むための標準的な手段が LangChain エージェント です。本記事では、考え方から本番コードまでを一通り扱います。エージェントループ、ツールの書き方、メモリと状態、構造化出力、ストリーミング、エラー処理、そして r/LangChain、r/LocalLLaMA、X の開発者たちが「これは効く」「これは効かない」と語っている内容です。
本記事は LangChain v1 のエージェント公式ドキュメント、LangGraph のドキュメント、および r/LangChain と X の @LangChainAI で繰り返し交わされている議論にもとづいています。
どのモデルを使っても、LangChain エージェントは同じループを回します。
ToolMessage として会話に追加します。仕組みはこれだけです。差がつくのは、どんなツールを渡すか、ループをどう制約するか。フレームワークの内部に魔法があるわけではありません。
LangChain v1 の create_agent を使えば、定型コードはほとんど不要です。
from langchain.agents import create_agent
from langchain.tools import tool
@tool
def search_orders(order_id: str) -> str:
"""Look up an order by ID and return its current status."""
# Replace with your real DB call
return f"Order {order_id}: Shipped, arriving 2026-06-23."
@tool
def issue_refund(order_id: str, reason: str) -> str:
"""Issue a full refund for an order given a reason."""
return f"Refund issued for order {order_id}. Reason: {reason}."
agent = create_agent(
model="anthropic:claude-sonnet-4-6",
tools=[search_orders, issue_refund],
system_prompt=(
"You are a helpful customer support agent. "
"Always look up the order before issuing a refund."
),
)
result = agent.invoke({
"messages": [{"role": "user", "content": "Refund order #4821 — it arrived broken."}]
})
print(result["messages"][-1].content)
内部では、エージェントが search_orders("4821") を呼び、その結果を読み、続けて issue_refund("4821", "arrived broken") を呼び、最後に確認メッセージを返します。これがすべて invoke 1回のなかで完結し、手作業のオーケストレーションは要りません。
エージェントの品質を最も左右するのは、モデル選びではなくツール設計です。モデルは関数名、docstring、引数スキーマだけを見てどのツールを呼ぶかを決めます。ここを外すと、どれだけプロンプトを工夫しても取り返せません。
実務で通用するルール
search_and_refund() は罠です。分割してください。モデルが各ステップを独立して呼べる形にします。"Error: order not found" を返します。そうすればエージェントは再試行するか、失敗の理由を説明できます。落ちることはありません。from langchain.tools import tool
from pydantic import BaseModel, Field
class SearchInput(BaseModel):
order_id: str = Field(description="The numeric order ID, e.g. '4821'")
include_history: bool = Field(
default=False,
description="Set True to include the full shipment history"
)
@tool(args_schema=SearchInput)
def search_orders(order_id: str, include_history: bool = False) -> str:
"""
Look up an order's current status by order ID.
Call this FIRST before any action that modifies the order.
Returns: status string, or an error message if not found.
"""
try:
order = db.get_order(order_id)
if not order:
return f"Error: order {order_id} not found."
base = f"Order {order_id}: {order.status}, ETA {order.eta}."
if include_history:
base += f" History: {order.shipment_history}"
return base
except Exception as e:
return f"Error fetching order: {str(e)}"
既定では agent.invoke() はステートレスです。処理が終わった瞬間、エージェントは直前のやり取りを忘れます。複数ターンの会話を成立させるには、状態を明示的に渡す必要があります。LangChain には2つのパターンがあります。
パターン A — LangGraph によるスレッド単位のチェックポイント(本番推奨)
from langchain.agents import create_agent
from langgraph.checkpoint.memory import MemorySaver
# MemorySaver keeps state in RAM; swap for PostgresSaver in production
checkpointer = MemorySaver()
agent = create_agent(
model="anthropic:claude-sonnet-4-6",
tools=[search_orders, issue_refund],
checkpointer=checkpointer,
)
# Same thread_id = same conversation memory
config = {"configurable": {"thread_id": "user-123-session-456"}}
# Turn 1
agent.invoke(
{"messages": [{"role": "user", "content": "What is the status of order 4821?"}]},
config=config,
)
# Turn 2 — agent remembers turn 1
agent.invoke(
{"messages": [{"role": "user", "content": "Go ahead and refund it."}]},
config=config,
)
パターン B — 長い文脈のための要約
スレッドがモデルのコンテキストウィンドウを超えたら、SummarizationMiddleware を使います。モデル呼び出しのたびに、古いメッセージを累積要約へ自動的に圧縮します。逐語的な履歴は失われますが、意味は保たれます。サポートやアシスタント用途であれば、これで十分です。
自由記述の要約ではなく、検証済みのオブジェクトを返してほしい場面は少なくありません。response_format に Pydantic モデルを渡せば、同じループのなかで型付きオブジェクトが得られます。追加のパース処理は不要です。
from pydantic import BaseModel
from langchain.agents import create_agent
class SupportTicket(BaseModel):
order_id: str
issue_type: str # "refund" | "late_delivery" | "wrong_item"
recommended_action: str
confidence: float # 0.0 – 1.0
agent = create_agent(
model="anthropic:claude-sonnet-4-6",
tools=[search_orders],
response_format=SupportTicket,
system_prompt=(
"Classify the customer's issue and recommend an action. "
"Always search the order before classifying."
),
)
result = agent.invoke({"messages": [
{"role": "user", "content": "My order 4821 never arrived — it's been 3 weeks."}
]})
ticket: SupportTicket = result["structured_response"]
print(ticket.issue_type) # "late_delivery"
print(ticket.recommended_action) # "escalate to carrier"
print(ticket.confidence) # 0.92
エージェント最大の UX 課題はレイテンシです。ループが終わるまで、ユーザーには何も表示されません。ストリーミングは、トークンとツールのイベントを発生順に見せることでこれを解決します。LangChain は2つのモードに対応しています。
# Mode 1 — stream final output tokens only
for chunk in agent.stream(
{"messages": [{"role": "user", "content": "Status of order 4821?"}]},
stream_mode="messages",
):
if chunk[1].get("langgraph_node") == "agent":
print(chunk[0].content, end="", flush=True)
# Mode 2 — stream every event (tool calls, results, tokens)
for event in agent.stream(
{"messages": [{"role": "user", "content": "Status of order 4821?"}]},
stream_mode="updates",
):
kind = list(event.keys())[0]
if kind == "tools":
print(f"[tool] {event['tools']['messages'][0].name}")
elif kind == "agent":
for msg in event["agent"]["messages"]:
print(msg.content, end="", flush=True)
実務では、「思考中」パネルを表示する UI なら stream_mode="updates" を使ってください。最終回答を待たずに、いまどのツールを呼んでいるかを提示できます。
金銭を動かす、メッセージを送信する、データベースに書き込む。こうした操作ができるエージェントには、取り消せないアクションに対する人間の承認が必要です。LangChain v1 には2つの方法があります。単純なケースは middleware、細かく制御したい場合は LangGraph の interrupt です。
# Simple approach — middleware
from langchain.agents.middleware import HumanInTheLoopMiddleware
agent = create_agent(
model="anthropic:claude-sonnet-4-6",
tools=[search_orders, issue_refund, send_email],
middleware=[
HumanInTheLoopMiddleware(
interrupt_on={"issue_refund": True, "send_email": True}
)
],
)
# Advanced approach — LangGraph interrupt node
from langgraph.types import interrupt
def human_approval_node(state):
last_tool_call = state["messages"][-1]
# Pause execution and surface the tool call to your UI
decision = interrupt({
"tool": last_tool_call.name,
"args": last_tool_call.tool_input,
"prompt": "Approve this action?",
})
if decision["approved"]:
return state # continue
# Inject a rejection message back into the graph
return {"messages": [ToolMessage(content="Action rejected by user.", ...)]}
導入が速いのは middleware です。LangGraph の interrupt はより柔軟で、承認・却下だけでなく引数の変更もできます。クライアント案件では、まず middleware から始めるのが通例です。実行前にユーザーがツール呼び出しを編集する必要が出てきた段階で、interrupt に切り替えます。
ここを混同している開発者は多くいます。2022〜2023年の LangChain では ReAct(Reason + Act)が主流でした。モデルに「Thought / Action / Observation」という書式のスクラッチパッドをプレーンテキストで書かせ、それを LangChain が解析して呼び出し先を決めていました。動作はしましたが脆く、書式が少しでも崩れるとパーサーが壊れました。
2026年の create_agent は ネイティブ tool calling を使います。モデルは自由記述ではなく、API レスポンスとして構造化された呼び出しを返します。こちらのほうが信頼性が高く、プロンプトが二重にならないぶん低コストで、主要プロバイダーすべてが対応しています。ReAct はネイティブ tool calling に非対応のモデル向けの代替手段であり、標準の選択肢ではなくなりました。
| 項目 | ReAct(レガシー) | ネイティブ tool calling(v1 既定) |
|---|---|---|
| 形式 | 自由記述のスクラッチパッド | 構造化された API レスポンス |
| 信頼性 | 書式に依存 | スキーマで検証 |
| ツールの並列呼び出し | 不可 | 可(対応環境の場合) |
| 向いている用途 | tool calling 非対応のローカルモデル | それ以外のすべて |
LANGSMITH_API_KEY と LANGSMITH_TRACING=true を設定します。invoke もツール呼び出しもトークンも、すべて自動でトレースされます。本番で障害が起きた深夜2時に、入れておいてよかったと思うはずです。MemorySaver はローカル開発用です。公開前に PostgresSaver か RedisSaver へ差し替えてください。そうしないとサーバー再起動で会話状態がすべて消えます。r/LangChain、r/LocalLLaMA、そして X の AI エンジニアリング界隈のスレッドを数か月分読み込むと、コミュニティの見解は次のような論点に収束します。
langchain / langchain-core / langgraph)はいまだに初学者を混乱させる」。 LangChain チーム自身も認めています。v1 で概念整理は進みましたが、最初のインストールでつまずく点は残っています。「2026年の問いは『LangChain を使うべきか』ではありません。『チェックポイント、可観測性、プロバイダー横断の tool calling が必要なのか。それともプロバイダーは1つ、ステップは3つで、直接呼び出しで足りるのか』です。フレームワークを選ぶ前に、自分がどちらの問題を抱えているかを見極めてください。」
次のうち2つ以上が必要なら、LangChain エージェントが適しています。
一方、次の場合はプロバイダーの SDK を直接使うほうが適しています。
2026年の LangChain エージェントは、もはやチュートリアル用のおもちゃではありません。create_agent、ネイティブ tool calling、チェックポイント付きの状態管理、構造化出力、ストリーミング、middleware。本番のエージェントに必要な範囲を、フレームワークが一通り押さえています。学習コストは確かにあります。特にツール設計と LangGraph のチェックポイントモデルは相応の理解が要ります。それでも得られるのは、観測でき、停止でき、人間に引き継げ、コードを書き換えずに別モデルへ移せるエージェントです。AI を使った MVP の土台として、これは強い出発点になります。
IdeaToMVP Academy
4-week live cohort for founders. Learn to ship AI agents, scope MVPs, and automate your business — taught by the same team that writes these guides.