Skip to main content
このドキュメントは AI によって自動翻訳されています。不正確な部分がある場合は、英語版 を参照してください。
このガイドでは、Slack 内でユーザーの質問に直接回答する、AI を活用した Slack Bot を構築します。プラグインを開発したことがない場合は、まず プラグイン開発クイックスタートガイド を読んでください。

プロジェクトの背景

Slack Bot プラグインを使うと、チームは Slack 内で LLM と直接チャットでき、会話がすでに行われている場所に AI を組み込めます。 Slack は堅牢な API を備えたオープンなリアルタイムコミュニケーションプラットフォームで、開発が容易な webhook ベースのイベントシステムも提供しています。このガイドでは、そのシステムを利用して以下の図のような Slack Bot プラグインを作成します。
Slack Bot の図
このガイドでは、よく似た 2 つの用語が登場します。
  • Slack Bot:Slack プラットフォーム上のチャットボットで、リアルタイムにやり取りできる仮想ユーザーです。
  • Slack Bot プラグイン:Dify アプリケーションと Slack を接続する、Dify マーケットプレイス内のプラグインです。このガイドでは、その構築方法を説明します。

動作の仕組み

  1. ユーザーが Slack Bot にメッセージを送信する Slack 内のユーザーが Bot にメッセージを送信すると、Slack Bot は即座に Dify プラットフォームへ webhook リクエストを発行します。
  2. Slack がメッセージを Slack Bot プラグインに転送する Dify プラットフォームが Slack Bot プラグインをトリガーし、プラグインがメッセージを Dify アプリケーションに中継します。これは、メールシステムが受信者のアドレスに配信するのと似ています。この接続は、Slack の API を通じて Slack の webhook アドレスを設定し、プラグインに入力することで確立します。プラグインは Slack リクエストを処理して Dify アプリケーションに転送し、そこで LLM が入力を分析して応答を生成します。
  3. プラグインが応答を Slack に返す プラグインは Dify アプリケーションから応答を受け取ると、LLM の回答を同じルートで Slack Bot に送り返します。これにより、ユーザーはチャットしている場所でそのまま応答を受け取れます。

前提条件

Slack App を作成するには、Slack API プラットフォーム にアクセスし、アプリをゼロから作成して、デプロイ先のワークスペースを選択します。
Slack App を作成する
  1. Webhooks を有効にする
Webhooks を有効にする
  1. Slack ワークスペースにアプリをインストールする
Slack ワークスペースにアプリをインストールする
  1. プラグイン開発のために OAuth トークンを取得する
プラグイン開発のために OAuth トークンを取得する

1. プラグインの開発

コーディングを始める前に、クイックスタート:拡張プラグインの開発 を読んでいるか、または Dify プラグインを構築した経験があることを確認してください。

1.1 プロジェクトの初期化

以下のコマンドを実行して、プラグイン開発環境をセットアップします。
dify plugin init
プロンプトに従って基本的なプロジェクト情報を入力します。extension テンプレートを選択し、AppsEndpoints の両方の権限を付与します。 プラグイン内で Dify サービスを逆呼び出しする方法の詳細は、逆呼び出し:App を参照してください。
プラグイン権限

1.2 設定フォームの編集

このプラグインには 2 つの情報が必要です。どの Dify アプリが応答を処理するか、そして Bot の応答を認証する Slack App トークンです。この両方のフィールドをプラグインのフォームに追加します。 group ディレクトリ内の YAML ファイル(例:group/slack.yaml)を修正します。フォームのファイル名はプラグイン作成時に入力した情報によって決まるため、パスは適宜調整してください。 サンプルコード slack.yaml
settings:
  - name: bot_token
    type: secret-input
    required: true
    label:
      en_US: Bot Token
      zh_Hans: Bot Token
      pt_BR: Token do Bot
      ja_JP: Bot Token
    placeholder:
      en_US: Please input your Bot Token
      zh_Hans: 请输入你的 Bot Token
      pt_BR: Por favor, insira seu Token do Bot
      ja_JP: ボットトークンを入力してください
  - name: allow_retry
    type: boolean
    required: false
    label:
      en_US: Allow Retry
      zh_Hans: 允许重试
      pt_BR: Permitir Retentativas
      ja_JP: 再試行を許可
    default: false
  - name: app
    type: app-selector
    required: true
    label:
      en_US: App
      zh_Hans: 应用
      pt_BR: App
      ja_JP: アプリ
    placeholder:
      en_US: the app you want to use to answer Slack messages
      zh_Hans: 你想要用来回答 Slack 消息的应用
      pt_BR: o app que você deseja usar para responder mensagens do Slack
      ja_JP: あなたが Slack メッセージに回答するために使用するアプリ
endpoints:
  - endpoints/slack.yaml
特に注目すべき設定フィールドが 2 つあります。
  - name: app
    type: app-selector
    scope: chat
  • typeapp-selector に設定すると、ユーザーはこのプラグインの使用時にメッセージを特定の Dify アプリへ転送できます。
  • scopechat に設定すると、プラグインは Agent、チャットボット、チャットフローなどのアプリタイプとのみやり取りできます。
最後に、endpoints/slack.yaml ファイルで、受信する Slack メッセージを処理できるようリクエストメソッドを POST に変更します。 サンプルコード endpoints/slack.yaml
path: "/"
method: "POST"
extra:
  python:
    source: "endpoints/slack.py"

2. 関数コードの編集

endpoints/slack.py ファイルを修正し、以下のコードを追加します。
import json
import traceback
from typing import Mapping
from werkzeug import Request, Response
from dify_plugin import Endpoint
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError


class SlackEndpoint(Endpoint):
    def _invoke(self, r: Request, values: Mapping, settings: Mapping) -> Response:
        """
        Invokes the endpoint with the given request.
        """
        retry_num = r.headers.get("X-Slack-Retry-Num")
        if (not settings.get("allow_retry") and (r.headers.get("X-Slack-Retry-Reason") == "http_timeout" or ((retry_num is not None and int(retry_num) > 0)))):
            return Response(status=200, response="ok")
        data = r.get_json()

        # Handle Slack URL verification challenge
        if data.get("type") == "url_verification":
            return Response(
                response=json.dumps({"challenge": data.get("challenge")}),
                status=200,
                content_type="application/json"
            )

        if (data.get("type") == "event_callback"):
            event = data.get("event")
            if (event.get("type") == "app_mention"):
                message = event.get("text", "")
                if message.startswith("<@"):
                    message = message.split("> ", 1)[1] if "> " in message else message
                    channel = event.get("channel", "")
                    blocks = event.get("blocks", [])
                    blocks[0]["elements"][0]["elements"] = blocks[0].get("elements")[0].get("elements")[1:]
                    token = settings.get("bot_token")
                    client = WebClient(token=token)
                    try:
                        response = self.session.app.chat.invoke(
                            app_id=settings["app"]["app_id"],
                            query=message,
                            inputs={},
                            response_mode="blocking",
                        )
                        try:
                            blocks[0]["elements"][0]["elements"][0]["text"] = response.get("answer")
                            result = client.chat_postMessage(
                                channel=channel,
                                text=response.get("answer"),
                                blocks=blocks
                            )
                            return Response(
                                status=200,
                                response=json.dumps(result),
                                content_type="application/json"
                            )
                        except SlackApiError as e:
                            raise e
                    except Exception as e:
                        err = traceback.format_exc()
                        return Response(
                            status=200,
                            response="Sorry, I'm having trouble processing your request. Please try again later." + str(err),
                            content_type="text/plain",
                        )
                else:
                    return Response(status=200, response="ok")
            else:
                return Response(status=200, response="ok")
        else:
            return Response(status=200, response="ok")

3. プラグインのデバッグ

Dify プラットフォームに移動し、プラグインのリモートデバッグアドレスとキーを取得します。
リモートデバッグアドレスとキーを取得する
プラグインプロジェクトに戻り、.env.example ファイルをコピーして .env にリネームし、デバッグ情報を入力します。
INSTALL_METHOD=remote
REMOTE_INSTALL_URL=debug.dify.ai:5003
REMOTE_INSTALL_KEY=********-****-****-****-************
プラグインを起動します。
python -m main
これで、Dify のプラグイン管理ページのワークスペースにプラグインがインストールされ、他のチームメンバーもアクセスできるようになります。

プラグインエンドポイントの設定

Dify のプラグイン管理ページで、新しくインストールしたテストプラグインを見つけ、新しいエンドポイントを作成します。名前と Bot Token を入力し、接続するアプリを選択します。
プラグインをテストする
保存すると、POST リクエスト URL が生成されます。
生成された POST リクエスト URL
次に、Slack App のセットアップを完了します。
  1. Event Subscriptions を有効にする
    Event Subscriptions を有効にする
    上記で生成した POST リクエスト URL を貼り付けます。
    上記で生成した POST リクエスト URL を貼り付ける
  2. 必要な権限を付与する
    必要な権限を付与する

4. プラグインの検証

プラグインは self.session.app.chat.invoke を通じて Dify アプリケーションを呼び出し、app_idquery などのパラメータを渡して、応答を Slack Bot に返します。python -m main を再度実行してプラグインを再起動し、Slack に Dify アプリの回答が表示されることを確認します。
Slack に Dify アプリの回答が表示される

5. プラグインのパッケージ化(オプション)

プラグインが正しく動作することを確認したら、以下のコマンドでパッケージ化します。このコマンドは、現在のディレクトリに slack_bot.difypkg ファイル、つまり最終的なプラグインパッケージを生成します。詳細なパッケージ化手順は、ローカルファイルとしてパッケージ化して共有 を参照してください。
# ./slack_bot を実際のプラグインプロジェクトパスに置き換えてください。

dify plugin package ./slack_bot
おめでとうございます。プラグインの開発、テスト、パッケージ化が完了しました。

6. プラグインの公開(オプション)

これで、Dify マーケットプレイスリポジトリ にアップロードして一般公開できます。公開前に、プラグインが Dify マーケットプレイス公開ガイドライン を満たしていることを確認してください。承認されると、コードはメインブランチにマージされ、プラグインは Dify マーケットプレイス で公開されます。

関連リソース

さらに読む

完全な Dify プラグインプロジェクトの例については、GitHub リポジトリ をご覧ください。完全なソースコードと実装の詳細を含む追加のプラグインも見つかります。 プラグイン開発についてさらに学ぶには、以下を参照してください。 クイックスタート プラグインインターフェースドキュメント
Last modified on June 25, 2026