はじめに:なぜ「状態保持」エージェントなのか

ソファのクリーニング見積もりを取るために業者に連絡したことはありますか?サイズ、素材、写真、住所をやり取りし、見積もり確認後に日程調整まで…気づけば15分もかかってしまいます。このプロセスをAIに任せられたらどうでしょうか。

単なるチャットボットと真のAIエージェントの違いは**「状態(State)」**にあります。顧客が「2LDKで冷蔵庫内部の清掃もお願いします。火曜と水曜なら可能です」と一度に伝えた場合、エージェントは不足情報を判断し、価格を計算し、予約まで一貫して処理する必要があります。

本記事では、PythonとLangGraphを使用して、マルチステップの予約ワークフローを処理する状態ベースのエージェントを構築します。さらにLangfuseを組み込み、可観測性(Observability)を確保する実践的なアプローチを解説します。(なお、エージェントの完全なソースコードはGitHubで公開されています。)

AI chat interface for customer service booking agent with LangGraph

核心実装:LangGraphで状態マシンを構築する

LangGraphの核心は**共有状態(Shared State)**です。複数の顧客メッセージにわたって会話を継続する必要があるため、TypedDictで状態スキーマを定義します。

from typing import TypedDict, Optional

class BookingDetails(TypedDict):
    service_type: Optional[str]
    size: Optional[str]
    address: Optional[str]
    preferred_dates: Optional[list[str]]
    price: Optional[float]

class AgentState(TypedDict):
    messages: list
    booking_details: BookingDetails
    next_step: str

次にグラフビルダーを生成し、ノードを追加します。例えば価格計算ノードは以下のように状態を読み取り、部分的な更新を返します。

from langgraph.graph import StateGraph, END

def calculate_price_node(state: AgentState):
    details = state["booking_details"]
    # 実際の価格計算ロジック(例:サービス種別、サイズに基づく)
    price = calc_price(details)
    return {"booking_details": {**details, "price": price}, "next_step": "confirm"}

graph = StateGraph(AgentState)
graph.add_node("gather_info", gather_info_node)
graph.add_node("calculate_price", calculate_price_node)
graph.add_node("book_appointment", book_node)

情報収集後、条件付きルーティング関数が十分な情報があるか判断します。

def route_after_gather(state: AgentState):
    if is_complete(state["booking_details"]):
        return "calculate_price"
    return END  # 追加の顧客メッセージを待機

graph.add_conditional_edges("gather_info", route_after_gather)
graph.add_edge("calculate_price", "book_appointment")
graph.add_edge("book_appointment", END)

最後にチェックポインタと共にグラフをコンパイルすると、状態が自動保存され、会話が途切れても続行できます。

from langgraph.checkpoint.memory import MemorySaver
app = graph.compile(checkpointer=MemorySaver())

この構造の利点は明確です。LLMの柔軟な対話能力と決定論的なビジネスルール(価格計算、予約ロジック)を分離することで、予測可能かつ自然なユーザー体験を提供できます。

Python code editor showing LangGraph state schema and node definitions

注意事項と深掘り:可観測性(Observability)の確保

プロダクション環境でAIエージェントを運用する際に最も重要なのは**「何が起きているかを把握すること」**です。LangfuseはオープンソースのLLM観測プラットフォームで、プロンプト、入出力、トークン使用量、コストを追跡できます。

from langfuse.callback import CallbackHandler

langfuse_handler = CallbackHandler(
    public_key="pk-lf-...",
    secret_key="sk-lf-...",
    host="https://cloud.langfuse.com"
)

# グラフ実行時にコールバックを渡す
app.invoke(inputs, config={"callbacks": [langfuse_handler]})

注意点:

  • LLM呼び出しコストは予想以上に早く積み上がる可能性があります。Langfuseダッシュボードでトークン使用量を定期的に監視してください。
  • 状態スキーマが複雑になるほどデバッグが難しくなります。各ノードの入出力をロギングする習慣をつけましょう。
  • チェックポインタをメモリではなくPostgreSQLなどの永続ストレージに置き換えれば、サーバー再起動後も状態が維持されます。

この技術の限界はLLMの非決定性です。同じ入力でも異なる応答が返る可能性があるため、重要なビジネスロジック(価格、予約確定)は必ずコードで検証する防御ロジックが必要です。

Langfuse observability dashboard monitoring LLM token usage and traces Development Concept Image

結論:次のステップは?

ここまで、LangGraphとLangfuseを活用して状態ベースの予約エージェントを構築する方法を見てきました。このプロジェクトはv0レベルですが、モジュール化された設計のおかげで拡張が容易です。

実務適用のためのアドバイス:

  • 日本のSI環境ではレガシーシステムとの連携が鍵となります。予約データを既存のERPやCRMに同期するアダプターレイヤーを必ず検討してください。
  • フロントエンドはStreamlitで素早くプロトタイピングした後、実際のサービスではReactやVueに置き換えることを推奨します。
  • LINE、Slackなどのメッセンジャー連携を追加すれば、顧客接点を大きく拡張できます。

次の学習方向:

  • LangGraphのinterrupt機能を活用したhuman-in-the-loopワークフロー
  • Langfuseの評価(Evaluation)機能でエージェント応答品質を自動測定
  • マルチエージェント構造への拡張(例:予約エージェント+通知エージェント)

AIエージェントは単なる流行ではなく、反復的なビジネスプロセスを自動化する実質的なツールです。小さなワークフローから始めてみてください。


合わせて読みたい記事:

根拠資料: I Replaced a 15-Minute Booking Process with a LangGraph AI Agent

本コンテンツは、信頼性の高い情報源をもとにAIツールを活用して作成され、編集者によるレビューを経て公開されています。専門家によるアドバイスの代替となるものではありません。