1.はじめに
こんにちは!
KDDIアイレットの取り組みとして、8月17日から8月28日まで開催中の「Google Cloud 夏休み自由研究ブログリレー」、本日は3日目の投稿です。
今回は「 Slack会話要約Botの完全自動構築」をテーマに、実際に検証してみた内容をご紹介します!
これまでの記事はこちらです。
- ADK × Agent Engine、最小構成のはずが Agent Identity でハマった話
- Google Workspace Studio × Gemini Notebookを使ってノーコードでできる効率化を考えてみた
日々の業務で Slack の会話を追いきれず、「今日どんな重要な連絡があったっけ?」となることはありませんか?
普段なかなか立ち止まることができないチャンネルの情報を見逃さないためにも、
毎日決まった時間にその日のSlackの会話をAIが自動で要約してくれるBotを作成しました。
このBotは、
- Slackからメッセージを受信
- Gemini 2.5 Flashで要約
- 要約結果をSlackへ自動投稿
という処理をサーバーレスで実現しています。
この記事では、Botの作り方だけでなく、設計の考え方や初心者がつまずきやすいポイントも紹介します。これからCloud RunやGeminiを触ってみたい方の第一歩になれば嬉しいです。
目次
- 1.はじめに
- 2. システム構成
- 3.今回作ったBOTの特徴
- 4. 事前準備
- 5.【Step 1】 必要なファイルを作成する(コピペでOK!)
- 6.【Step 2】 初心者最大の壁 IAMを突破する
- 7.【Step 3】 ネット上に公開!(ビルド & デプロイ)
- 8.【Step 4】 毎日決まった時刻に自動で動かすタイマー設定
- 9.まとめ
2. システム構成

- Python (Flask): アプリケーションのベース
- Cloud Scheduler**: 毎日19:00に定期実行するタイマー
- Cloud Run: コンテナ上で Flask アプリ(要約ロジック)を稼働
- Vertex AI (Gemini 2.5 Flash): 高速かつ高精度なLLMで会話を要約
- Artifact Registry: Docker コンテナイメージの保存庫
Slackのテスト出力イメージ

3.今回作ったBotの特徴
ただ要約するだけでなく、実運用に耐えうるようにいくつか工夫を入れました!
①AIが「業務」と「雑談」を自動で仕分け
Geminiへのプロンプト(指示)を工夫し、「業務トピック」と「社内コミュニケーション」を綺麗に分けて箇条書きにしてくれます。
②「過去24時間」の出来事だけを正確に拾う
時間を計算し、「確実に過去24時間以内のメッセージだけ」を要約対象にしています。
③会話がない休日は静かにしている
その日チャンネルに新しい投稿がなかった場合は、無駄なエラーや通知を出さず、静かに処理を終了します。
④維持費がほぼ「無料」
サーバーを常時稼働させず、1日1回動く瞬間だけ起動する仕組み(Cloud Run + Cloud Scheduler)にしているため、個人開発の無料枠に収まります。
4.事前準備
以下の3つを用意します。
- Google Cloud アカウントとプロジェクト作成
- Cloud Shell の起動(ブラウザ上でコマンドが打てる黒い画面)
- Slack Bot Token の取得(xoxb-から始まるトークン)
※Slack API管理画面からBotを作成し、channels:history と chat:write の権限を付与しておきます。



5. 【Step 1】 必要なファイルを作成する(コピペでOK!)
Google Cloud の Cloud Shell を開き、以下の3つのファイルを作成します。(エディタを開いてコピペするだけです。)

① requirements.txt(必要なライブラリ)
Flask==3.0.3
google-genai
slack_sdk
gunicorn
② Dockerfile(動かすための環境設定)
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
ENV PORT=8080
EXPOSE 8080
CMD ["gunicorn", "--bind", "0.0.0.0:8080", "--workers", "1", "--threads", "8", "main:app"]
③ main.py(メインのプログラム)
軽量な Python イメージをベースにし、Gunicorn で Flask アプリを起動します。
import os
import time
from flask import Flask
from google import genai
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
app = Flask(__name__)
SLACK_BOT_TOKEN = os.environ.get("SLACK_BOT_TOKEN")
TARGET_CHANNEL = os.environ.get("TARGET_CHANNEL_ID", "YOUR_TARGET_CHANNEL_ID") # 環境変数化を推奨
POST_CHANNEL = os.environ.get("POST_CHANNEL_ID", "YOUR_POST_CHANNEL_ID")
@app.route("/", methods=["GET", "POST"])
def run_pipeline():
if not SLACK_BOT_TOKEN:
return "SLACK_BOT_TOKEN is not set", 500
slack_client = WebClient(token=SLACK_BOT_TOKEN)
project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")
# Vertex AI クライアントの初期化
gemini_client = genai.Client(
vertexai=True,
project=project_id,
location="us-central1"
)
try:
twenty_four_hours_ago = time.time() - (24 * 60 * 60)
result = slack_client.conversations_history(
channel=TARGET_CHANNEL,
oldest=str(twenty_four_hours_ago),
limit=100
)
messages = result.get("messages", [])
if not messages:
return "No messages found in the last 24 hours", 200
# ボット以外のユーザー発言を抽出
conversation_text = ""
for msg in reversed(messages):
if "bot_id" not in msg:
conversation_text += f"- {msg.get('text')}\n"
if not conversation_text.strip():
return "No user messages to summarize", 200
# Prompt の作成
prompt = f"""
以下のSlackの会話ログを読み、内容を「業務トピック」と「社内コミュニケーション」に分けて要約してください。
単なる相槌(「了解です」「ありがとうございます」など)は省いてください。
【要約フォーマット】
*🎯 本日の業務トピック*
・(業務上の決定事項、連絡事項、障害対応など)
*☕️ 本日の社内コミュニケーション*
・(メンバーの誕生日、雑談、ランチ情報、週末の予定など)
【会話ログ】
{conversation_text}
"""
response = gemini_client.models.generate_content(
model='gemini-2.5-flash',
contents=prompt,
)
slack_client.chat_postMessage(
channel=POST_CHANNEL,
text=response.text
)
return "Success", 200
except Exception as e:
print(f"Error: {e}")
return f"Error: {e}", 500
if __name__ == "__main__":
port = int(os.environ.get("PORT", 8080))
app.run(host="0.0.0.0", port=port)
※APIトークンやシークレット情報を Git やコード内に直書きしないよう注意してください。Secret Manager の利用を推奨します
※投稿数が極めて多いチャンネルではページネーション処理の追加を検討してください
6. 【Step 2】 初心者最大の壁 IAMを突破する
Google Cloud で初心者が一番ハマるのが「権限エラー(403 PERMISSION_DENIED)」です。
※私もここで何度も繰り返しつまづきました。
「コンテナを保存する権限」と「AIを使う権限」を付与します。
Cloud Shell で以下を実行してください。
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUM=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
SERVICE_ACCOUNT="${PROJECT_NUM}-compute@developer.gserviceaccount.com"
# 1. コンテナ保存庫への書き込み権限
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT}" \
--role="roles/artifactregistry.writer"
# 2. AI(Gemini)を使う権限
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT}" \
--role="roles/aiplatform.user"
7.【Step 3】 ネット上に公開!(ビルド & デプロイ)
書いたコードをアップロードして動かします。
① コンテナの保存庫(リポジトリ)を作る
まずは「slack-repo」という名前の保存庫を作ります。
gcloud artifacts repositories create slack-repo \
--repository-format=docker \
--location=us-central1 \
--description="Slack Bot Repository"
② コンテナのビルド
作った保存庫(私の場合slack-repo)の中に、今回のアプリをアップロードします。
gcloud builds submit --tag us-central1-docker.pkg.dev/${PROJECT_ID}/slack-repo/作成したアプリ名:v1
③ Cloud Run へデプロイ
※ xoxb-... の部分は、事前準備で取得したトークンとチャンネルIDに書き換えて実行してください。
gcloud run deploy slack-summary-service \
--image us-central1-docker.pkg.dev/${PROJECT_ID}/slack-repo/作成したアプリ名:v1 \
--region us-central1 \
--allow-unauthenticated \
--set-env-vars SLACK_BOT_TOKEN="xoxb-取得したトークン",GOOGLE_CLOUD_PROJECT="${PROJECT_ID}",TARGET_CHANNEL_ID="紐づけたいチャンネルID",POST_CHANNEL_ID="YOUR_CHANNEL_ID"
※本記事では簡易化のため –allow-unauthenticated を使用していますが、本番環境では OIDC 認証を設定してください
8.【Step 4】 毎日決まった時刻に自動で動かすタイマー設定
最後に、「Cloud Scheduler」を使って毎日決まった時刻に実行されるように設定します。(今回は19時に設定します。)
(※URLの部分は、Step 3 で画面に出た Cloud Run のURLに書き換えてください)
gcloud scheduler jobs create http daily-slack-summary-job \
--schedule="0 19 * * *" \
--time-zone="Asia/Tokyo" \
--uri="Step3で表示されたCloud RunのURL全体を貼る" \
--http-method=GET \
--location=us-central1
これで完成です!!
テストの手順(3ステップ)
今すぐ動くかどうか気になるので、動作確認をします。
Step 1: Slackにテスト用の会話を投稿する
以下を小分けにして送ってみてください。送信者は自分だけで問題ないです。
Aさん: お疲れ様です!来週のクライアント提出用資料、デザインのFix締め切りを「8/5(水) 15:00」に変更したいのですがいかがでしょうか?
Bさん: 了解です!マーケチームのチェックが入るので、8/5 15:00で問題ありません。スケジュール確定しましょう。
Aさん: ありがとうございます!確定で進めます!
Cさん: 了解です〜。あ、全然関係ないですが今日のオフィス近くのカレー屋さん、日替わりがチキンカツカレーでした!めちゃくちゃうまかったです笑
Bさん: うわ、それ絶対うまいやつですね。明日行きます笑
Fさん: 緊急です!決済連携APIで500エラーが多発しています。ログ調査入ります。
Gさん: こちらでも確認しました!原因は外部APIのレスポンスタイムアウトのようです。リトライ処理のタイムアウト値を 3秒 から 10秒 に変更する緊急パッチをあてます。
Fさん: パッチ適用完了しました。エラー収束を確認!迅速な対応ありがとうございました。
Hさん: お疲れ様です!障害対応ありがとうございます。
Hさん: 今週末、〇〇さんキャンプ行くって言ってましたよね?天気晴れそうでよかったですね!
Gさん: そうなんですよ!富士山の方に行ってきます〜:camping: リフレッシュしてきます!
Step 2: スケジューラーを手動で強制的に実行する
毎日19時の動作をシミュレートするため、Cloud Shell で以下のコマンドを実行し、
手動でBotを起動します。
gcloud scheduler jobs run daily-slack-summary-job --location=us-central1
Step 3: Slackに届いた要約結果をチェックする!
指定したSlackのチャンネルに、Geminiからの要約が届けば大成功です。

9.まとめ
Gemini 2.5 Flash は非常にレスポンスが早く、日本語の要約クオリティも十分実用レベルです。
Cloud Run + Cloud Scheduler の組み合わせにより、リクエストが発生した瞬間しか課金されない超低コストな運用が可能です。
Google Cloud で動かす際は、
Cloud Run / Cloud Build のサービスアカウントに必要な IAM 権限を漏れなく付与するのが成功の鍵でした!
ぜひ皆さんの Slack ワークスペースでも試してみてください!
💡 おまけ:要約を自分だけのDMで受け取る方法
「全員のチャンネルに要約を流すのはちょっと恥ずかしい…」という方は、環境変数の POST_CHANNEL_ID を自分の「メンバーID(Uから始まるID)」に変更するだけで、Botから個別のDMとして要約を受け取ることができます!コードの修正は不要です!