Community研究&データ分析github.com

SystemTce/dify-skills

Dify プラグイン開発の完全ガイド。ツール、モデル、データソース、拡張の4種類のプラグインを網羅します。

dify-skills とは?

このスキルは、Dify プラグインシステムに関する包括的な開発ガイドを提供します。Beehive(ハイブ)アーキテクチャに基づき、分散スケジューリング、マスター選出、障害自己修復などの機能を備え、Local、Debug、Serverless の3つのランタイムモードをサポートします。Tool、Model、Datasource、Extension の4種類のプラグインの開発手法を詳しく解説しており、プラグインの初期化から実装、テスト、デプロイまでの全工程をカバーします。特に、dify CLI を用いたプロジェクト作成、Python SDK を利用したカスタムツール開発、OAuth 2.0 認証の統合、API からプラグインへの移行手順などが含まれています。開発者はこのスキルを参照することで、Dify プラットフォーム上でカスタムプラグインを効率的に開発し、多様なサービスと統合できるようになります。

対応✓Claude Code✓Codex CLI~Cursor✓Gemini CLI
npx skills add https://github.com/SystemTce/dify-skills/tree/main/02-plugin

Installed? Explore more 研究&データ分析 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Dify プラグイン開発 SKILL

概要

Dify プラグインシステムは、革新的な Beehive(ハイブ)アーキテクチャを採用しており、3つのランタイムモードと4種類のプラグインタイプをサポートし、開発者に強力な拡張機能を提供します。この SKILL は、初心者からエキスパートまで対応する完全なプラグイン開発ガイドです。

適用シーン

以下のようなシナリオでこの SKILL を使用します:

  • Dify プラグインの開発:ツール、モデル、データソース、拡張の4タイプ
  • サードパーティサービスとの統合:API ラッピング、OAuth 認証
  • カスタムツールの実装:AI 機能の拡張
  • Dify プラットフォーム機能の拡張:トリガー、Agent ポリシー
  • 既存 API のプラグインへの移行:API からプラグインへの変換
  • プラグインパフォーマンスのデバッグと最適化:パフォーマンスチューニングと問題解決

コアバリュー

  • Beehive アーキテクチャ:分散スケジューリング、マスター選出、障害自己修復
  • マルチランタイムサポート:Local、Debug、Serverless の3モード
  • 完全なツールチェーン:dify CLI、Python SDK、デバッグランタイム
  • 豊富なエコシステム:70+ のモデルプラグイン、20+ のツールプラグイン、18+ のデータソースプラグイン
  • プロダクションレベルの品質:OAuth 2.0、アクセス制御、モニタリングトレース

クイックスタート

1. 環境準備

# Python 3.12+ のインストール
python --version  # >= 3.12 を確認

# uv パッケージマネージャーのインストール(推奨)
curl -LsSf https://astral.sh/uv/install.sh | sh

# dify CLI のインストール
pip install dify-cli

# インストールの確認
dify --version

2. 最初のプラグインを作成

# プラグインプロジェクトの初期化
dify plugin init

# プラグインタイプの選択
? Select plugin type: Tool
? Plugin name: my_first_tool
? Author: your_name
? Description: My first Dify tool plugin

# プロジェクトディレクトリへ移動
cd my_first_tool

# 依存関係のインストール
uv pip install -r requirements.txt

3. プラグインロジックの実装

tools/my_tool.py を編集:

from typing import Any, Generator
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin import Tool


class MyTool(Tool):
    def _invoke(
        self, tool_parameters: dict[str, Any]
    ) -> Generator[ToolInvokeMessage, None, None]:
        """
        ツール呼び出しエントリポイント
        """
        # パラメータの取得
        text = tool_parameters.get("text", "")

        # 処理ロジック
        result = f"処理結果: {text.upper()}"

        # 結果を返す
        yield self.create_text_message(result)

4. ローカルデバッグ

# Debug Runtime の起動
dify plugin run

# Dify 画面でプラグインをテスト
# http://localhost:5001 にアクセス

5. パッケージ化とデプロイ

# プラグインのパッケージ化
dify plugin package

# my_first_tool.difypkg ファイルが生成される
# Dify Marketplace またはプライベートデプロイにアップロード

コアコンセプト

Beehive アーキテクチャ

Dify プラグインシステムは Beehive(ハイブ)アーキテクチャを採用しており、その中核的特徴は以下の通りです:

  1. 分散スケジューリング:各デーモンプロセスノードがローカルプラグインを独立して管理
  2. マスター選出:Redis 分散ロックによる自動マスターノード選出
  3. 状態同期:全ノードの状態を Redis に保存し、ノード間アクセスをサポート
  4. 障害自己修復:ノードダウン時にプラグインを自動再割り当て

詳細なアーキテクチャ説明は types/architecture.md を参照してください。

3つのランタイムモード

ランタイムモード適用シーン通信方式利点欠点
Local Runtimeローカル開発、小規模デプロイSTDIN/STDOUT低レイテンシ、リソース分離メモリ消費大、拡張性に制限
Debug Runtimeリモートデバッグ、開発環境TCP 全二重開発フレンドリー、柔軟なデプロイネットワーク依存、状態管理が複雑
Serverless Runtime大規模本番環境HTTP/SSE自動スケーリング、コスト最適化コールドスタート遅延、デバッグが複雑

詳細な比較は development/runtime-modes.md を参照してください。

4種類のプラグインタイプ

1. Tool(ツールプラグイン)

翻訳、検索、データ処理など、AI の機能を拡張するツールです。

# 例:Google Translate
type: plugin
plugins:
  tools:
    - provider/google_translate.yaml

使用シーン:

  • API ラッピング(REST API → Tool)
  • データ処理(形式変換、計算)
  • 外部サービス統合(検索、翻訳)

2. Model(モデルプラグイン)

Anthropic、OpenAI、Gemini などの LLM プロバイダーに接続します。

# 例:Anthropic Claude
type: plugin
plugins:
  models:
    - provider/anthropic.yaml

使用シーン:

  • 新しい LLM プロバイダーへの接続
  • カスタムモデル設定
  • マルチモーダルモデルサポート

3. Datasource(データソースプラグイン)

S3、Google Drive、Notion などのストレージシステムに接続します。

# 例:AWS S3
type: plugin
plugins:
  datasources:
    - provider/aws_s3.yaml

使用シーン:

  • クラウドストレージ統合
  • ドキュメントプラットフォームへの接続
  • データベースアクセス

4. Extension(拡張プラグイン)

Slack、企業微信などのサードパーティプラットフォーム統合など、プラットフォーム機能を拡張します。

# 例:Slack
type: plugin
plugins:
  extensions:
    - provider/slack.yaml

使用シーン:

  • サードパーティプラットフォーム統合
  • トリガーの実装
  • カスタム Agent ポリシー

各タイプの詳細は types/ を参照してください。


プロジェクト構成

標準的な Dify プラグインプロジェクトの構成:

my_plugin/
├── manifest.yaml           # プラグインマニフェスト(必須)
├── main.py                 # エントリファイル(必須)
├── requirements.txt        # Python 依存関係
├── pyproject.toml         # プロジェクト設定
├── README.md              # プラグイン説明
├── PRIVACY.md             # プライバシーポリシー(OAuth が必要な場合)
├── .env.example           # 環境変数サンプル
│
├── _assets/               # リソースファイル
│   └── icon.svg          # プラグインアイコン
│
├── provider/              # プロバイダー設定
│   ├── provider_name.yaml # プロバイダー設定ファイル
│   └── provider_name.py   # プロバイダー実装
│
└── tools/                 # ツール実装(Tool プラグイン)
    ├── tool_name.yaml    # ツール設定ファイル
    └── tool_name.py      # ツール実装

コアファイルの説明

manifest.yaml

プラグインの基本情報と設定を定義するマニフェストファイル:

author: your_name
name: my_plugin
version: 0.0.1
type: plugin

description:
  en_US: Plugin description
  zh_Hans: プラグイン説明

label:
  en_US: My Plugin
  zh_Hans: マイプラグイン

icon: icon.svg

meta:
  version: 0.0.1
  arch:
    - amd64
    - arm64
  runner:
    language: python
    version: '3.12'
    entrypoint: main

plugins:
  tools:
    - provider/my_provider.yaml

resource:
  memory: 1048576  # 1MB = 1048576 bytes
  permission:
    tool:
      enabled: true
    model:
      enabled: true
      llm: true

tags:
  - utilities

詳細設定は development/manifest.md を参照してください。

main.py

プラグインエントリファイル:

from dify_plugin import Plugin, DifyPluginEnv

# プラグインインスタンスの作成
plugin = Plugin(DifyPluginEnv(MAX_REQUEST_TIMEOUT=120))

if __name__ == '__main__':
    # プラグインの起動
    plugin.run()

開発ガイド

Tool プラグイン開発

1. Provider の作成

provider/my_provider.yaml を編集:

identity:
  author: your_name
  name: my_provider
  label:
    en_US: My Provider
    zh_Hans: マイプロバイダー
  description:
    en_US: Provider description
    zh_Hans: プロバイダー説明
  icon: icon.svg
  tags:
    - utilities

extra:
  python:
    source: provider/my_provider.py

tools:
  - tools/my_tool.yaml

provider/my_provider.py を編集:

from typing import Any
from dify_plugin.errors.tool import ToolProviderCredentialValidationError
from dify_plugin import ToolProvider
from tools.my_tool import MyTool


class MyProvider(ToolProvider):
    def _validate_credentials(self, credentials: dict[str, Any]) -> None:
        """
        資格情報の検証(必要な場合)
        """
        try:
            # API Key などの資格情報を検証
            api_key = credentials.get("api_key")
            if not api_key:
                raise ToolProviderCredentialValidationError("API Key is required")

            # 資格情報の有効性テスト
            MyTool().invoke(
                tool_parameters={"text": "test"}
            )
        except Exception as e:
            raise ToolProviderCredentialValidationError(str(e))

2. Tool の作成

tools/my_tool.yaml を編集:

identity:
  author: your_name
  name: my_tool
  label:
    en_US: My Tool
    zh_Hans: マイツール

description:
  human:
    en_US: Tool description for humans
    zh_Hans: 人間向けのツール説明
  llm: Tool description for LLM

extra:
  python:
    source: tools/my_tool.py

parameters:
  - name: text
    type: string
    required: true
    label:
      en_US: Input Text
      zh_Hans: 入力テキスト
    human_description:
      en_US: The text to process
      zh_Hans: 処理するテキスト
    llm_description: The input text to be processed
    form: llm

tools/my_tool.py を編集:

from typing import Any, Generator
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin import Tool


class MyTool(Tool):
    def _invoke(
        self, tool_parameters: dict[str, Any]
    ) -> Generator[ToolInvokeMessage, None, None]:
        """
        ツール呼び出しエントリポイント

        Args:
            tool_parameters: ツールパラメータの辞書

        Yields:
            ToolInvokeMessage: ツール呼び出しメッセージ
        """
        # 1. パラメータの取得
        text = tool_parameters.get("text", "")

        if not text:
            yield self.create_text_message("Error: text parameter is required")
            return

        try:
            # 2. 処理ロジック
            result = self._process_text(text)

            # 3. 結果を返す
            yield self.create_text_message(result)

        except Exception as e:
            yield self.create_text_message(f"Error: {str(e)}")

    def _process_text(self, text: str) -> str:
        """
        テキスト処理の具体的なロジック
        """
        return text.upper()

詳細な開発ガイドは development/tool.md を参照してください。


OAuth 2.0 統合

OAuth フロー概要

Dify は完全な OAuth 2.0 認可フローをサポートしています:

  1. 認可 URL の取得:ユーザーが認可ボタンをクリック
  2. ユーザー認可:サードパーティサービスの認可ページにリダイレクト
  3. 認可コードの取得:ユーザー認可後に認可コードが返される
  4. アクセストークンの交換:認可コードを使用してアクセストークンを取得
  5. トークンのリフレッシュ:アクセストークン期限切れ時にリフレッシュトークンを使用して新しいトークンを取得

OAuth スキーマの設定

provider/my_provider.yaml に OAuth 設定を追加:

oauth_schema:
  client_schema:
    - name: client_id
      type: secret-input
      required: true
      label:
        en_US: Client ID
        zh_Hans: クライアント ID
      placeholder:
        en_US: Enter your OAuth Client ID
        zh_Hans: OAuth クライアント ID を入力
      help:
        en_US: Get your client ID from the service provider
        zh_Hans: サービスプロバイダーからクライアント ID を取得
      url: https://console.example.com/credentials

    - name: client_secret
      type: secret-input
      required: true
      label:
        en_US: Client Secret
        zh_Hans: クライアントシークレット
      placeholder:
        en_US: Enter your OAuth Client Secret
        zh_Hans: OAuth クライアントシークレットを入力

  credentials_schema:
    - name: access_token
      type: secret-input
      label:
        en_US: Access Token
        zh_Hans: アクセストークン

    - name: refresh_token
      type: secret-input
      label:
        en_US: Refresh Token
        zh_Hans: リフレッシュトークン

OAuth Provider の実装

from typing import Any
from dify_plugin import ToolProvider
from dify_plugin.errors.tool import ToolProviderCredentialValidationError
import requests


class MyOAuthProvider(ToolProvider):
    def _validate_credentials(self, credentials: dict[str, Any]) -> None:
        """
        OAuth 資格情報の検証
        """
        access_token = credentials.get("access_token")
        if not access_token:
            raise ToolProviderCredentialValidationError(
                "Access token is required"
            )

        # アクセストークンの有効性テスト
        try:
            response = requests.get(
                "https://api.example.com/user",
                headers={"Authorization": f"Bearer {access_token}"}
            )
            response.raise_for_status()
        except Exception as e:
            raise ToolProviderCredentialValidationError(
                f"Invalid access token: {str(e)}"
            )

OAuth トークンの使用

ツール内で OAuth トークンを使用:

class MyOAuthTool(Tool):
    def _invoke(
        self, tool_parameters: dict[str, Any]
    ) -> Generator[ToolInvokeMessage, None, None]:
        # OAuth 資格情報を取得
        credentials = self.runtime.credentials
        access_token = credentials.get("access_token")

        # API を呼び出す
        response = requests.get(
            "https://api.example.com/data",
            headers={"Authorization": f"Bearer {access_token}"}
        )

        yield self.create_text_message(response.text)

完全な OAuth 統合ガイドは development/oauth-integration.md を参照してください。


テストとデバッグ

ユニットテスト

pytest を使用してユニットテストを作成:

# tests/test_my_tool.py
import pytest
from tools.my_tool import MyTool


def test_my_tool():
    tool = MyTool()
    result = list(tool.invoke(tool_parameters={"text": "hello"}))

    assert len(result) == 1
    assert "HELLO" in result[0].message

テストを実行:

pytest tests/

統合テスト

Dify システムとの統合テスト:

# tests/test_integration.py
def test_plugin_integration():
    # プラグインのインストールテスト
    # ツール呼び出しテスト
    # OAuth フローテスト
    pass

Debug Runtime デバッグ

Debug Runtime を起動してリモートデバッグ:

# Debug Runtime の起動
dify plugin run --debug

# Dify 画面でテスト
# リアルタイムログとエラー情報を確認

一般的な問題のトラブルシューティング

プラグイン起動失敗

  • Python バージョンを確認(3.12+ が必要)
  • 依存関係のインストールを確認(requirements.txt)
  • manifest.yaml の設定を確認
  • エントリファイルのパスを確認(main.py)

権限検証失敗

  • credentials の設定を確認
  • OAuth トークンの有効期限を確認
  • API Key の有効性を確認
  • 権限宣言を確認(resource.permission)

ランタイムエラー

  • タイムアウト時間を調整(MAX_REQUEST_TIMEOUT)
  • メモリ使用量を最適化(resource.memory)
  • ネットワーク接続を確認
  • リバースコール権限を確認

詳細なトラブルシューティングガイドは testing/troubleshooting.md を参照してください。


API からプラグインへの移行

移行戦略

  1. API ラッピングパターン:REST API を Tool プラグインとしてラップ
  2. SDK 統合パターン:サードパーティ Python SDK の使用
  3. OAuth 移行:OAuth 2.0 認可フローの実装
  4. バッチ操作の最適化:ストリームレスポンスを使用した大規模データ処理

移行手順

  1. 既存 API の分析

    • API エンドポイントとパラメータ
    • 認証方式(API Key / OAuth)
    • レスポンス形式とエラー処理
  2. プラグインタイプの選択

    • REST API → Tool プラグイン
    • LLM API → Model プラグイン
    • ストレージ API → Datasource プラグイン
  3. プラグインプロジェクトの作成

    dify plugin init
    
  4. API 呼び出しの実装

    import requests
    
    class APIWrapperTool(Tool):
        def _invoke(self, tool_parameters: dict[str, Any]):
            response = requests.post(
                "https://api.example.com/endpoint",
                json=tool_parameters,
                headers={"Authorization": f"Bearer {api_key}"}
            )
            yield self.create_text_message(response.text)
    
  5. 認証の設定

    • API Key:provider.yaml で credentials を設定
    • OAuth:oauth_schema を設定
  6. エラー処理の追加

    try:
        response = requests.post(...)
        response.raise_for_status()
    except requests.exceptions.RequestException as e:
        yield self.create_text_message(f"API Error: {str(e)}")
    
  7. テストの作成

    def test_api_wrapper():
        tool = APIWrapperTool()
        result = list(tool.invoke(tool_parameters={...}))
        assert result[0].message
    
  8. パッケージ化とデプロイ

    dify plugin package
    

実際のケース

  • REST API → Tool:Google Translate(認証なし)
  • OAuth API → Tool:Google Contacts(OAuth 2.0)
  • LLM API → Model:Anthropic Claude(API Key)
  • ストレージ API → Datasource:AWS S3(IAM 認証)

詳細な移行ガイドは development/migration-guide.md を参照してください。


ベストプラクティス

コード構成

  1. 単一責任:各 Tool は1つのことだけを行う
  2. エラー処理:すべての例外をキャッチし、ユーザーフレンドリーなエラーメッセージを返す
  3. パラメータ検証:_invoke の開始時にすべてのパラメータを検証
  4. ログ記録:構造化ログを使用して重要な操作を記録

パフォーマンス最適化

  1. ストリームレスポンス:大規模データには Generator を使用したストリーム返却
  2. キャッシュ戦略:頻繁にアクセスするデータをキャッシュ
  3. 非同期処理:I/O バウンドな操作には async/await を使用
  4. リソース制限:resource.memory を適切に設定

セキュリティ考慮事項

  1. 入力検証:すべてのユーザー入力を検証
  2. 機密データ:機密情報は secret-input タイプで保存
  3. アクセス制御:最小権限の原則に従い、必要な権限のみを宣言
  4. エラーメッセージ:エラーメッセージに機密データを含めない

ユーザーエクスペリエンス

  1. 明確な説明:詳細な description と help を提供
  2. 適切なデフォルト値:パラメータに適切なデフォルト値を設定
  3. 多言語サポート:少なくとも en_US と zh_Hans をサポート
  4. ユーザーフレンドリーなエラー:ユーザーが理解できるエラーメッセージを返す

デプロイと運用

ランタイムモードの選択

シーン推奨モード理由
ローカル開発Local Runtime低レイテンシ、デバッグ容易
リモートデバッグDebug Runtime柔軟、リモートサポート
小規模本番Local Runtimeシンプル、低コスト
大規模本番Serverless Runtime自動スケーリング、高可用性

Serverless デプロイ

AWS Lambda へのデプロイ:

# 1. プラグインのパッケージ化
dify plugin package

# 2. Lambda 関数の作成
aws lambda create-function \
  --function-name my-plugin \
  --runtime python3.12 \
  --handler main.handler \
  --zip-file fileb://my_plugin.difypkg

# 3. 環境変数の設定
aws lambda update-function-configuration \
  --function-name my-plugin \
  --environment Variables={...}

# 4. API Gateway の設定
# 詳細は Serverless デプロイガイドを参照

監視とログ

  1. ログ記録

    import logging
    
    logger = logging.getLogger(__name__)
    logger.info("Tool invoked with parameters: %s", tool_parameters)
    
  2. メトリクス収集

    • 呼び出し回数
    • 応答時間
    • エラー率
    • メモリ使用量
  3. アラート設定

    • エラー率の閾値
    • 応答時間の閾値
    • リソース使用量の閾値

バージョン管理とアップデート

  1. セマンティックバージョニング

    • メジャー:互換性のない変更
    • マイナー:後方互換性のある機能追加
    • パッチ:バグ修正
  2. 更新手順

    • manifest.yaml のバージョン更新
    • 変更ログの記録
    • テストの実行
    • パッケージ化と再デプロイ
# プラグインの更新
dify plugin package --version 0.0.2

詳細なデプロイガイドは deployment/ を参照してください。


参考リンク


この SKILL は Dify プラグイン開発者向けの包括的なガイドです。開発サイクル全体を通して参照し、高品質なプラグインを効率的に開発してください。

Individual skills in this repo

This repo contains 5 individual skills — each has its own dedicated page.

関連スキル