ライフサイエンス企業検索・リサーチBot Part3 質疑応答機能の実装
| 目次(STEP2:スレッド対応編) |
1. 導入
前回の記事では、Slack上で「@bot 企業名」とメンションするだけで、自動的に企業情報を収集・要約し、スレッドにレポートを返すワークフローを紹介しました。
今回はその発展編として、スレッド上での質問応答が可能な機能を追加します。
これにより、同一スレッド内で追加の質問や深掘り分析ができ、チーム内の議論をよりインタラクティブに進めることができます。
2. 背景と目的
通常、Slackボットは単発のメッセージに反応する構成が多く、文脈をまたいだ応答が難しいという課題がありました。
しかし、n8nとSlack APIを組み合わせることで、スレッド構造を検知し、親メッセージ(ルートメッセージ)を参照した上で、文脈を保持した回答を生成することが可能になります。
この仕組みにより、Slack上で「企業調査→補足質問→AIによる再分析」といった流れを1つのスレッド内で完結できます。
3. スレッド対応ワークフローの概要
ワークフローの基本的な流れは以下の通りです:
- Slack上でボットをメンション
- メッセージがスレッドに属するか(親スレッドがあるか)を判定
- スレッドがなければ、新規企業としてWeb検索を開始
- スレッドがあれば、ルートメッセージを取得し、会話全体をLLMに入力
- OpenAIノードが文脈を踏まえた応答を生成
- 結果をスレッドに返信
- (発展)Web検索データをRAG用データベースに保存可能

4. Slack権限設定の追加
スレッド情報を取得するため、Slack Appに以下のBot Token Scopesを追加する必要があります:
• channels:history • groups:history • im:history • mpim:history
これにより、ボットがスレッドの履歴データを取得し、前後文脈を参照可能になります。
権限を変更した場合は、再インストール(Reinstall the App)を忘れずに行います

5. 条件分岐(IFノード)の設定
Slack Triggerノードの直後にIFノードを追加します。
判定条件は以下の通りです:
- 条件:thread_ts が存在するか
- 存在しない → 新規企業検索(STEP1ワークフローへ)
- 存在する → スレッド返信(STEP2ワークフローへ)
この分岐によって、n8nがスレッド内返信か新規検索かを自動で判断できます。

6. スレッド情報の取得
リプライ時の分岐では、Slack APIノード「Get a thread of messages posted to a channel」を使用します。
設定項目:
• Channel:トリガーから受け取ったチャンネルID • Thread_TS:スレッドの親メッセージID • Limit:1(親スレッドのみ取得する場合)
これにより、ルートメッセージを取得してLLMに読み込ませることができます。

7. LLMノードによる応答生成
次に、OpenAIノードを追加し、以下のプロンプト構成を設定します:
• system: 企業アナリストとしての役割を指定 • instruction: ルートメッセージとスレッド全体を参照し、質問に応じた補足説明を生成 • input: Slackスレッドの本文 • output: Markdown形式の回答
こうすることで、単発回答ではなく「前回のレポート+質問内容」を踏まえた整合的な回答を出力できます。

8. 結果統合とSlack返信設定
最後に、Mergeノードで両分岐(新規検索/スレッド返信)を統合し、Slack Messageノードでスレッドに返信します。
設定ポイント:
• Send Message To: チャンネルID • Message Text: OpenAIノードの出力 • Reply to a Message: メッセージID(ts)
これで、新規検索でもスレッド返信でも安定した出力が可能になります。
リンクエラーを避けるため、フィールド指定は手動入力が推奨です。

9. 実行結果
Slack上での実行イメージ:
• 新規メンション → 企業情報レポートを自動返信 • スレッド内質問 → 前回レポートを参照し、AIが文脈に沿って回答
この結果、Slack上での「リサーチBotとしての継続的対話」が実現します。
ユーザーは、複数回の検索やブラウザ操作を行わずに、チャット内で知見を深めることができます。

10. まとめ
今回紹介したスレッド対応機能により、Slack連携ボットが「一問一答型」から「文脈理解型」に進化しました。
次回は、STEP3としてRAG(Retrieval-Augmented Generation)を導入し、企業情報のデータベースを活用した高度な再検索・補足分析を実現します。
Appendix. 詳細ステップ
STEP2. スレッドに関する内容は質問応答ができる

一連の流れ
- Slack上でボットをメンションすることでワークフローが起動
- メッセージが親スレッドを持つか否かで条件分岐
- 親スレッドなし・・・新規企業として新たに情報検索開始
- 1.Firecrawlを用いてWeb検索を実施し、複数のURLを取得(Firecrawl / Split out)
- 2.URL群に対してスクレイピングを実施(Loop Over Items / Firecrawl)
- 3.結果をまとめて企業情報に関するレポートを生成(OpenAI)
- 親スレッドあり・・・スレッドの内容を読み込んで返信する
- 1.スレッドの一番親となるルートメッセージを取得
- 2.メッセージをLLMに読み込ませやすい形に変換
- 3.スレッドの内容も含めてLLMが気レポートを生成(OpenAI)
- 親スレッドなし・・・新規企業として新たに情報検索開始
- LLMが生成したレポートをSlackの返信として送信
- 今回、Web検索によって収集されたデータをRAG用のデータベースに追加
1.まずは質問応答を可能にするためには、メンションされたメッセージの内容だけではなく他のメッセージも取得する必要があるので、SlackAppの権限を設定する。Slack通知の際に設定した権限に加えて、さらに4つの権限を追加する。

この時に、OAuth & Permissionsの権限を変更すると組織への再インストールが必要になるので、reinstall the appボタンで再インストールすることを忘れない。

試してみると上記のように、スレッドの親メッセージにある情報なども含めて全て取得できるようになる。
2.Slack Triggerの後ろにifノードを追加する。

IFノードの中は「thread_ts」が存在するか/しないかを判定させる。thread_tsが存在しない = スレッドではなく単なるメッセージである。逆にthread_ts が存在する = リプライである(つまり、前後関係を踏まえる必要がある)

3.リプライ時の分岐を作成する
- まずはメンションされたメッセージ以外のスレッド情報を取得するために、「Get a thread of messages posted to a channel」ノードを配置。

- 中身は以下のようにセット。今回、親スレッドのみ取得することを念頭に置いてLimit = 1に設定。もしスレッドの内容を全て取得したい場合は、Limit を増やすことで取得可能。1件のみ取得の場合はコードブロックは不要

4.AIノードを追加

- 前のSlack MessageもしくはJavascriptコードの結果を使ってLLMに与えるプロンプトを作成

5.Mergeノードをセットして、どちらの分岐であっても回答が送信されるように結果を統合。

- Mergeノードの中は「Append」を設定

- Slack Messageは「スラック返信ワークフロー」と同様に、Add Optionから「Reply to a message」を追加。一番初め、ワークフローのトリガーとなったSlack MessageのユニークなIDであるts をここに入れる。

ヘルツレーベンでは、ライフサイエンス業界に特化したDX・自動化支援を提供しています。
PubMedや学術情報の自動収集をはじめ、Slack・Gmailなどを活用したナレッジ共有の仕組みまで、実務に直結するワークフローを設計・導入いたします。
提供サービスの例
- 製薬・医療機器業界での提案活動や調査業務の自動化支援
- アカデミアや研究者向けの文献レビュー・情報共有フローの最適化
- 医療従事者のキャリア開発を支援するリスキリングプログラム
👉 ご興味をお持ちの方はぜひお気軽にお問い合わせください。
お問い合わせフォームはこちら

監修者 株式会社ヘルツレーベン代表 木下 渉
株式会社ヘルツレーベン 代表取締役/医療・製薬・医療機器領域に特化したDXコンサルタント/
横浜市立大学大学院 ヘルスデータサイエンス研究科 修了
製薬・医療機器企業向けのデータ利活用支援、提案代行、営業戦略支援を中心に、医療従事者向けのデジタルスキル教育にも取り組む。AI・データ活用の専門家として、企業研修、プロジェクトPMO、生成AI導入支援など幅広く活動中

