この記事は、LINE公式アカウントの応答を自動化したい個人事業主・小規模事業者の方に向けて書いています。特に「拡張ツールを月額で契約するほどの規模ではないけれど、標準の応答メッセージでは足りない」「予約の受付や、人に引き継ぐ条件を自分で決めたい」という方を想定しています。

先に結論です。HaruIroAIの自社LINE公式アカウントでは、2026年2月17日から、LINEのMessaging APIを受ける自前のBotが動いています。構成は「受付→生成AIによる一次応答→条件に当たれば担当者のLINEへ通知」で、予約の確定は人が押します。LINE公式アカウントとサーバー(Cloudflare Workers)は、それぞれの無料枠に収まることを狙った設計で、料金が発生する前提で組んであるのは生成AIのAPI利用だけです。ただし、月々の送信通数やサーバーの利用量を記録してきたわけではないので、「半年ぶんの請求が0円だった」と実績で示せる材料はありません。この記事で示すのは、無料枠の上限の位置と、自社の設計がその線のどちら側にあるか、です。そして半年のあいだに、Botがどこで動いているかの記録が無いまま5ヶ月半稼働していた、という穴も踏みました。なお、ここに書く失敗はすべてHaruIroAI自身のアカウントで起きたことで、お客様に納めた仕組みの話ではありません。

この記事で分かるのは5つです。Botの構成図と流れ、無料で済む範囲と有料になる線(2026年8月20日時点の公式料金で確認)、コードに注記として残した詰まりどころ3つ、5ヶ月半気づかなかった穴の時系列、そして人が確認する境界の設計。最後に、そのまま貼って使えるWebhook受付の骨格コードと、公開前のチェックリストを置きます。

前提——標準機能・拡張ツール・自前Botの3択

LINE公式アカウントの自動応答には、大きく3つの選択肢があります。ひとつは管理画面の標準機能で、一律の応答メッセージやキーワード応答を無料で設定できます。もうひとつは月額の拡張ツールで、「LINE公式アカウント 自動化」で検索すると(2026年8月20日確認)、上位にはこの拡張ツールの解説と比較が並びます。そして3つ目が、Messaging APIのWebhookでメッセージを受け取り、自分のサーバーで返事を組み立てる自前のBotです。

HaruIroAIが自前を選んだ理由は2つです。会話の中身を生成AIに判断させたうえで、予約の受付ルールや「ここから先は人が答える」という条件を自分たちで持ちたかったこと。そして、お客様に提案する前に、自社で同じものを動かして詰まりどころを知っておきたかったことです。標準機能や拡張ツールが劣るという話ではなく、自分たちの条件に合ったのが自前だった、というだけです。なお、HaruIroAIの設定ではWebhook(Bot)とチャット(人が手で返す機能)を両方オンにしていて、Botの返事に人が割り込めるようにしています(2026年8月3日確認)。

構成——受付→AI一次応答→担当者通知

全体の流れを1枚にすると、こうなります。

[お客様のLINE]
   │ メッセージ/友だち追加/ボタン操作
   ▼
[LINEプラットフォーム] ──Webhook(HTTP POST)──▶ [自前サーバー(Cloudflare Workers)]
                                                    ├─ 1. 署名を検証する(HMAC-SHA256)。合わなければ403
                                                    ├─ 2. すぐに200を返す(LINEは2秒で待つのをやめる)
                                                    └─ 3. 200を返したあと、裏で処理する
                                                         ├─ 会話履歴を読む(KV・最大20件・24時間で消える)
                                                         ├─ 生成AIに一次応答を作らせる
                                                         │    └─ 使える道具: 案内カード/選択肢ボタン/
                                                         │                  予約の日時ピッカー/担当者へ回す
                                                         ├─ お客様へ返事を送る(push)
                                                         └─ 予約・エスカレーションなら担当者のLINEへ通知

受け取ったイベントは3種類に振り分けています。友だち追加なら、あいさつ文を返してリッチメニューを紐付ける。テキストのメッセージなら、「入力中」のようなローディング表示を出してから(最大30秒)、生成AIに返事を作らせて送る。スタンプや画像なら「テキストでお送りください」の定型文。生成AIのキーが設定されていない状態でも「担当者が確認しております」の定型文で受付だけは止まらないようにしてあります。

予約の流れだけ、もう少し詳しく書きます。お客様が「相談を予約したい」と明確に言ったときだけ、生成AIが日時ピッカーを出します。選ばれた日時はサーバー側で、代表が確認した受付ルール——平日、開始10時〜17時、最短24時間後、最長60日先、個別の休業日——に照らし、外れていれば理由を添えて選び直してもらいます。ピッカー側では日付の範囲しか絞れず、曜日や時間帯は表現できないので、この検証はサーバー側に置くしかありませんでした。通ったら、予約リクエストを「保留」として30日間保存し、お客様には「担当者が確認次第ご連絡します」というカード(キャンセルボタン付き)、担当者のLINEには「確定/お断り」のボタン付きカードを送ります。確定ボタンを押すのは人で、Botは確定しません。

無料で済む範囲と、有料になる線(2026年8月20日確認)

LINE公式アカウントの料金は、開設時のコミュニケーションプランが月額0円・無料メッセージ200通/月(追加購入不可)、ライトプランが月額5,000円(税別)・5,000通、スタンダードプランが月額15,000円(税別)・30,000通+追加メッセージ約3円/通です(LINEヤフー for Businessの料金ページ。2026年10月1日に追加メッセージ料金の改定予定との注記がありました)。

ここで効いてくるのが、Messaging APIの「応答メッセージ(reply)は通数にカウントされない、プッシュメッセージ(push)はカウントされる」という決まりです。つまり、お客様のメッセージに対してreplyで返せる設計なら、返事の通数は無料枠を減らしません。ところが、replyに使う応答トークンは「一度だけ、Webhook受信から1分以内」という条件があり、Webhook自体も2秒以内に200を返さないとタイムアウト扱いになります。生成AIの返事には数秒から数十秒かかるので、HaruIroAIはreplyを友だち追加のあいさつだけに使い、会話の返事はpushで送る設計にしました。この設計では、AIの返事1通ごとに無料200通を1通ずつ使います。月に200往復を超える見込みがあるなら、最初からライトプランを前提にするか、返事をreplyの1分以内に収める工夫が要ります。

サーバー側のCloudflare Workersは、無料プランで1日10万リクエスト・1リクエストあたりCPU時間10msまで。会話履歴と予約を置いているKVは、無料で読み取り10万/日・書き込み1,000/日(異なるキー)・容量1GBです。HaruIroAIでは通数やリクエスト数を継続的に記録していないため、実際の利用量は示せません。示せるのは設計上の計算で、会話1往復につき、Workersへのリクエスト1回・KVの読み取り1回・書き込み1回(会話履歴の保存)を使います。最初に足りなくなるのはKVの書き込み1,000/日で、1日の往復が1,000件に近づく規模が境目です(予約の保存や確定・お断りの更新も同じ書き込み枠を使うので、実際の境目はそれより少し手前になります)。

この構成で料金が発生する前提になっているのは生成AIのAPIだけです(従量課金。金額は公開していません)。「無料でどこまで作れるか」の答えとしては、replyを軸にすればLINEの通数を消費しない設計が可能で、サーバーも上の無料枠の上限に対して小さく作れる——ここまでが設計として言えることです。実際に収まり続けているかは利用量の実測で確かめるもので、うちはまだその集計を取っていません。たまり次第、実測の数字をこの記事に追記します。

LINE公式アカウントで通数を消費するかどうかが返し方で決まることを示した図。replyは通数にカウントされないが応答トークンは1分以内の一度だけ、pushはカウントされる。サーバー側の無料枠で最初に足りなくなるのはKVの書き込み1日1,000回。
LINEヤフー for Business 料金ページおよび Messaging API・Cloudflare Workers の各ドキュメントをもとに作図(2026年8月20日に確認)。

確認先:LINE公式アカウント 料金プラン(LINEヤフー for Business)Messaging APIの料金(LINE Developers)Messaging APIリファレンス「応答メッセージを送る」Webhookのエラーの原因と統計情報Cloudflare Workers LimitsWorkers KV Limits(いずれも2026年8月20日に確認)

詰まったところ——コードに注記として残した3つ

半年のあいだに直した箇所のうち、同じものを作る人が同じ場所で詰まりそうなものを、コードの注記から3つ選びます。本番で何回起きたかの記録は取っていないので、件数は書きません。

1. ボタンに持たせるデータ(postback)には上限がある。切る位置を間違えると落ちる。日時ピッカーのような「ボタンを押すとサーバーに送られるデータ(postback)」には上限があり、HaruIroAIの本番コードは300文字で詰めています(コードの注記に残している値です。製品仕様として変わり得るので、作る際はMessaging APIリファレンスの「ポストバックアクション」で当日の値を確かめてください)。相談内容の要約を日本語で持たせていたところ、ひらがなや漢字の多く(UTF-8で3バイトの文字)はURLエンコードすると1文字が9文字になるため(絵文字など4バイトの文字なら12文字)、エンコード後に300文字で切ると %E7%84 のように途中で切れ、受信側の復号で URIError になります。対処は、エンコード前の文字数を1文字ずつ減らしながら、エンコード後が上限に収まるまで詰めること。あわせて、受信側で一度復号された値をもう一度復号しない(本文に % が含まれていると、それだけで落ちます)。

2. 生成AIの「考える」機能を速度のために切ったら、道具が動かなくなった。返事を速くしようと思考(thinking)を無効化したところ、本来は構造化された形で返ってくる「道具を使う」という指示が、本文のテキストとして出力されることがありました。エラーは出ません。道具が実行されないまま、会話は正常に終わります。気づきにくい壊れ方です。いまは思考を有効のまま、速さは別の設定(effort)で調整しています。これは使っているモデルでの挙動で、どのモデルでも同じとは限りません。

3. モデルを乗り換えたら、古い会話履歴が邪魔をした。2026年8月3日に生成AIをGemini 2.5 FlashからClaude(Opus 5)へ切り替えました。会話履歴は24時間で消えるとはいえ、切替の瞬間には旧モデルの形式で保存された履歴が残っています。新しいAPIはその形式を受け付けず、さらに履歴の先頭がユーザー発言でないと400エラーを返します。旧形式を捨てる処理と、先頭がユーザー発言になるまで先頭を削る処理の2つを足しました。ついでに書くと、Workersは協定世界時で動き、LINEの日時ピッカーはお客様の端末の時刻文字列を返すので、日本時間への変換は1箇所にまとめています。

5ヶ月半気づかなかった穴——稼働場所とデプロイ経路が記録に無かった

作ること自体より痛かったのは、こちらです。時系列で書きます。

  • 2026年2月17日リポジトリの外で先にデプロイして稼働開始。6日後の2月23日にソースコードを後追いでコミット。このとき「どのアカウントのWorkerで動いているか」が記録に残らなかった
  • 2026年7月15日旧ブログ15本の公開を終了(旧URLは410)。Botが会話の中で案内する記事カード5件と、その画像がすべて410になった
  • 2026年7月19日カードのリンク切れに気づく
  • 2026年8月3日生きているページへ差し替える修正を用意したが、本番へ届ける経路が無いと判明。調べると、Botは業務用ではない個人のクラウドアカウント上で5ヶ月半動いていた。同日、業務用アカウントへ移す手順(8ステップ・戻し方を含む)を文書にした

リンクが切れていた期間に、カードを押した方がいたかどうかは、ログが無く確認できていません。影響があり得たのは自社LINEの友だちの方で、お客様に納めた仕組みではありませんが、「案内のたびにエラーページへ飛ぶ」状態が、7月15日から少なくとも8月3日までの19日間は続いていたことは事実です。

もうひとつ、記録の事故も起きました。業務用アカウントを見てBotが見当たらなかったときに、「Workerは存在しない=影響なし」と一度誤って判断し、正しい記録を間違った訂正で上書きしかけました。見えているアカウントに無いことと、存在しないことは別です。同じ型の空振りは「AIの障害報告が指した機能は本番に存在しなかった——緊急対応の空振り実例」にも書きましたが、今回は逆向き——「無い」と判断した側が間違っていました。

HaruIroAIはこう考えています。自前Botの難所は作ることではなく、「どこで動いていて、どうやって直し、どこで人に渡すか」を決めて記録しておくことです。Botは一度動くと、壊れたように見えないまま古くなります。

人が確認する境界——Botが決めないこと

半年の運用で固まった境界は4つです。

ひとつ、予約の確定は人が押す。Botは「受け付けました、担当者が確認次第ご連絡します」までしか言いません。ふたつ、人へ回す条件を先に書いておく。具体的な見積や納期の確定が必要なとき、お客様が不満や怒りを示したとき、「人と話したい」と言われたとき、同じ質問が3回以上繰り返されたとき、知識ベースに無い質問のとき(この2つには例外があり、屋号の由来などブランドの話は何度聞かれてもBotが自分で答えます)——このどれかに当たれば、Botは担当者のLINEへ理由と会話の要約を送り、お客様には「担当者から改めてご連絡します」と伝えます。みっつ、答えない領域を決めておく。事業と無関係な話題(政治・宗教・医療・法律)には答えず、住所や電話番号などの個人情報は求めも答えもしません。よっつ、残す期間を決めておく。会話履歴は24時間、予約リクエストは30日で自動的に消えます。

正直に書いておくと、応答の質については、代表の自己評価は「まだ良くない」です(2026年8月3日時点)。稼働場所の是正を先に進めていて、プロンプトと応答設計の改善は次の課題です。AIにどこまで任せ、どこから人が確認するかの線引きは「AIに任せる範囲と人が確認する範囲の線引き——取り返しのつかない操作の前の1確認」にも書きました。Botの場合、取り返しのつかない操作は「予約の確定」と「金額の提示」でした。

コピペで使える2つ——Webhook受付の骨格と、公開前チェックリスト

ひとつ目は、Cloudflare Workers用のWebhook受付の骨格です。HaruIroAIの本番コードから、署名検証・即200・裏処理の3点だけを抜き出した簡略版で、イベントごとの処理(handleEvent)はご自身の用途で書く前提です。チャネルシークレットは環境変数から渡し、コードには書きません。

export default {
  async fetch(request, env, ctx) {
    if (request.method !== 'POST') return new Response('running', { status: 200 });

    const body = await request.text();                       // 検証はパース前の文字列で行う
    const signature = request.headers.get('x-line-signature');
    if (!signature || !(await verifySignature(body, signature, env.LINE_CHANNEL_SECRET))) {
      return new Response('Invalid signature', { status: 403 });
    }

    // 重い処理(生成AIの呼び出し等)は裏へ回し、先に200を返す。LINEは2秒でタイムアウト扱いにする
    ctx.waitUntil(processEvents(JSON.parse(body).events, env));
    return new Response('OK', { status: 200 });
  },
};

async function verifySignature(body, signature, channelSecret) {
  const enc = new TextEncoder();
  const key = await crypto.subtle.importKey(
    'raw', enc.encode(channelSecret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']
  );
  const sig = await crypto.subtle.sign('HMAC', key, enc.encode(body));
  return btoa(String.fromCharCode(...new Uint8Array(sig))) === signature;
}

async function processEvents(events, env) {
  for (const event of events) {
    try {
      await handleEvent(event, env);   // follow / message / postback を振り分ける
    } catch (err) {
      console.error('event error', err); // 1件の失敗で残りを止めない
    }
  }
}

ふたつ目は、自前Botを公開する前のチェックリストです。上の半年ぶんの経験を、確認項目に直したものです。

  • 稼働場所(どのアカウント・どのWorkerやサーバー)と、更新の手順が、コードと同じ場所の文書に書いてある
  • 秘密情報4種(チャネルシークレット/チャネルアクセストークン/生成AIのAPIキー/通知先の担当者ID)はコードに書かず、環境変数か秘密管理から注入している
  • 署名が合わないリクエストは403で捨てている(検証はパース前の文字列で)
  • Webhookは2秒以内に200を返し、重い処理は後ろへ回している
  • 返事をreplyで返すかpushで返すかを決め、pushなら月の通数を見積もっている(無料は200通/月)
  • Botが案内するURLと画像が生きているかを、サイトを更新するたびに確認する手順がある
  • Botが確定してはいけない操作(予約の確定・金額の提示)と、人へ回す条件を書き出してある
  • 会話履歴と予約データを残す期間を決めてある(HaruIroAIは24時間と30日)
  • Webhookの再送をオンにするかを決め、オンなら再送フラグ(deliveryContext.isRedelivery)で二重処理を防いでいる

この記事も、ひとつの検証です

最後に、この記事を書いた理由をもうひとつ。HaruIroAIのサイトは「line公式アカウント 自動化」という検索語で、直近4週に12回表示され、平均15.3位、クリックは0回でした(2026年8月20日のSearch Console)。母数が小さいため評価はせず、件数だけを示します。この語に対して、一般論ではなく自社の実装記録を置いたらどうなるか——この記事自体が、その検証の1本です。結果は、数字がたまったらこのブログで公開します。

自前で作るか、拡張ツールか、標準機能か。分かれ目は、月の会話数と、会話の中身をどこまで自分で制御したいかだと考えています。ご自身のLINE公式アカウントで、受付・自動応答・予約連携をどの段階から整えるかは、LINE公式アカウント構築・運用支援のページで段階ごとにご案内しています。

この記事を書いた人

相葉 葵 / HaruIroAI 広報

HaruIroAIの広報担当。専門用語をできるだけ使わず、WebやAI活用の実践で分かったことを、小規模事業者向けに整理します。記事はHaruIroAIの検証記録と一次情報をもとに作成し、公開前に人が確認しています。

この記事の作り方

この記事は、構成・一次情報の照合・文章化にAIを使用し、HaruIroAIの編集ルールに基づいて作成しています。Botの構成・設定値・コード注記は、HaruIroAIのリポジトリにある本番Botのソースコードと運用記録を2026年8月20日に読んで確認したもので、記事内の骨格コードはそこから署名検証・即200・裏処理の3点だけを抜き出した簡略版です(署名の比較は簡易な文字列比較で、定数時間比較ではありません)。稼働開始日・リンク切れ・稼働場所の判明に関する時系列は社内の運用記録によります。リンク切れの期間にカードを押した方がいたかは、ログが無く確認できていません。LINE公式アカウントの料金、Messaging APIの課金対象、応答トークンと2秒の条件、Cloudflare WorkersとKVの無料枠は、本文中にリンクした各公式ページを2026年8月20日(日本時間)にHaruIroAIが直接開いて確認した時点の記載で、今後変わる可能性があります。自社の月間送信通数・Workersのリクエスト数・KVの利用量・請求額は記録・公開しておらず、本文の「無料枠の範囲に収まる設計」は、これらの上限値と設計からの位置づけで、利用実績の提示ではありません。「WebhookとチャットをどちらもオンにしているHaruIroAIの設定」は自社の設定の事実であり、LINE公式の仕様説明ではありません。詰まりどころ3つは本番コードの注記に基づく記述で、本番での発生件数は記録していません。postbackのデータ上限300文字も本番コードの注記に残した値で、製品仕様として変わる可能性があります。生成AIのAPI費用、Botの開発工数・費用、稼働中のアカウントや識別子、秘密情報の値は公開していません。Search Consoleの数値(表示12回・15.3位・クリック0)は母数が小さいため件数のみを示し、率や傾向は述べていません。内容は公開前に人が最終確認しています。