Dify Plugin-Entwicklung SKILL
Überblick
Das Dify Plugin-System verwendet die innovative Beehive-Architektur (Bienenstock-Architektur) und unterstützt drei Laufzeitmodi. Es bietet vier Plugin-Typen und bietet Entwicklern leistungsstarke Erweiterungsmöglichkeiten. Dieses SKILL bietet einen vollständigen Leitfaden zur Plugin-Entwicklung vom Anfänger bis zum Fortgeschrittenen.
Anwendungsszenarien
Verwenden Sie dieses SKILL in den folgenden Szenarien:
- Entwicklung von Dify-Plugins: Die vier Typen Werkzeug, Modell, Datenquelle und Erweiterung
- Integration von Drittanbieterdiensten: API-Wrapper, OAuth-Autorisierung
- Implementierung benutzerdefinierter Werkzeuge: Erweiterung der KI-Fähigkeiten
- Erweiterung der Dify-Plattformfunktionen: Trigger, Agent-Strategien
- Migration bestehender APIs zu Plugins: API-zu-Plugin-Konvertierung
- Debugging und Optimierung der Plugin-Leistung: Leistungsoptimierung und Fehlerbehebung
Kernwerte
- Beehive-Architektur: Dezentrale Orchestrierung, Master-Wahl, Selbstheilung
- Mehrere Laufzeitmodi: Lokal, Debug, Serverless – drei Modi
- Vollständige Toolchain:
difyCLI, Python SDK, Debug-Laufzeit - Reichhaltiges Ökosystem: 70+ Modell-Plugins, 20+ Werkzeug-Plugins, 18+ Datenquellen-Plugins
- Produktionsqualität: OAuth 2.0, Zugriffskontrolle, Monitoring und Tracing
Kurzanleitung
1. Umgebungsvorbereitung
# Installieren Sie Python 3.12+
python --version # Stellen Sie sicher, dass >= 3.12
# Installieren Sie den uv-Paketmanager (empfohlen)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Installieren Sie die dify CLI
pip install dify-cli
# Überprüfen Sie die Installation
dify --version
2. Erstellen des ersten Plugins
# Initialisieren Sie ein Plugin-Projekt
dify plugin init
# Wählen Sie den Plugin-Typ
? Select plugin type: Tool
? Plugin name: my_first_tool
? Author: your_name
? Description: My first Dify tool plugin
# Wechseln Sie in das Projektverzeichnis
cd my_first_tool
# Installieren Sie Abhängigkeiten
uv pip install -r requirements.txt
3. Implementieren der Plugin-Logik
Bearbeiten Sie 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]:
"""
Werkzeugaufruf-Einstiegspunkt
"""
# Parameter abrufen
text = tool_parameters.get("text", "")
# Verarbeitungslogik
result = f"Verarbeitungsergebnis: {text.upper()}"
# Ergebnis zurückgeben
yield self.create_text_message(result)
4. Lokales Debugging
# Debug-Laufzeit starten
dify plugin run
# Plugin in der Dify-Oberfläche testen
# Zugriff unter http://localhost:5001
5. Paketieren und Bereitstellen
# Plugin paketieren
dify plugin package
# Erzeugt die Datei my_first_tool.difypkg
# Hochladen in den Dify Marketplace oder zur privaten Bereitstellung
Kernkonzepte
Beehive-Architektur
Das Dify Plugin-System verwendet die Beehive-Architektur mit den folgenden Kernmerkmalen:
- Dezentrale Orchestrierung: Jeder Daemon-Knoten verwaltet lokale Plugins unabhängig
- Master-Wahl: Automatische Master-Wahl über Redis Distributed Lock
- Zustandssynchronisation: Der Zustand aller Knoten wird in Redis gespeichert und ermöglicht knotenübergreifenden Zugriff
- Selbstheilung: Bei Knotenausfall werden Plugins automatisch neu zugewiesen
Eine detaillierte Architekturbeschreibung finden Sie unter: types/architecture.md
Drei Laufzeitmodi
| Laufzeitmodus | Anwendungsszenario | Kommunikationsmethode | Vorteile | Nachteile |
|---|---|---|---|---|
| Local Runtime | Lokale Entwicklung, kleine Bereitstellungen | STDIN/STDOUT | Niedrige Latenz, Ressourcenisolierung | Hoher Speicherverbrauch, begrenzte Skalierbarkeit |
| Debug Runtime | Remote-Debugging, Entwicklungsumgebung | TCP Vollduplex | Entwicklerfreundlich, flexible Bereitstellung | Netzwerkabhängigkeit, komplexe Zustandsverwaltung |
| Serverless Runtime | Große Produktionsumgebungen | HTTP/SSE | Automatische Skalierung, Kostenoptimierung | Kaltstart-Latenz, komplexes Debugging |
Ein detaillierter Vergleich finden Sie unter: development/runtime-modes.md
Vier Plugin-Typen
1. Tool (Werkzeug-Plugin)
Werkzeuge zur Erweiterung der KI-Fähigkeiten, z. B. Übersetzung, Suche, Datenverarbeitung.
# Beispiel: Google Translate
type: plugin
plugins:
tools:
- provider/google_translate.yaml
Anwendungsszenarien:
- API-Wrapper (REST API → Tool)
- Datenverarbeitung (Formatkonvertierung, Berechnung)
- Integration externer Dienste (Suche, Übersetzung)
2. Model (Modell-Plugin)
Anbindung von LLM-Anbietern wie Anthropic, OpenAI, Gemini usw.
# Beispiel: Anthropic Claude
type: plugin
plugins:
models:
- provider/anthropic.yaml
Anwendungsszenarien:
- Anbindung neuer LLM-Anbieter
- Benutzerdefinierte Modellkonfiguration
- Unterstützung multimodaler Modelle
3. Datasource (Datenquellen-Plugin)
Anbindung von Speichersystemen wie S3, Google Drive, Notion usw.
# Beispiel: AWS S3
type: plugin
plugins:
datasources:
- provider/aws_s3.yaml
Anwendungsszenarien:
- Cloud-Speicher-Integration
- Verbindung zu Dokumentenplattformen
- Datenbankzugriff
4. Extension (Erweiterungs-Plugin)
Erweiterung der Plattformfunktionen, z. B. Integration von Drittanbieterplattformen wie Slack, WeChat Work.
# Beispiel: Slack
type: plugin
plugins:
extensions:
- provider/slack.yaml
Anwendungsszenarien:
- Integration von Drittanbieterplattformen
- Implementierung von Triggern
- Benutzerdefinierte Agent-Strategien
Eine detaillierte Typbeschreibung finden Sie unter: types/
Projektstruktur
Die Standardstruktur eines Dify Plugin-Projekts:
my_plugin/
├── manifest.yaml # Plugin-Manifest (erforderlich)
├── main.py # Einstiegspunkt (erforderlich)
├── requirements.txt # Python-Abhängigkeiten
├── pyproject.toml # Projektkonfiguration
├── README.md # Plugin-Beschreibung
├── PRIVACY.md # Datenschutzerklärung (falls OAuth erforderlich)
├── .env.example # Beispiel für Umgebungsvariablen
│
├── _assets/ # Ressourcendateien
│ └── icon.svg # Plugin-Symbol
│
├── provider/ # Anbieterkonfiguration
│ ├── provider_name.yaml # Konfigurationsdatei des Anbieters
│ └── provider_name.py # Implementierung des Anbieters
│
└── tools/ # Werkzeugimplementierung (Tool-Plugin)
├── tool_name.yaml # Werkzeugkonfigurationsdatei
└── tool_name.py # Werkzeugimplementierung
Beschreibung der Kerndateien
manifest.yaml
Die Plugin-Manifestdatei definiert die grundlegenden Informationen und die Konfiguration des Plugins:
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 # 1 MB = 1048576 Bytes
permission:
tool:
enabled: true
model:
enabled: true
llm: true
tags:
- utilities
Eine detaillierte Konfigurationsbeschreibung finden Sie unter: development/manifest.md
main.py
Plugin-Einstiegspunkt:
from dify_plugin import Plugin, DifyPluginEnv
# Plugin-Instanz erstellen
plugin = Plugin(DifyPluginEnv(MAX_REQUEST_TIMEOUT=120))
if __name__ == '__main__':
# Plugin starten
plugin.run()
Entwicklungsleitfaden
Entwicklung von Tool-Plugins
1. Erstellen eines Anbieters
Bearbeiten Sie 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
Bearbeiten Sie 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:
"""
Anmeldeinformationen validieren (falls erforderlich)
"""
try:
# API-Schlüssel oder andere Anmeldeinformationen validieren
api_key = credentials.get("api_key")
if not api_key:
raise ToolProviderCredentialValidationError("API Key is required")
# Gültigkeit der Anmeldeinformationen testen
MyTool().invoke(
tool_parameters={"text": "test"}
)
except Exception as e:
raise ToolProviderCredentialValidationError(str(e))
2. Erstellen eines Werkzeugs
Bearbeiten Sie 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
Bearbeiten Sie 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]:
"""
Werkzeugaufruf-Einstiegspunkt
Args:
tool_parameters: Dictionary der Werkzeugparameter
Yields:
ToolInvokeMessage: Werkzeugaufruf-Nachricht
"""
# 1. Parameter abrufen
text = tool_parameters.get("text", "")
if not text:
yield self.create_text_message("Error: text parameter is required")
return
try:
# 2. Verarbeitungslogik
result = self._process_text(text)
# 3. Ergebnis zurückgeben
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:
"""
Spezifische Logik zur Textverarbeitung
"""
return text.upper()
Eine detaillierte Entwicklungsanleitung finden Sie unter: development/tool.md
OAuth 2.0-Integration
OAuth-Ablauf Übersicht
Dify unterstützt den vollständigen OAuth 2.0-Autorisierungsablauf:
- Autorisierungs-URL abrufen: Der Benutzer klickt auf die Autorisierungsschaltfläche
- Benutzerautorisierung: Weiterleitung zur Autorisierungsseite des Drittanbieters
- Autorisierungscode abrufen: Nach der Autorisierung des Benutzers wird der Autorisierungscode zurückgegeben
- Access-Token austauschen: Verwendung des Autorisierungscodes zum Austausch gegen ein Access-Token
- Token aktualisieren: Bei Ablauf des Access-Tokens wird das Refresh-Token verwendet, um ein neues Token zu erhalten
Konfigurieren des OAuth-Schemas
Fügen Sie in provider/my_provider.yaml die OAuth-Konfiguration hinzu:
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: 刷新令牌
Implementieren eines OAuth-Anbieters
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-Anmeldeinformationen validieren
"""
access_token = credentials.get("access_token")
if not access_token:
raise ToolProviderCredentialValidationError(
"Access token is required"
)
# Gültigkeit des Access-Tokens testen
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)}"
)
Verwenden von OAuth-Tokens
Verwenden von OAuth-Tokens in einem Tool:
class MyOAuthTool(Tool):
def _invoke(
self, tool_parameters: dict[str, Any]
) -> Generator[ToolInvokeMessage, None, None]:
# OAuth-Anmeldeinformationen abrufen
credentials = self.runtime.credentials
access_token = credentials.get("access_token")
# API aufrufen
response = requests.get(
"https://api.example.com/data",
headers={"Authorization": f"Bearer {access_token}"}
)
yield self.create_text_message(response.text)
Eine vollständige Anleitung zur OAuth-Integration finden Sie unter: development/oauth-integration.md
Testen und Debugging
Unit-Tests
Schreiben von Unit-Tests mit 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
Tests ausführen:
pytest tests/
Integrationstests
Testen der Integration des Plugins mit dem Dify-System:
# tests/test_integration.py
def test_plugin_integration():
# Plugin-Installation testen
# Werkzeugaufruf testen
# OAuth-Ablauf testen
pass
Debuggen mit der Debug-Laufzeit
Starten der Debug-Laufzeit für Remote-Debugging:
# Debug-Laufzeit starten
dify plugin run --debug
# In der Dify-Oberfläche testen
# Live-Logs und Fehlermeldungen anzeigen
Fehlerbehebung bei häufigen Problemen
Plugin-Start fehlgeschlagen
- Python-Version überprüfen (3.12+ erforderlich)
- Abhängigkeitsinstallation überprüfen (
requirements.txt) manifest.yaml-Konfiguration überprüfen- Pfad der Einstiegspunktdatei überprüfen (
main.py)
Berechtigungsvalidierung fehlgeschlagen
credentials-Konfiguration überprüfen- Überprüfen, ob OAuth-Token abgelaufen ist
- Überprüfen, ob der API-Schlüssel gültig ist
- Berechtigungsdeklaration überprüfen (
resource.permission)
Laufzeitfehler
- Timeout-Wert anpassen (
MAX_REQUEST_TIMEOUT) - Speichernutzung optimieren (
resource.memory) - Netzwerkverbindung überprüfen
- Rückrufberechtigungen überprüfen
Eine detaillierte Anleitung zur Fehlerbehebung finden Sie unter: testing/troubleshooting.md
Migration von APIs zu Plugins
Migrationsstrategie
- API-Wrapper-Modus: REST-API als Tool-Plugin kapseln
- SDK-Integrationsmodus: Verwendung eines Python SDK eines Drittanbieters
- OAuth-Migration: Implementierung des OAuth 2.0-Autorisierungsablaufs
- Batch-Verarbeitungsoptimierung: Verwendung von Streaming-Antworten für große Datenmengen
Migrationsschritte
-
Vorhandene API analysieren
- API-Endpunkte und Parameter
- Authentifizierungsmethode (API-Key / OAuth)
- Antwortformat und Fehlerbehandlung
-
Plugin-Typ auswählen
- REST API → Tool-Plugin
- LLM API → Model-Plugin
- Storage API → Datasource-Plugin
-
Plugin-Projekt erstellen
dify plugin init -
API-Aufruf implementieren
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) -
Authentifizierung konfigurieren
- API-Key:
credentialsinprovider.yamlkonfigurieren - OAuth:
oauth_schemakonfigurieren
- API-Key:
-
Fehlerbehandlung hinzufügen
try: response = requests.post(...) response.raise_for_status() except requests.exceptions.RequestException as e: yield self.create_text_message(f"API Error: {str(e)}") -
Tests schreiben
def test_api_wrapper(): tool = APIWrapperTool() result = list(tool.invoke(tool_parameters={...})) assert result[0].message -
Paketieren und bereitstellen
dify plugin package
Praxisbeispiele
- REST API → Tool: Google Translate (keine Authentifizierung)
- OAuth API → Tool: Google Contacts (OAuth 2.0)
- LLM API → Model: Anthropic Claude (API-Key)
- Storage API → Datasource: AWS S3 (IAM-Authentifizierung)
Eine detaillierte Migrationsanleitung finden Sie unter: development/migration-guide.md
Bewährte Methoden
Code-Organisation
- Einzelverantwortung: Jedes Tool macht nur eine Sache
- Fehlerbehandlung: Alle Ausnahmen abfangen und benutzerfreundliche Fehlermeldungen zurückgeben
- Parametervalidierung: Alle Parameter zu Beginn von
_invokevalidieren - Protokollierung: Strukturierte Protokollierung für kritische Vorgänge
Leistungsoptimierung
- Streaming-Antworten: Verwendung von Generator für Streaming großer Datenmengen
- Cache-Strategie: Häufig abgerufene Daten zwischenspeichern
- Asynchrone Verarbeitung: Verwendung von async/await für I/O-intensive Vorgänge
- Ressourcenbeschränkungen:
resource.memoryangemessen konfigurieren
Sicherheitsaspekte
- Eingabevalidierung: Alle Benutzereingaben validieren
- Sensible Daten: Verwendung von
secret-inputfür die Speicherung sensibler Informationen - Zugriffskontrolle: Prinzip der minimalen Berechtigung, nur notwendige Berechtigungen deklarieren
- Fehlermeldungen: Keine sensiblen Daten in Fehlermeldungen preisgeben
Benutzererfahrung
- Klare Beschreibungen: Bereitstellung detaillierter
descriptionundhelp - Sinnvolle Standardwerte: Bereitstellung sinnvoller Standardwerte für Parameter
- Mehrsprachige Unterstützung: Mindestens
en_USundzh_Hansunterstützen - Benutzerfreundliche Fehler: Rückgabe von für den Benutzer verständlichen Fehlermeldungen
Bereitstellung und Betrieb
Auswahl des Laufzeitmodus
| Szenario | Empfohlener Modus | Grund |
|---|---|---|
| Lokale Entwicklung | Local Runtime | Niedrige Latenz, einfaches Debugging |
| Remote-Debugging | Debug Runtime | Flexibel, Remote-Unterstützung |
| Kleine Produktion | Local Runtime | Einfach, geringe Kosten |
| Große Produktion | Serverless Runtime | Automatische Skalierung, hohe Verfügbarkeit |
Serverless-Bereitstellung
Bereitstellung auf AWS Lambda:
# 1. Plugin paketieren
dify plugin package
# 2. Lambda-Funktion erstellen
aws lambda create-function \
--function-name my-plugin \
--runtime python3.12 \
--handler main.handler \
--zip-file fileb://my_plugin.difypkg
# 3. Umgebungsvariablen konfigurieren
aws lambda update-function-configuration \
--function-name my-plugin \
--environment Variables={...}
Überwachung und Protokollierung
- Strukturierte Protokollierung: Verwendung von JSON-Format für Logs
- Metriken erfassen: Latenz, Fehlerrate, Speichernutzung
- Alarme einrichten: Alarme für anormales Verhalten konfigurieren
- Tracing verteilter Systeme: Implementierung von verteiltem Tracing für komplexe Workflows
Anhang
Referenzen
- Beehive-Architektur
- Laufzeitmodi
- Plugin-Typen
- Manifest-Konfiguration
- Werkzeugentwicklung
- OAuth-Integration
- Dokumentation zur Plugin-Umgebung
- Reverse-API-Dokumentation
- Ressourcenverwaltung
- Migrationsleitfaden
- Fehlerbehebung