当記事では、SlackとChatGPTを組み合わせたチャットボットを作成する手順を解説します。実際に実装する際には、セキュリティ上の注意点や権限の管理などをしっかり検証しながら進めてください。はじめにSlack はビジネスチャットツールとして多くの企業やチームで利用されており、チャットベースのコミュニケーションを円滑にするだけでなく、Bot を導入することで作業の自動化や情報の一元化が期待できます。一方の ChatGPT は OpenAI が提供する大規模言語モデルで、テキストベースのやり取りに対して柔軟かつ高度な応答を返すことができる点が魅力です。この 2 つを組み合わせた「Slack × ChatGPT」のボットを導入すると、たとえば以下のようなメリットがあります。高度な応答精度ChatGPT は自然言語処理が得意なため、ユーザーからの問い合わせやサポート対応をある程度自動化しながらも、違和感の少ない応答を返すことが可能です。24 時間 365 日稼働Slack Bot はクラウド上で動かすことで、常時稼働が容易になります。ユーザーがいつ問い合わせても、素早く対応する下地が整います。チームコミュニケーションの活性化プロジェクト管理やドキュメントの作成など、社内情報を一括管理している場合、ChatGPT Bot に簡単な質問をするだけで補足情報が得られるなど、業務効率化につながります。これから解説する手順は、SlackApp の作成、OpenAI (ChatGPT) 側の設定、そして実際にボットのコードを実装し、Cloud Run でデプロイする流れとなります。スクリーンショットを交えながら進めることで、読者の方が実際の画面を確認しながら構築できるように意図しています。1. SlackAppSlackApp の作成まずは Slack Bot として動作するアプリ (以下「SlackApp」と表記) を作成します。Slack のAPI ポータルにアクセスし、右上にある「Your Apps」から「Create New App」を選択。「Create an app」と言うポップアップが表示されるので、下の「From scratch」をクリックします。「App Name」の箇所に作成するアプリの名前(今回は「Bot test」として作成)を入力し、作成するワークスペースを選んで選択します。「Create App」を押すとアプリのダッシュボード画面に遷移します。ここまでで、ひとまず Slack 上での Bot となるアプリの「枠」ができました。次に、ボットとしての振る舞いを定義していくために権限の設定を行います。権限の設定SlackApp のダッシュボードにはサイドバーに「OAuth & Permissions」というセクションがあり、ここでスコープ (Bot が使える権限の範囲) を設定します。たとえばユーザーからメッセージを取得したり、Bot としてメッセージを送信したりする場合は下記のようなスコープを追加します。channels:historychannels:readchat:writechat:write.publicim:history など例えば「slackでメンション付きの質問メッセージに対して回答してくれるBot」を作成する際は以下のような権限が必要になります。追加したスコープは必ずサイドバーの「Install App」からワークスペースにインストールし直すことで有効になります。インストール後に生成される「Bot User OAuth Token」が実際に Slack にメッセージを投稿する際に利用する認証トークンです。これをコピーしておきましょう。2. ChatGPTopenai プラットフォームの設定続いて、ChatGPT (OpenAI) 側の設定を行います。ChatGPT は Web のチャット UI で利用するだけでなく、OpenAI が提供する API を通してプログラムから利用できます。OpenAI プラットフォームにアクセスし、アカウントを作成もしくはログイン。「View API keys」などのメニューから管理画面に入り、必要に応じて使用状況や請求 (Billing) の上限を確認しておきます。OpenAI の利用には無料枠が存在するものの、一定量を超えると課金が発生します。特に開発段階や検証段階ではどの程度リクエストが飛ぶかを考慮し、上限を超えないように注意しましょう。API キーの発行OpenAI 管理画面で「Create new secret key」ボタンを押すと、API キーが発行されます。このキーは一度しか表示されないため、発行時にメモしておきましょう。セキュリティ管理が重要なので、Git リポジトリなどに直接ハードコードしないように注意が必要です。あとでプログラム内や環境変数として使用するため、キーを安全に保管しておきます。3. CloudRun 関数実装する関数の作成Cloud Runは、コンテナで実行可能なアプリケーションをデプロイするだけでなく、HTTP トリガーとしてサーバレス的に利用できるGCPのサービスです。今回は、Slack からのリクエストを受け取ってChatGPTに問い合わせ、結果を Slack に返す処理を実装します。例えば Pythonで実装すると以下のイメージは以下のようになります。(Flaskで簡易的にサーバーを立ち上げる例を用いています)%3Cpre%3E%3Ccode%3E%0Aimport%20os%0Aimport%20json%0Aimport%20openai%0Aimport%20requests%0Afrom%20flask%20import%20Flask%2C%20request%2C%20jsonify%0A%0Aapp%20%3D%20Flask(__name__)%0A%0A%23%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%20%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%20%2F%20%E5%AE%9A%E6%95%B0%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%0A%23%20%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%81%AF%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%82%84%E3%82%BB%E3%82%AD%E3%83%A5%E3%82%A2%E3%82%B9%E3%83%88%E3%82%A2%E3%81%AB%E4%BF%9D%E5%AD%98%E3%81%99%E3%82%8B%E3%81%AE%E3%81%8C%E6%9C%9B%E3%81%BE%E3%81%97%E3%81%84%E3%81%A7%E3%81%99%0ASLACK_BOT_TOKEN%20%3D%20%22xoxb-XXXXXXXXXXXX-XXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXX%22%0AOPENAI_API_KEY%20%3D%20%22sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX%22%0A%0A%23%20OpenAI%20API%20%E3%82%AD%E3%83%BC%E8%A8%AD%E5%AE%9A%0Aopenai.api_key%20%3D%20OPENAI_API_KEY%0A%0A%23%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%20Slack%20%E3%81%B8%E3%81%AE%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E9%80%81%E4%BF%A1%E7%94%A8%E3%83%98%E3%83%AB%E3%83%91%E3%83%BC%E9%96%A2%E6%95%B0%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%0Adef%20post_message_to_slack(channel%2C%20text)%3A%0A%20%20%20%20%22%22%22%0A%20%20%20%20Slack%E3%81%AE%E6%8C%87%E5%AE%9A%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB%E3%81%AB%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E9%80%81%E3%82%8B%E9%96%A2%E6%95%B0%0A%20%20%20%20%22%22%22%0A%20%20%20%20url%20%3D%20%22https%3A%2F%2Fslack.com%2Fapi%2Fchat.postMessage%22%0A%20%20%20%20headers%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22Content-Type%22%3A%20%22application%2Fjson%22%2C%0A%20%20%20%20%20%20%20%20%22Authorization%22%3A%20f%22Bearer%20%7BSLACK_BOT_TOKEN%7D%22%0A%20%20%20%20%7D%0A%20%20%20%20payload%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22channel%22%3A%20channel%2C%0A%20%20%20%20%20%20%20%20%22text%22%3A%20text%0A%20%20%20%20%7D%0A%0A%20%20%20%20response%20%3D%20requests.post(url%2C%20headers%3Dheaders%2C%20data%3Djson.dumps(payload))%0A%20%20%20%20if%20response.status_code%20!%3D%20200%3A%0A%20%20%20%20%20%20%20%20print(f%22Slack%20API%20error%3A%20%7Bresponse.text%7D%22)%0A%0A%23%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%20Flask%20%E3%83%AB%E3%83%BC%E3%83%88%EF%BC%9ASlack%E3%81%8B%E3%82%89%E3%81%AE%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E5%8F%97%E4%BF%A1%E3%82%A8%E3%83%B3%E3%83%89%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%0A%40app.route(%22%2Fslack%2Fevents%22%2C%20methods%3D%5B%22POST%22%5D)%0Adef%20slack_events()%3A%0A%20%20%20%20%22%22%22%0A%20%20%20%20Slack%E3%81%AEEvent%20Subscriptions%E3%81%A7%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E3%82%A8%E3%83%B3%E3%83%89%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%0A%20%20%20%20%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E5%8F%97%E3%81%91%E5%8F%96%E3%81%A3%E3%81%A6ChatGPT%E3%81%AB%E6%8A%95%E3%81%92%E3%80%81%E8%BF%94%E7%AD%94%E3%82%92Slack%E3%81%AB%E6%8A%95%E7%A8%BF%E3%81%99%E3%82%8B%E4%BE%8B%0A%20%20%20%20%22%22%22%0A%20%20%20%20data%20%3D%20request.json%0A%0A%20%20%20%20%23%20Event%20Subscriptions%20%E3%81%AEURL%E6%A4%9C%E8%A8%BC%20(%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8)%20%E3%81%AB%E5%AF%BE%E5%BF%9C%0A%20%20%20%20if%20%22challenge%22%20in%20data%3A%0A%20%20%20%20%20%20%20%20return%20jsonify(%7B%22challenge%22%3A%20data%5B%22challenge%22%5D%7D)%0A%0A%20%20%20%20event%20%3D%20data.get(%22event%22%2C%20%7B%7D)%0A%20%20%20%20if%20event.get(%22type%22)%20%3D%3D%20%22message%22%20and%20not%20event.get(%22bot_id%22)%3A%0A%20%20%20%20%20%20%20%20channel%20%3D%20event.get(%22channel%22)%0A%20%20%20%20%20%20%20%20user_message%20%3D%20event.get(%22text%22%2C%20%22%22)%0A%0A%20%20%20%20%20%20%20%20%23%20%3D%3D%3D%20ChatGPT%20%E3%81%B8%E3%81%AE%E5%95%8F%E3%81%84%E5%90%88%E3%82%8F%E3%81%9B%20%3D%3D%3D%0A%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20response%20%3D%20openai.ChatCompletion.create(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20model%3D%22gpt-3.5-turbo%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20messages%3D%5B%7B%22role%22%3A%20%22user%22%2C%20%22content%22%3A%20user_message%7D%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20gpt_text%20%3D%20response.choices%5B0%5D.message.content.strip()%0A%20%20%20%20%20%20%20%20except%20Exception%20as%20e%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22OpenAI%20API%20error%3A%20%7Be%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20gpt_text%20%3D%20%22%E3%81%99%E3%81%BF%E3%81%BE%E3%81%9B%E3%82%93%E3%80%81%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E5%BF%9C%E7%AD%94%E3%81%AB%E5%A4%B1%E6%95%97%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82%22%0A%0A%20%20%20%20%20%20%20%20%23%20%3D%3D%3D%20Slack%20%E3%81%B8%E3%81%AE%E8%BF%94%E4%BF%A1%20%3D%3D%3D%0A%20%20%20%20%20%20%20%20post_message_to_slack(channel%2C%20gpt_text)%0A%0A%20%20%20%20return%20jsonify(%7B%22status%22%3A%20%22ok%22%7D)%2C%20200%0A%0A%23%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%20%E3%83%A1%E3%82%A4%E3%83%B3%E9%96%A2%E6%95%B0%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8B%E9%9A%9B%E3%81%AF%20debug%3DFalse%20%E3%81%AB%E3%81%97%E3%80%81%E3%83%9D%E3%83%BC%E3%83%88%E3%81%AA%E3%81%A9%E3%82%92%E7%92%B0%E5%A2%83%E3%81%AB%E5%90%88%E3%82%8F%E3%81%9B%E3%81%A6%E8%AA%BF%E6%95%B4%E3%81%97%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%0A%20%20%20%20app.run(host%3D%220.0.0.0%22%2C%20port%3D3000%2C%20debug%3DTrue)%0A%0A%3C%2Fcode%3E%3C%2Fpre%3E%0Aコードの概要Flask を使用したサーバ/slack/events エンドポイントで Slack からのイベントを受け取り、POST リクエスト内容を request.json で取得しています。Event Subscriptions で発生する「URL 検証(challenge)」にも簡易的に対応。Slack Bot Token と OpenAI API KeySLACK_BOT_TOKEN と OPENAI_API_KEY は本来、環境変数やAWS Secret Manager などで安全に管理する必要があります。コード上にベタ書きは推奨されません。OpenAI API の呼び出しopenai.ChatCompletion.create() を使って ChatGPT (gpt-3.5-turbo) にリクエストしています。ユーザーのメッセージ (user_message) を messages に入れ、モデルからの回答を gpt_text に取得。Slack への返信post_message_to_slack 関数で chat.postMessage を呼び出し、チャネルに Bot としてメッセージを投稿します。メッセージの投稿が成功すると、ユーザー側では Bot が返信した内容を確認できます。注意事項セキュリティ: リクエストが本物の Slack から送られたものかを検証するため、署名検証(Slack Signing Secret の活用)が推奨されます。認証情報の管理: API キーはベタ書きではなく環境変数や安全な管理方法を用いることが望ましいです。レートリミット: OpenAI API にはリクエスト数などの制限があるため、実運用では適宜ログやキャッシュを導入し、コストや制限に気をつけてください。ChatBotの利用例社内ドキュメントに関する質疑応答通常ChatGPTに代表される対話式のAIはインターネット上の情報をもとに回答をしてくれます。そのため社内の情報は学習データに含まれておらず「先月の弊社の売り上げを教えて」などの質問には回答することができません。そこで、ChatBotを社内ドキュメントと連携させれば、社外秘の情報を含む便利な問い合わせ窓口として機能します。社内ドキュメントをベクトル化した状態でGCS等に保存しておき、質問があった際にこちらを参照した上で回答させるようにすれば、ChatGPTが社内に関する事前知識を持った状態で質問に回答してくれるようになります。要約・翻訳AIを活用したChatBotは、大量の文章を瞬時に要約したり、多言語間の翻訳を行ったりすることが得意です。社内で長文のレポートやエンジニアリングドキュメントを共有するとき、ChatBotを活用して重要なポイントだけを要約した資料を作成すれば、読む側の負担を軽減できるでしょう。また、海外の取引先や海外支社とのやり取りが増える昨今、英語や他の言語の文書をChatBotに翻訳させることで、コミュニケーションの効率がさらに向上します。専門用語や固有名詞が混在する資料でも、継続的に学習を行うことで精度を高められるのが魅力です。フィードバック上司普段の上司への報告やフィードバックも、ChatBotを介して簡単にまとめることができます。たとえば、部署メンバーが1週間の業務内容をChatBotに入力すれば、報告書の形式に整えたり、必要に応じてグラフやリスト形式に要約してくれます。また、上司からの問い合わせに対しても、ChatBotがやり取りを補助する形で回答の下書きを提示してくれるため、回答に漏れがないかのチェックが容易になります。実際のやり取りの前に下書きをChatBotに作ってもらうことで、事前確認の質が上がり、コミュニケーションがスムーズになるでしょう。慰め一見、業務とは直接関係のない領域に思えるかもしれませんが、ChatBotはユーザーの悩み相談やメンタルケアの一端を担うこともできます。長時間の作業や難しい案件に取り組んで疲弊しているメンバーに対して、気軽に悩みを打ち明けられる相手としてChatBotが存在すると、ストレス発散のきっかけになる場合があります。もちろん、専門的なメンタルサポートが必要なレベルであれば別途対応が求められますが、ちょっとした励ましや慰めの言葉をかけてもらえるだけでも、モチベーションや気分を多少なりとも向上させる効果が期待できます。まとめ以上の手順を踏むことで、Slack と ChatGPT を連携させたチャットボットを作ることができます。大まかな流れとしては、SlackApp の作成とトークンの取得OpenAI 側での API キーの発行Cloud Run 上に Bot アプリをデプロイして、Slack のイベントを受信するというステップに整理されます。ポイントは、セキュリティトークンや API キーを適切に管理し、不要な部分が外部に公開されないようにすること、そしてSlack 側の設定 (Event Subscriptions や Slash Command) と Cloud Run のエンドポイントを正しく紐づけることです。実運用となると、ChatGPT への問い合わせ頻度が多くなってコストやレート制限などの課題が出てくるかもしれません。その際は、応答をキャッシュしたり、問い合わせの長さを制限したりといった工夫が必要になるでしょう。しかし、適切な運用がなされれば、Slack との連携による自然言語応答は、社内サポートや情報検索、簡単なタスク自動化などに大きな効果を発揮します。ぜひ、本記事を参考に自社だけのチャットボットを作成してみてください。