01背景 — 取りこぼしていたのは「営業時間外」だった
中小企業の問い合わせ対応には、共通した構造的な問題があります。問い合わせが来る時間帯と、対応できる時間帯が一致していないという点です。経営者が本気で情報収集をするのは、たいてい業務が終わった夜か、休日です。しかしその時間、こちらは電話にもメールにも出られません。
加えて、実際に面談まで進めようとすると日程調整の往復が発生します。「来週の火曜はいかがですか」「その日は難しくて…」というやり取りが3往復すれば、それだけで数日が過ぎます。その間に、相手の熱量は下がっていきます。
02設計方針 — 「回答するAI」ではなく「実行するAI」にする
よくある失敗は、FAQを大量に読み込ませただけのチャットボットを置いて終わることです。それでは結局「詳しくはお問い合わせください」に着地し、利用者は元の場所に戻されます。
そこで今回は、AIに外部システムを操作する権限そのものを渡す方針を採りました。Claude APIのTool Use(ツール実行)機能を使い、AIが会話の流れの中で必要と判断したタイミングで、自分でカレンダーを確認し、自分で予定を登録します。人間が間に入って転記する工程を、最初から設計に含めません。
- 会話を分岐させない。 選択肢ボタンを押させる形式ではなく、自然文のまま受け取って解釈します。「来週の水曜の午後」のような曖昧な表現も、当日日付を基準に解決します。
- 空き確認を必須の前段に置く。 予約を確定するツールは、空き状況を確認するツールを通ったあとでなければ呼ばれないよう、プロンプト側で制約しています。
- 名前の自己申告を信用しすぎない。 会話で聞いた名前とは別に、LINE側のプロフィール名をサーバー側で取得し、両方を記録します。
03システム構成
Webhook 送信
ユーザー単位ロック
会話履歴の保持
events.insert
AIは 03 で止まらず、04 を自分で呼び出す。ここが「回答するだけのボット」との構造的な違い。
実行環境: Render(常時起動) / gunicorn + Flask / 認証情報はすべて環境変数で管理
04実装 — AIに渡す「道具」の定義
Tool Useでは、AIに使わせたい機能をJSONスキーマとして定義します。ここで重要なのは引数の形式だけでなく、「いつ呼ぶべきか」を説明文に書き込むことです。AIはこの説明を読んで呼び出しを判断するため、ここが実質的な業務ルールの記述になります。
# AIに渡すツール定義。descriptionが呼び出し条件そのものになる TOOLS = [ { "name": "check_availability", "description": "指定した日付・時間帯に予定が空いているか確認する。" "予約を確定する前に必ず呼び出すこと。", "input_schema": { "type": "object", "properties": { "date": {"type": "string", "description": "YYYY-MM-DD形式"}, "start_time": {"type": "string", "description": "HH:MM形式"}, "end_time": {"type": "string", "description": "HH:MM形式"}, }, "required": ["date", "start_time", "end_time"], }, }, { "name": "book_appointment", "description": "check_availabilityで空きを確認した後、実際に予約を確定して" "Googleカレンダーに登録する。日付・時間・目的・名前が" "全て揃うまでは呼び出さないこと。", # ... 以下略 }, ]
あとはAIの応答が tool_use を返す限りループし、実際の関数を実行して結果を返す、というエージェントループを組みます。予約者のLINE IDのような改ざんされては困る値は、AIに渡させずサーバー側で注入しています。
本番で実際に踏んだ問題
- LINEのWebhook再送による二重処理。 応答が遅れるとLINEは同じイベントを再送します。結果、同一ユーザーの会話履歴が同時に書き換えられ、ツール呼び出しと実行結果の対応が壊れてAPIエラーになりました。メッセージIDによる重複排除と、ユーザー単位のロックで解消しています。
- Google Meetリンクの自動生成が通らない。 サービスアカウント経由ではカンファレンス作成が拒否される構成だったため、固定の面談URLを案内する方式に切り替えました。仕様上できないことは、早めに諦めて別解に寄せるほうが速いです。
$ POST /webhook ← LINE Messaging API > tool_use: check_availability(date, time) > Google Calendar API ✓ 空き状況を確認 > tool_use: book_appointment(...) > Google Calendar API ✓ 予定を登録 > reply → LINE 200 OK
05結果
- 営業時間外の問い合わせは翌営業日まで放置
- 日程調整に複数回のやり取りが発生
- カレンダーへの登録は手作業
- 面談URLの発行・送付も都度手動
- 24時間、その場で一次回答が返る
- 1回の会話の中で日程が確定する
- カレンダー登録まで自動で完了
- オンライン希望なら面談URLも自動案内

06仕様まとめ
| 区分 | 自社導入(シモテクノロジー 問い合わせ窓口) |
|---|---|
| 実装機能 | AI相談応答 / カレンダー空き照会 / 予約確定 / オンライン面談URL自動案内 / 対応履歴の記録 |
| 使用技術 | Claude API(Tool Use)、LINE Messaging API、Google Calendar API、Python、Flask、gunicorn |
| 実行環境 | Render(常時起動プラン) / 認証情報は環境変数で管理 |
| 運用状況 | 本番環境で24時間稼働中 |
07この事例から言えること
AI導入がうまくいかない原因の多くは、モデルの性能ではなく業務システムに接続されていないことにあります。どれだけ賢く回答できても、実際の予約台帳やカレンダーに手が届かなければ、最後の一歩は人間の手作業として残り続けます。
逆に言えば、接続さえしてしまえば、規模の大きくない会社ほど効果は分かりやすく出ます。今回の構成は、美容室やクリニック、学習塾のように問い合わせと予約が業務の入口になっている業種であれば、ほぼそのまま応用できます。
同じ仕組みを、御社のLINE公式アカウントにも。
この記事のシステムは、実際に当社の問い合わせ窓口として動いています。まずは触ってみてください。ご相談はそのままAIが受け付けます。
サービス内容と料金を見る →