8月2日、Soner Yıldırımが「I Replaced a 15-Minute Booking Process with a LangGraph AI Agent」と題した記事を公開した。この記事では、LangGraphとLangfuseを組み合わせてステートフルなカスタマーサポートエージェントを構築する手順について詳しく紹介されている。
清掃会社に見積もりを依頼したとき、ソファのサイズや素材の確認、写真の送付、住所の提供——そのやり取りだけで15分かかった。Soner Yıldırımはこれを「AIエージェントに任せるべき問題だ」と判断し、Python・LangGraph・LangChainでエージェントを実装した。ソースコードはGitHubで公開されている。
単なるチャットボットではない
記事が強調するのは、このシステムが「定型フォームの代替」ではないという点だ。
フォームベースの見積もりツールでは、全顧客が同じ質問フローをたどる必要がある。一方、AIエージェントであれば:
「2LDKの部屋を掃除してほしい。住所はここで、冷蔵庫の中も頼みたい。火曜か水曜が都合いい」
この一文に必要情報がすべて含まれていれば、エージェントは追加質問なしに価格計算へ進む。逆に情報が不足していれば、不足している項目だけを聞く。エージェントが次のアクションを自律的に決定する点が、単なるワークフローとの違いだ。
エージェントが担う処理は以下の通り:
- 顧客との会話を通じたニーズの把握
- サービス料金の計算と提示
- 顧客の承諾・拒否の処理
- 最適な予約時間枠の提案
- 予約の確定と記録
LangGraphでステートを管理する
複数ターンにまたがる会話を扱うため、ステートフルな設計が必要になる。LangGraphはグラフ構造——処理単位である「ノード」と、ノード間の遷移を定義する「エッジ」——によって会話フローをモデル化する。各ノードは現在の状態を読み取り、部分的な更新を返す。エッジには条件付きルーティングを設定でき、状態の内容に応じて次に実行するノードを動的に切り替えられる。
状態スキーマはTypedDictで定義する:
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
booking_details: BookingDetails
calculated_price: NotRequired[float | None]
time_options: NotRequired[list[TimeOption]]
selected_slot: NotRequired[TimeOption | None]
status: BookingStatus
booking_id: NotRequired[str | None]
会話から抽出した情報はBookingDetailsという構造化モデルに変換される。フィールドはすべてOptionalで、部分的な抽出にも対応できる設計だ:
class BookingDetails(BaseModel):
service_type: ServiceType | None = Field(default=None)
size_info: float | None = Field(default=None, gt=0)
cleaning_depth: CleaningDepth | None = Field(default=None)
add_ons: list[str] = Field(default_factory=list)
address: str | None = Field(default=None)
is_complete: bool = False
next_question: str | None = Field(
default=None,
exclude=True,
description="A concise question asking only for information still missing.",
)
条件付きルーティングで次のノードを決定する仕組みも肝だ。情報収集ノードの後、is_completeフラグを確認して価格計算ノードへ進むか、次のメッセージを待つかを分岐させる:
def should_continue_to_pricing(
state: AgentState,
) -> Literal["calculate_price", "end"]:
if state["booking_details"].is_complete:
return "calculate_price"
return "end"
最終的にグラフはチェックポインター付きでコンパイルされ、会話の途中状態を保持できる:
graph.compile(checkpointer=checkpointer or MemorySaver())
オブザーバビリティにLangfuseを使う
本番運用で欠かせないのがオブザーバビリティ(可観測性)だ。記事ではLangfuse——LLMアプリのトレーシング・モニタリング・デバッグを目的としたプラットフォームで、OSSとしてセルフホストすることも、クラウド版(SaaS)を利用することもできる——を採用している。
設定は.envにキーを記述するだけ:
LANGFUSE_SECRET_KEY=
LANGFUSE_PUBLIC_KEY=
LANGFUSE_BASE_URL="https://cloud.langfuse.com"
Langfuseのダッシュボードでは、プロンプト・入出力・トークン使用量・コストを一覧で確認できる。予算の異常検知にも使えるため、本番環境での監視基盤として機能する。

コストについては、1回の実行でほぼゼロに近い金額と紹介されており、OpenAI APIキーがあれば手軽に検証できる。

拡張の余地
現時点はv0という位置付けで、CLIによるエンドツーエンドの動作確認が可能な状態だ。モジュール設計により、以下への拡張が想定されている:
- Webやモバイルアプリ、WhatsAppなどのフロントエンド
- PostgreSQL等の本番データベース
- 従業員カレンダーや位置情報サービスとの直接連携
こうした拡張が低コストで実現できる背景には、AgentStateを中心に据えたグラフ設計がある。すべてのノードが共通の状態オブジェクトを読み書きする構造のため、新たな機能をノードとして追加するだけでよく、既存の処理フローへの影響を最小限に抑えられる。
詳細はI Replaced a 15-Minute Booking Process with a LangGraph AI Agentを参照していただきたい。