TL;DR:プロジェクトの議論が複数の LINE グループに散らばっていて、手動エクスポートでは抜け漏れが出やすい。そこで記録ボットを作った。入室時に一言だけ自己紹介し、以後はグループ内で受信のみに徹する。クラウドは中継点に留め、本機のスクリプトが定期的にメッセージと添付ファイルを取得し、手動エクスポートと同じ形式のテキストファイルに書き出してプロジェクトフォルダに保存する。設計のポイントは四つ。本機を唯一の長期保存先とすること、書き込み検証後にクラウドの削除を通知すること、先に受信して後で分類すること、ハートビートで「誰も話していない」と「ボットが壊れた」を区別することだ。できないことも先に言っておく。一対一トークには入れない、参加前の履歴は取得できない、保存するのは全文と添付ファイルであって要約ではない。そして正直に言えば、フォルダをクラウド同期対象の場所に置いていたために書き込みが連続して失敗した経験が自分にもある。詳細は最後の節に記載する。
プロジェクトの議論が LINE グループに散らばっている。どう残すか?
複数のプロジェクトグループに同時に参加している。業務上の決定・タスク・相手から届くファイル、その多くは LINE で発生する。
LINE には手動エクスポート機能があり、一定期間の会話をテキストファイルとして保存できる。ただし、実行を毎回誰かが覚えていなければならないし、各グループの記録が最新かどうかも確認が必要だ。業務が立て込むと、一つのグループのエクスポートを忘れたり、ある期間の記録が抜け落ちたりする。その期間の一言を探すとなると、LINE を遡って探すしかない。
求めている結果はシンプルだ。各グループの会話が、自動的にプロジェクトフォルダのテキストファイルになること。形式は手動エクスポートと同じで、古いファイルと新しいファイルをそのまま繋ぎ合わせられること。
一言でまとめると、図で示すと
一言で言えば、LINE 公式アカウントを受信担当として使う。グループ入室時の一言自己紹介を除き、グループ内では受信のみで送信しない。メッセージと添付ファイルはクラウド経由で一時保存され、パソコン上のスクリプトが定期的に取得してプロジェクトフォルダに書き出す。
唯一の例外は、一対一トークで「チャット内容を送信」を使って共有したときで、このときだけ受領確認を返す。質問には答えないし、雑談もしない。
flowchart LR A["LINE グループ"] --> B["公式アカウント webhook"] B -->|"署名検証・書き込み・200 返却"| C["クラウド中継(一時保存)"] C -->|"定期取得"| D["本機同期スクリプト"] D --> E["プロジェクトフォルダ LINE記録/グループ名.txt"] D -->|"書き込み確認後に削除通知"| C
いくつか用語を整理する。webhook とは、LINE がグループ内の各イベントを指定した URL にリアルタイムで送る仕組みだ。LINE の公式ドキュメントでは、イベントを処理する前に署名を検証することが求められている(ドキュメントはこちら)。クラウド側は小さな関数と、一時保存用のデータベース・添付ファイル用のオブジェクトストレージ・グループ名のキャッシュで構成される。本機側は Python 標準ライブラリだけで書いた同期スクリプトで、三時間おきに実行している。
このアーキテクチャにおいて、クラウドはファイル置き場ではない。あくまで中継点であり、ファイル置き場は自分のパソコン上のフォルダだ。
自分で作るなら、どこから始めるか
LINE 側の設定は、この順序で公式ドキュメントを読むといい。以下は公式の英語説明で、操作画面とフィールドはドキュメントを正として確認すること。
| やりたいこと | 公式説明と読むべきポイント |
|---|---|
| 公式アカウントの作成・受信機能の有効化 | Get started with the Messaging API:まず LINE 公式アカウントを作成し、Official Account Manager から Messaging API を有効にして、Developers Console でチャネルを管理する。 |
| 認証情報の準備・webhook の設定とテスト | Build a bot:channel access token・HTTPS の webhook URL・Verify と Use webhook の設定、ウェルカムメッセージと自動返信の設定について説明している。記録のみを目的とする場合は、これらの返信設定に特に注意。 |
| ボットをグループに参加させる | Group chats and multi-person chats:Allow bot to join group chats のスイッチと、グループイベントがボットに送られる仕組みを説明している。 |
| 受信イベントが LINE からのものであることを確認する | Verify webhook signature:channel secret を使った署名検証の方法。検証前にリクエスト内容を変更・再構成してはならない。 |
これらのドキュメントが説明するのは LINE プラットフォームの設定であり、本記事の記録フローを実現するには、自分で受信・同期プログラムを用意する必要がある。
クラウドと本機のセットアップについては、以下に一般的な指針を示す。筆者の実装の現状と未解決の問題は末尾に記載した。
クラウドでは、受信・一時保存・同期の三つの役割を最初に切り分ける。 Cloudflare を使う場合は、Workers 入門でデプロイ方法を確認し、D1 でメッセージを一時保存、R2 で添付ファイルを一時保存するとよい。独立したプロジェクトでテストし、権限はそのプロジェクトに必要なリソースだけに絞ることを勧める。LINE イベントを受け取る webhook は LINE から到達可能である必要があり、イベント処理前に署名検証が必要だ。本機がデータを取得して書き込みを確認する同期側は、別途認証が必要になる。URL が推測しにくいことは、この二種類の検証の代わりにはならない。
認証情報と添付ファイルはそれぞれ保管場所を決める。 LINE の channel secret・access token・本機同期用の認証情報は分けて管理し、クラウドの機密値は Workers Secrets を使い、コードや公開設定ファイルに直接書かない。本機には同期に必要な認証情報だけを置き、読み取れるアカウントを限定する。添付ファイルのストレージは非公開に保ち、公開ダウンロードは避ける。R2 の公開アクセスの説明には、どの設定でコンテンツがネットワークに公開されるかが記載されている。メッセージと添付ファイルの保存・削除ルールはあわせて確認し、片方が同期待ちのうちにもう片方が期限切れにならないよう注意する。
本機では手動実行で通しが確認できてから、スケジューラに渡す。 クラウドに同期されず、バージョン管理にも入らない普通のフォルダを書き込み先として選び、スクリプトを実行するアカウントに読み書き権限があることを確認する。システムのスケジューラで定期実行する場合は、同期や確認の失敗を検査可能なログに記録する。バックアップは別途用意し、アクセス制限と暗号化を施したうえで、実際にリストアできるか試すこと。フォルダをクラウド同期から外しても、それは書き込み先の問題を解決するだけで、バックアップは自動的には生まれない。
テストはファイルが実際に保存されるまで確認する。 まずテストグループで個人情報を含まないテキストとテスト用添付ファイルを送り、クラウドが受信できているか、本機に書き込めているか、内容が一致しているかを確認する。次に重複イベント・一時的な書き込み失敗・再実行・確認失敗をテストし、取りこぼし・重複・クラウドデータの早期削除がないかをチェックする。本機への書き込み結果とクラウドの受信状況は別々に確認し、webhook のテスト成功やハートビートの正常だけで判断しないこと。
セットアップのメモを公開する場合は、URL・アカウント名・グループ名・ストレージリソース名はすべてダミー値に置き換え、画面もテスト環境のものを使うこと。実際の認証情報・完全な設定ファイル・会話内容を含むログは載せない。読者に必要なのは設定と検証の方法であり、筆者の実際のデプロイ情報をそのまま使う必要はない。
グループのメンバーにこのボットをどう説明するか
まず原則を述べてから、筆者の対応を説明する。
ボットがグループに参加した瞬間、自動的に一言送信される。意図的に一言だけにした。
I’m Paul’s note-taking assistant, responsible for summarizing work activities. I do not participate in conversations.
日本語に意訳すると、「Paul の記録アシスタントです。業務の動向をまとめる役割を担っており、会話には参加しません」という内容だ。
あるとき、グループに参加させてから二分後に、自分でこう補足した。
これは私の業務記録を作る AI です。記録するだけで投稿しません。ご安心ください。
あるメンバーが「すごい」と返し、続けてボットに英語でタグ付けして、情報の整理・アイデアの連結・洞察を実行可能な成果に変えることへの協力を依頼した。「返事してくれるの?」と聞かれたので、「禁呪をかけているので答えません」と答えた。要するに、記録係であって質問には応答しないということだ。
ただし「summarizing」という英語は要約だけを残すと受け取られやすく、「業務記録を作る」もまだ保存内容を十分に説明していない。ボットが実際に保存するのは会話の全文であり、グループに送られた添付ファイルも一緒に保存される。業務報告書にまとめるのは、その記録を AI に渡して整理させる別のステップだ。入室時の自己紹介は用途と役割は伝えているが、保存場所・閲覧できる人・保存期間・その後 AI にどう整理させるかは、別途メンバーに説明する必要がある。
公式アカウントが送信済みのメッセージを後から編集・取り消すことはできない。Messaging API のリファレンスに列挙されているメッセージ系エンドポイントは送信と統計に限られており、送信済みメッセージの変更・取り消しに対応するエンドポイントはない。ドキュメントにある unsend イベントは、ユーザーが自分のメッセージを取り消したときにボットへ通知するものであり、ボットが自分のメッセージを取り消すためのものではない(API リファレンス)。したがって、自動説明のテキストはボットが初めてグループに参加する前に確定させる必要がある。
LINE Developers のユーザーデータポリシーには、この種のデータ取り扱いに関する別途の規定がある(ポリシー原文はこちら)。この記事では法令遵守上の結論は出さないし、誰かの状況について保証もしない。実装を検討する人は自分で全文を読んでから、どう告知するかを判断してほしい。
四つの設計判断とその理由
一、クラウドは中継点に留め、本機を唯一の長期保存先とする。 完全な会話の別コピーをクラウドに長期間置いておきたくなかった。代償は、バックアップが自分の仕事になることだ。フォルダが壊れれば第二のコピーはない。このトレードオフは設計時に受け入れたものだから、フォルダはバックアップの習慣に沿って管理する。
二、同期の順序を固定し、失敗したらそのバッチを丸ごと残す。 スクリプトの順序は、クラウドから取得(読み取り専用)・ファイル書き込み・書き込み検証・本機の記録更新、最後にクラウドへの削除通知だ。取得と削除通知は別々のリクエストになる。どこかのステップで失敗したら、そのバッチはクラウドに残したまま次のサイクルで再取得する。本機には書き込み済みの ID リストがあり、重複書き込みを防ぐ。原則は「重複あり、欠損なし」だ。これは設計上の動作であって結果の保証ではないから、だからこそ一つ目の点でバックアップが必要になる。
三、先に受信、後で分類する。 まだ登録されていないグループからのメッセージは、すべて _未分類 フォルダに先に落とし、後でルーティングを登録する。グループ ID とプロジェクトの対応付けか、ファイル名の文字列でプロジェクトを指定する形だ。こうすることで、新しいグループは設定しなくてもメッセージを取りこぼさない。設定を忘れてもメッセージが消えることはなく、ファイルが未分類に一時的に入るだけだ。出力のファイル名はグループ名によって決まる。手動エクスポート時のファイル名と異なると、同じ会話が二つのファイルに分割される。その場合はマージする必要があり、並存させてはいけない。
四、ハートビートで「誰も話していない」と「ボットが壊れた」を区別する。 ボットがグループから退出させられたり、認証情報が無効になったりしても、外から見れば「このグループは静かだ」としか分からない。だからスクリプトは毎サイクル、最後のイベントが何時間前だったかを報告し、三日間以上イベントがなければ警告を出す。また直近七日間の参加・退出イベントと、まだ同期されていない件数も一覧に表示する。LINE はボットを誰が退出させたかを教えてくれないので、あらかじめ覚悟しておく必要がある。ハートビートに一つ明確にしておくべき範囲がある。計測しているのはクラウドがイベントを受信しているかどうかであり、本機の書き込み失敗はハートビートでは見えない。その区間は同期ログにしか残らないため、誰かが読む必要がある。この考え方は、以前書いた監視スクリプト自体が壊れている問題と同じ構造だ。イベントがないとき、それが本当に何もないのか、見えていないだけなのかを区別できなければならない。
最も反直観的だった五つの落とし穴
一、名前は異なる言語を使うメンバーにも伝わるものにする。 最初のアカウントは純粋な中国語名にしていた。外国人メンバーがいるグループに参加させたところ、相手にはこれが何のアカウントか分からなかったため、後から新しいアカウントを作り直した。今は英語か中英併記の名前にして、用途が一目で分かるようにすることを勧める。名前の変更ルールはアカウントの種類によって異なる。LINE 台湾公式の説明によると、認証されていない一般アカウントは自分で変更でき、変更後七日間は再変更できない。認証アカウントの名前を変更する場合は、LINE の審査チームへ申請する必要がある。
二、echo でシークレットを貼り付けると、原因不明の 401 が出る。 echo は末尾に改行を付け加えるため、HTTP ヘッダーに入ると不正な文字になり、症状は認証失敗として現れるだけだ。これのデバッグにかなり時間を取られた。対話式入力か printf %s で値を渡すこと。
三、403 と 401 は別物だ。 カスタムの User-Agent を付けていないリクエストは、自分の関数に届く前に、クラウドプラットフォーム層のボット検知ルールで 403 に弾かれることがある。自分の関数が返すのは 401 だけなので、403 が出たらまずプラットフォーム層を疑う。シークレットが原因ではない。同期スクリプト内ではすでに対処済みだ。
四、ログをデスクトップに置くと、バックグラウンドのスケジューラが起動しない。 実際に踏んだ。ログファイルをデスクトップに置いたところ、システムの権限フラグによってスケジューラがそもそも起動しなかった。ログは ~/Library/Logs/ 以下に置くこと。デスクトップやクラウド同期対象のフォルダには置かない。
五、一つのグループに同時に存在できる LINE 公式アカウントは一つだけだ。 これはプラットフォームの制限であり、筆者が実際に踏んだわけではない。公式ドキュメントには「At any time, only one LINE Official Account can be in a group chat or multi-person chat」と明記されている(Group chats and multi-person chats)。グループにすでに別の公式アカウントがいる場合、自分のボットが参加できないのか、参加後に退出させられるのか、通知があるのかなどは、ドキュメントのその箇所には書かれておらず、筆者も実測していない。この点は確認が必要だ。招待する前に、まずメンバーリストを確認すること。
保存した記録の使い方:週次業務報告を例に
ある非営利組織で役職を務めており、毎週業務報告を提出する。進捗とタスクの主な情報源は、各 LINE グループの記録だ。記録ボットが保存するフォルダが、この報告書の原材料になっている。
大まかな流れはこうだ。毎週 AI に LINE記録 フォルダ全体を読ませる。特定のグループ名をハードコードするのではなくフォルダ全体を対象にするため、新しいグループが追加されれば自動的に含まれる。AI がドラフトを生成する。Markdown 版・PDF 版、そしてグループに貼り返す用のメッセージ草稿だ。草稿は自分が確認してから送る。これは自分に課したルールだ。
記録を AI に渡す前に、実際に踏んでから加えた規律が二つある。
第一に、各エクスポートファイルの更新状況を先に確認する。 素材を使う前に、ファイルの最終更新日時と、ファイル内の最後のメッセージの日付を確認する。記録が報告期間の数日前で止まっていれば、確認が必要な範囲を明示し、同期ログまたは LINE の元の会話と照合する。グループに本当に新しいメッセージがないこともあれば、エクスポートや同期が遅れているだけのこともある。確認できていない段階で、AI にその空白を「進捗なし」と書かせてはいけない。
第二に、ダッシュボードが空白でも進捗なしとは限らない。本機のファイルを正とする。 以前、オンラインのダッシュボードだけを読ませてドラフトを作ったところ、「本期間中に新たな成果物なし」と書き出された。しかし本機のフォルダにはそのとき大量の変更があった。ダッシュボードが反映するのは誰かが記入を覚えていた部分だけで、ファイルが反映するのは実際に起きたことだ。
もう一つ小さな落とし穴がある。フォルダをクラウドに自動同期される場所に置いていると、ファイルがまだダウンロードされていないプレースホルダーの状態になっていることがあり、読み取りに失敗する。エラーメッセージは Resource deadlock avoided だ。読む前に brctl download でファイルを手元に落とす必要がある。同じ理由でボットの書き込みも失敗する。筆者の実際の状況は次の節に記載する。
できないこと、使うべきでない場面は?
まずプラットフォームの制限から。これらは回避方法がない。
- 二人の間の一対一トークには入れない。 自分が LINE の「チャット内容を送信」でボットに共有するしかない。ボットがダウンロードするのは、自分が共有した
.txtファイルのみだ。共有されたファイルがパソコン上の既存ファイルより小さければ、スクリプトは上書きせずに.incoming.txtとして別途保存し、自分で比較できるようにする。 - 参加前の履歴は取得できない。 参加前に一度手動エクスポートをベースラインとして取得しておくこと。
- メンバーが個人プロフィールへのアクセスを許可していない場合、名前は「未知のメンバー(xxxxxxxx)」と表示される。 これは通常の動作であり、不具合ではない。誰かを特定しようとしてはいけない。
- LINE 上のファイルには保存期限がある。
次に設計上の制限を説明する。本機が唯一の長期保存先であり、バックアップの習慣がない人にとってはリスクをすべて自分が背負う構造だ。フォルダをクラウド同期対象の場所に置いていてファイルがプレースホルダーの状態になっていると、書き込みに失敗する。スクリプトの動作はクラウドへの通知をせずに次のサイクルで再取得するというもので、その場での補完はしない。
この点は自分で実際に踏んだ。10/2 当日に修正した。 以下は修正前に本機の同期ログとフォルダを確認した結果だ。修正方法と結果は末尾に記載する。
- 失敗は 8/20 から発生しており、8/27 以降は明らかに増加した。 ログに記録されているエラーは
Resource deadlock avoidedだ。一日に実行されるサイクル数が一定でない(2 回から 12 回)ため、「一サイクルあたり書き込めなかったファイル数」で状況を把握した。8/20 から 8/26 は平均して一サイクルあたり約 0.3 から 3 件。8/27 以降はほとんどが一サイクルあたり 4 から 13 件で、10/1 は 13 件、10/2 は 12 件だった。9/13 だけは例外で、7 サイクル実行して失敗がゼロだった。 - 原因はデスクトップがクラウドに同期されていたことだと判断した。 プロジェクトフォルダをデスクトップに置いており、デスクトップはクラウド同期が有効だった。10/2 のサイクルで書き込めなかった 12 件のファイルは、すべてまだダウンロードされていないプレースホルダーファイルだった。
LINE記録以下の 33 個のテキストファイルのうち、22 個がプレースホルダーだった。失敗していたのは_未分類だけでなく、プロジェクトフォルダ以下のファイルにも及んでいた。 - 全停止ではなく部分的な失敗だった。 9/28 は 8 サイクル実行し、うち 5 サイクルで記録に書き込めていた。ただし 10/2 午前 11:20 のサイクルでは、クラウドから 687 件取得したものの、12 ファイルすべての書き込みに失敗し、今サイクルの書き込みは 0 件だった。10/1 から 10/2 にかけて確認した複数のサイクルでも、毎サイクル六百件台を取得し、すべてが「新規」として扱われていた。確認が取れなかった同じバッチがクラウドに残り続けているという動作と一致する。
- ハートビートは終始正常を示していた。 8/19 から 10/2 のすべてのログを確認した。258 行のハートビートのうち、「正常」以外の行は一行もなかった。ハートビートが計測するのはクラウドがイベントを受信しているかどうかであり、クラウドは受信し続けていたため、ずっと正常を示していた。本機への書き込みが失敗していたことは、同期ログにしか残らない。
メッセージが失われているかどうかについて、判断を二段階に分けて示す。Worker のコードを見る限り、クラウドに一時保存されたデータは本機が書き込みを確認した後にのみ削除されるようになっており、期限切れ削除のコードは確認していない。設計上は、あのバッチはまだクラウドにあるはずだ。ただし、クラウドの添付ファイルストレージに別途保存期限が設定されているかは確認しておらず、逐一照合もしていない。だから設計はそうなっているとは言えるが、欠損はないとは言えない。
修正方法は、二種類の記録フォルダ(グループのテキスト記録とグループの添付ファイル)をクラウド同期対象のデスクトップから移し、同期されずバージョン管理にも入らない普通のフォルダに変更したことだ。スクリプト本体はパスの設定を一箇所変えただけだ。移動前に 572 ファイルを一つずつコピーし、各ファイルのサイズが一致することを確認してから切り替えた。切り替えた直後に一サイクル実行したところ、クラウドから 722 件取得し、すべて書き込みに成功し、添付ファイル 89 件も保存でき、書き込み失敗は 0 件、クラウドの 722 件を確認・削除した。続けてもう一サイクル実行すると、新たに取得されたものは何もなかった。これは積み上がっていたバッチが本機に落ちたことを証明するだけであり、「欠損なし」を意味するわけではない。修正前の数週間に、保存期限が来る前に消えたメッセージがあるかどうかは、逐一照合できていない。
2026 年 10 月 3 日時点で、未解決のことが二つある。新しい場所の記録フォルダのバックアップがまだ別途用意されていないこと、そしてハートビートは引き続きクラウドの受信のみを計測しており、本機の書き込み失敗は依然として同期ログを確認するしかないことだ。10/3 の午前 2:46 と 5:51 の二サイクルでは同期エラーは発生しなかったが、どちらも新しいメッセージはなかった。そのため証明できるのはスケジューラが動いているということだけで、新しいデータがあるときに正常に書き込み続けられるかどうかはまだ判断できない。クラウドの添付ファイルストレージのライフサイクルルールも未確認のままなので、今回の修正を「欠損なし」とは書けない。
最後に、使うべきでない場面について述べる。以下は筆者の判断であり、テストによる結論ではない。グループのメンバーに対して、何を・どこに保存するのか・誰が閲覧できるのかを明確に説明できない状況であれば、そのグループにこのボットを入れるべきではない。複数人が共用し、リアルタイムで全文検索できるチームの知識ベースが必要なのであれば、個人のパソコン上のテキストファイルは正しい形ではない。
コードは非公開だ。必要な人は直接連絡してほしい。一人会社の実装記録はさらにスタートアップと実装のトピックページにある。


💬 コメント
読み込み中...