From d951f5ddd9fc5561ece5d25863fd87b233b82fb6 Mon Sep 17 00:00:00 2001 From: crazywoola <427733928@qq.com> Date: Wed, 10 Jun 2026 13:34:20 +0800 Subject: [PATCH 1/2] docs: improve readability across develop-plugin section Editorial pass over all 39 pages in en/develop-plugin/: removed machine-translation artifacts and translator notes, rewrote awkward phrasing into direct natural English, normalized headings to title case and imperative form, converted blockquote callouts to Mintlify components, applied the bold-label list pattern to field references, tightened bloated frontmatter descriptions, and fixed mechanical formatting (list markers, blank lines, em dashes, code fence tags). No technical content changed: commands, YAML keys/values, code logic, URLs, and behavior claims are preserved verbatim; code blocks were touched only for comment/docstring grammar. Co-Authored-By: Claude Fable 5 --- .../agent-strategy-plugin.mdx | 132 ++++---- .../cheatsheet.mdx | 53 ++-- .../creating-new-model-provider.mdx | 110 ++++--- .../datasource-plugin.mdx | 50 +-- .../develop-a-slack-bot-plugin.mdx | 123 ++++---- .../develop-flomo-plugin.mdx | 42 +-- .../develop-md-exporter.mdx | 64 ++-- ...evelop-multimodal-data-processing-tool.mdx | 78 ++--- .../dev-guides-and-walkthroughs/endpoint.mdx | 69 ++--- .../tool-oauth.mdx | 63 ++-- .../tool-plugin.mdx | 187 ++++++------ .../trigger-plugin.mdx | 83 +++-- .../advanced-development/bundle.mdx | 55 ++-- .../customizable-model.mdx | 98 +++--- .../reverse-invocation-app.mdx | 34 +-- .../reverse-invocation-model.mdx | 69 ++--- .../reverse-invocation-node.mdx | 32 +- .../reverse-invocation-tool.mdx | 44 ++- .../reverse-invocation.mdx | 25 +- .../plugin-types/general-specifications.mdx | 161 +++++----- .../plugin-types/model-designing-rules.mdx | 284 +++++++++--------- .../plugin-types/model-schema.mdx | 181 ++++++----- .../plugin-types/multilingual-readme.mdx | 6 +- .../plugin-types/persistent-storage-kv.mdx | 18 +- .../plugin-types/plugin-info-by-manifest.mdx | 53 ++-- .../plugin-types/plugin-logging.mdx | 11 +- .../plugin-types/remote-debug-a-plugin.mdx | 10 +- .../features-and-specs/plugin-types/tool.mdx | 58 ++-- .../getting-started/choose-plugin-type.mdx | 10 +- en/develop-plugin/getting-started/cli.mdx | 34 +-- .../getting-started-dify-plugin.mdx | 12 +- en/develop-plugin/publishing/faq/faq.mdx | 10 +- .../plugin-auto-publish-pr.mdx | 154 +++++----- .../marketplace-listing/release-by-file.mdx | 10 +- .../marketplace-listing/release-overview.mdx | 6 +- .../release-to-dify-marketplace.mdx | 16 +- .../release-to-individual-github-repo.mdx | 30 +- .../privacy-protection-guidelines.mdx | 22 +- .../third-party-signature-verification.mdx | 8 +- 39 files changed, 1204 insertions(+), 1301 deletions(-) diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/agent-strategy-plugin.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/agent-strategy-plugin.mdx index 679a0f0ef..afc0ef909 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/agent-strategy-plugin.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/agent-strategy-plugin.mdx @@ -3,20 +3,20 @@ title: Agent Strategy Plugin description: Build a Function Calling agent strategy from scratch, with a worked example showing how to give an LLM tools and let it autonomously fetch the current time --- -An **Agent Strategy Plugin** helps an LLM carry out tasks like reasoning or decision-making, including choosing and calling tools, as well as handling results. This allows the system to address problems more autonomously. +An **Agent Strategy Plugin** gives an LLM the reasoning and decision-making logic to choose tools, call them, and handle their results, so it can solve problems autonomously. -Below, you’ll see how to develop a plugin that supports **Function Calling** to automatically fetch the current time. +This guide walks through building a **Function Calling** strategy that lets the model fetch the current time on its own. ## Prerequisites - Dify plugin scaffolding tool - Python environment (version 3.12) -For details on preparing the plugin development tool, see [Initializing the Development Tool](/en/develop-plugin/getting-started/cli). +For details on preparing the plugin development tool, see [CLI](/en/develop-plugin/getting-started/cli). - -**Tip**: Run `dify version` in your terminal to confirm that the scaffolding tool is installed. - + +Run `dify version` in your terminal to confirm that the scaffolding tool is installed. + --- @@ -24,11 +24,11 @@ For details on preparing the plugin development tool, see [Initializing the Deve Run the following command to create a development template for your Agent plugin: -``` +```bash dify plugin init ``` -Follow the on-screen prompts and refer to the sample comments for guidance. +Follow the on-screen prompts; the comments below explain each choice. ```bash ➜ Dify Plugins Developing dify plugin init @@ -67,7 +67,7 @@ Models: ... ``` -After initialization, you’ll get a folder containing all the resources needed for plugin development. Familiarizing yourself with the overall structure of an Agent Strategy Plugin will streamline the development process: +Initialization creates a folder with everything you need for plugin development: ```text ├── GUIDE.md # User guide and documentation @@ -96,27 +96,27 @@ Agent Strategy Plugin development revolves around two files: - **Plugin Declaration**: `strategies/basic_agent.yaml` - **Plugin Implementation**: `strategies/basic_agent.py` -### 2.1 Defining Parameters +### 2.1 Define Parameters -To build an Agent plugin, start by specifying the necessary parameters in `strategies/basic_agent.yaml`. These parameters define the plugin’s core features, such as calling an LLM or using tools. +Start by declaring the plugin's parameters in `strategies/basic_agent.yaml`. These parameters power the plugin's core features, such as calling an LLM or using tools. -We recommend including the following four parameters first: +We recommend starting with these four parameters: -1. **model**: The large language model to call (e.g., GPT-4, GPT-4o-mini). -2. **tools**: A list of tools that enhance your plugin’s functionality. -3. **query**: The user input or prompt content sent to the model. -4. **maximum_iterations**: The maximum iteration count to prevent excessive computation. +- **`model`**: The large language model to call (e.g., GPT-4, GPT-4o-mini). +- **`tools`**: A list of tools that enhance your plugin's functionality. +- **`query`**: The user input or prompt content sent to the model. +- **`maximum_iterations`**: The maximum iteration count, which prevents excessive computation. -Example Code: +Example: ```yaml identity: name: basic_agent # the name of the agent_strategy author: novice # the author of the agent_strategy label: - en_US: BasicAgent # the engilish label of the agent_strategy + en_US: BasicAgent # the English label of the agent_strategy description: - en_US: BasicAgent # the english description of the agent_strategy + en_US: BasicAgent # the English description of the agent_strategy parameters: - name: model # the name of the model parameter type: model-selector # model-type @@ -155,17 +155,15 @@ extra: source: strategies/basic_agent.py ``` -Once you’ve configured these parameters, the plugin will automatically generate a user-friendly interface so you can easily manage them: +Dify automatically renders a configuration interface from these parameter declarations: ![Agent Strategy Plugin UI](https://assets-docs.dify.ai/2025/01/d011e2eba4c37f07a9564067ba787df8.png) -### 2.2 Retrieving Parameters and Execution +### 2.2 Retrieve Parameters and Execute -After users fill out these basic fields, your plugin needs to process the submitted parameters. In `strategies/basic_agent.py`, define a parameter class for the Agent, then retrieve and apply these parameters in your logic. - -Verify incoming parameters: +When users fill out these fields, your plugin receives the submitted values. In `strategies/basic_agent.py`, define a Pydantic model that validates the incoming parameters: ```python from dify_plugin.entities.agent import AgentInvokeMessage @@ -179,7 +177,7 @@ class BasicParams(BaseModel): query: str ``` -After getting the parameters, the specific business logic is executed: +Then parse the parameters in `_invoke` and run your strategy logic: ```python class BasicAgentAgentStrategy(AgentStrategy): @@ -189,19 +187,19 @@ class BasicAgentAgentStrategy(AgentStrategy): ## 3. Invoke the Model -In an Agent Strategy Plugin, **invoking the model** is central to the workflow. You can invoke an LLM efficiently using `session.model.llm.invoke()` from the SDK, handling text generation, dialogue, and so forth. +Invoking the model is central to an Agent strategy. Use `session.model.llm.invoke()` from the SDK to call an LLM for text generation, dialogue, and similar tasks. -If you want the LLM **handle tools**, ensure it outputs structured parameters to match a tool’s interface. In other words, the LLM must produce input arguments that the tool can accept based on the user’s instructions. +For the LLM to drive tool calls, it must output structured arguments that match each tool's interface—input the tool can accept, derived from the user's instructions. -Construct the following parameters: +The method takes the following parameters: -* model -* prompt\_messages -* tools -* stop -* stream +- `model` +- `prompt_messages` +- `tools` +- `stop` +- `stream` -Example code for method definition: +Method signature: ```python def invoke( @@ -214,25 +212,25 @@ def invoke( ) -> Generator[LLMResultChunk, None, None] | LLMResult:... ``` -To view the complete functionality implementation, please refer to the Example Code for model invocation. +For the full implementation, see the **Invoke Model** tab in the [sample code](#sample-code) below. -This code achieves the following functionality: after a user inputs a command, the Agent strategy plugin automatically calls the LLM, constructs the necessary parameters for tool invocation based on the generated results, and enables the model to flexibly dispatch integrated tools to efficiently complete complex tasks. +With this in place, the plugin calls the LLM whenever a user enters a command, builds tool-invocation parameters from the model's output, and lets the model dispatch the configured tools to complete complex tasks. ![Request Parameters for Generating Tools](https://assets-docs.dify.ai/2025/01/01e32c2d77150213c7c929b3cceb4dae.png) -## 4. Handle a Tool +## 4. Invoke Tools -After specifying the tool parameters, the Agent Strategy Plugin must actually call these tools. Use `session.tool.invoke()` to make those requests. +Once the model has produced tool parameters, the plugin must actually call the tools. Use `session.tool.invoke()` to make those requests. -Construct the following parameters: +The method takes the following parameters: -- provider -- tool\_name -- parameters +- `provider` +- `tool_name` +- `parameters` -Example code for method definition: +Method signature: ```python def invoke( @@ -244,7 +242,7 @@ Example code for method definition: ) -> Generator[ToolInvokeMessage, None, None]:... ``` -If you’d like the LLM itself to generate the parameters needed for tool calls, you can do so by combining the model’s output with your tool-calling code. +To let the LLM generate the tool-call parameters itself, feed the model's extracted tool calls into your invocation code: ```python tool_instances = ( @@ -260,7 +258,7 @@ for tool_call_id, tool_call_name, tool_call_args in tool_calls: ) ``` -With this in place, your Agent Strategy Plugin can automatically perform **Function Calling**, for instance retrieving the current time. +Your plugin can now perform Function Calling automatically—for instance, retrieving the current time. ![Tool Invocation](https://assets-docs.dify.ai/2025/01/80e5de8acc2b0ed00524e490fd611ff5.png) @@ -268,12 +266,12 @@ With this in place, your Agent Strategy Plugin can automatically perform **Funct ## 5. Create Logs -Often, multiple steps are necessary to complete a complex task in an **Agent Strategy Plugin**. It’s crucial for developers to track each step’s results, analyze the decision process, and optimize strategy. Using `create_log_message` and `finish_log_message` from the SDK, you can log real-time states before and after calls, aiding in quick problem diagnosis. +Complex tasks usually take multiple steps, and you need to track each step's result to analyze decisions and refine your strategy. The SDK's `create_log_message` and `finish_log_message` let you record state before and after each call, which speeds up problem diagnosis. For example: -- Log a “starting model call” message before calling the model, clarifying the task’s execution progress. -- Log a “call succeeded” message once the model responds, ensuring the model’s output can be traced end to end. +- Log a "starting model call" message before calling the model to show execution progress. +- Log a "call succeeded" message once the model responds, so its output can be traced end to end. ```python model_log = self.create_log_message( @@ -300,15 +298,13 @@ yield self.finish_log_message( ) ``` -When the setup is complete, the workflow log will output the execution results: +Once set up, the workflow log shows the execution results: ![Agent Output Execution Results](https://assets-docs.dify.ai/2025/01/96516388a4fb1da9cea85fc1804ff377.png) -If multiple rounds of logs occur, you can structure them hierarchically by setting a `parent` parameter in your log calls, making them easier to follow. - -Reference method: +When a task spans multiple rounds, set the `parent` parameter in your log calls to nest the logs hierarchically and keep them easy to follow: ```python function_call_round_log = self.create_log_message( @@ -329,13 +325,11 @@ model_log = self.create_log_message( yield model_log ``` -### Sample code for agent-plugin functions +### Sample Code - #### Invoke Model - -The following code demonstrates how to give the Agent strategy plugin the ability to invoke the model: + The following code gives the Agent strategy plugin the ability to invoke the model: ```python import json @@ -559,9 +553,7 @@ class BasicAgentAgentStrategy(AgentStrategy): ``` - #### Handle Tools - -The following code shows how to implement model calls for the Agent strategy plugin and send canonicalized requests to the tool. + The following code invokes the model and sends well-formed requests to the tools it selects: ```python import json @@ -784,10 +776,8 @@ class BasicAgentAgentStrategy(AgentStrategy): return tool_calls ``` - - #### Example of a complete function code - -A complete sample plugin code that includes a **invoking model, handling tool** and a **function to output multiple rounds of logs**: + + A complete sample that covers model invocation, tool handling, and multi-round logging: ```python import json @@ -1045,13 +1035,13 @@ class BasicAgentAgentStrategy(AgentStrategy): ## 6. Debug the Plugin -After finalizing the plugin’s declaration file and implementation code, run `python -m main` in the plugin directory to restart it. Next, confirm the plugin runs correctly. Dify offers remote debugging. Go to **Plugin Management** to obtain your debug key and remote server address. +With the declaration file and implementation code complete, verify that the plugin runs correctly. Dify supports remote debugging: go to **Plugin Management** to obtain your debug key and remote server address. - ![Finalizing the Plugin’S Declaration File and Implementation Code, Run Python -M](https://assets-docs.dify.ai/2024/12/053415ef127f1f4d6dd85dd3ae79626a.png) + ![Debug Key and Remote Server Address in Plugin Management](https://assets-docs.dify.ai/2024/12/053415ef127f1f4d6dd85dd3ae79626a.png) -Back in your plugin project, copy `.env.example` to `.env` and insert the relevant remote server and debug key info. +In your plugin project, copy `.env.example` to `.env` and fill in the remote server address and debug key. ```bash INSTALL_METHOD=remote @@ -1065,7 +1055,7 @@ Then run: python -m main ``` -You’ll see the plugin installed in your Workspace, and team members can also access it. +The plugin appears in your workspace, where team members can also access it. ![Browser Plugins](https://assets-docs.dify.ai/2025/01/c82ec0202e5bf914b36e06c796398dd6.png) @@ -1073,7 +1063,7 @@ You’ll see the plugin installed in your Workspace, and team members can also a ## Package the Plugin (Optional) -Once everything works, you can package your plugin by running: +Once everything works, package your plugin by running: ```bash # Replace ./basic_agent/ with your actual plugin project path. @@ -1083,17 +1073,17 @@ dify plugin package ./basic_agent/ A file named `basic_agent.difypkg` (matching your plugin name) appears in your current folder. This is your final plugin package. -**Congratulations!** You’ve fully developed, tested, and packaged your Agent Strategy Plugin. +Congratulations! You've developed, tested, and packaged your Agent Strategy Plugin. ## Publish the Plugin (Optional) -You can now upload it to the [Dify Plugins repository](https://github.com/langgenius/dify-plugins). Before doing so, ensure it meets the [Plugin Publishing Guidelines](/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace). Once approved, your code merges into the main branch, and the plugin automatically goes live on the [Dify Marketplace](https://marketplace.dify.ai/). +You can now upload the package to the [Dify Plugins repository](https://github.com/langgenius/dify-plugins). Before doing so, ensure it meets the [Plugin Publishing Guidelines](/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace). Once approved, your code merges into the main branch, and the plugin automatically goes live on the [Dify Marketplace](https://marketplace.dify.ai/). --- ## Further Exploration -Complex tasks often need multiple rounds of thinking and tool calls, typically repeating **model invoke → tool use** until the task ends or a maximum iteration limit is reached. Managing prompts effectively is crucial in this process. Check out the [complete Function Calling implementation](https://github.com/langgenius/dify-official-plugins/blob/main/agent-strategies/cot_agent/strategies/function_calling.py) for a standardized approach to letting models call external tools and handle their outputs. +Complex tasks often need multiple rounds of thinking and tool calls, repeating the model invoke → tool use cycle until the task ends or the iteration limit is reached. Managing prompts well is crucial in this process. See the [complete Function Calling implementation](https://github.com/langgenius/dify-official-plugins/blob/main/agent-strategies/cot_agent/strategies/function_calling.py) for a standardized approach to letting models call external tools and handle their outputs. {/* Contributing Section diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet.mdx index 6611f283a..10659c307 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet.mdx @@ -7,22 +7,19 @@ dimensions: standard_title: Cheatsheet language: en title: Cheatsheet -description: A comprehensive reference guide for Dify plugin development, including - environment requirements, installation methods, development process, plugin categories - and types, common code snippets, and solutions to common issues. Suitable for developers - to quickly consult and reference. +description: A quick reference for Dify plugin development, covering environment setup, installation, the development process, and plugin types --- ## Environment Requirements -- Python version 3.12 -- Dify plugin scaffold tool (dify-plugin-daemon) +- Python version 3.12 +- Dify plugin scaffold tool (`dify-plugin-daemon`) -> Learn more: [Initializing Development Tools](/en/develop-plugin/getting-started/cli) +For setup instructions, see [Initializing Development Tools](/en/develop-plugin/getting-started/cli). ## Obtain the Dify Plugin Development Package -[Dify Plugin CLI](https://github.com/langgenius/dify-plugin-daemon/releases) +Download the [Dify Plugin CLI](https://github.com/langgenius/dify-plugin-daemon/releases) from the GitHub releases page. ### Installation Methods for Different Platforms @@ -71,7 +68,7 @@ dify version ## Run the Development Package -Here we use `dify` as an example. If you are using a local installation method, please replace the command accordingly, for example `./dify-plugin-darwin-arm64 plugin init`. +The following examples use `dify` as the command. If you installed locally, replace the command accordingly—for example, `./dify-plugin-darwin-arm64 plugin init`. ## Plugin Development Process @@ -81,9 +78,9 @@ Here we use `dify` as an example. If you are using a local installation method, ./dify plugin init ``` -Follow the prompts to complete the basic plugin information configuration +Follow the prompts to configure the basic plugin information. -> Learn more: [Dify Plugin Development: Hello World Guide](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) +For a full walkthrough, see [Dify Plugin Development: Hello World Guide](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin). ### 2. Run in Development Mode @@ -93,9 +90,9 @@ Configure the `.env` file, then run the following command in the plugin director python -m main ``` -> Learn more: [Remote Debugging Plugins](/en/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin) +For debugging details, see [Remote Debugging Plugins](/en/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin). -### 3. Packaging and Deployment +### 3. Package and Deploy Package the plugin: @@ -104,13 +101,13 @@ cd .. dify plugin package ./yourapp ``` -> Learn more: [Publishing Overview](/en/develop-plugin/publishing/marketplace-listing/release-overview) +For publishing details, see the [Publishing Overview](/en/develop-plugin/publishing/marketplace-listing/release-overview). ## Plugin Categories ### Tool Labels -Category `tag` [class ToolLabelEnum(Enum)](https://github.com/langgenius/dify-plugin-sdks/blob/main/python/dify_plugin/entities/tool.py) +Category tags are defined in [`ToolLabelEnum`](https://github.com/langgenius/dify-plugin-sdks/blob/main/python/dify_plugin/entities/tool.py): ```python class ToolLabelEnum(Enum): @@ -134,25 +131,14 @@ class ToolLabelEnum(Enum): ## Plugin Type Reference -Dify supports the development of various types of plugins: +Dify supports several plugin types: -- **Tool plugin**: Integrate third-party APIs and services - > Learn more: [Dify Plugin Development: Hello World Guide](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) - -- **Model plugin**: Integrate AI models - > Learn more: [Model Plugin](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules), [Quick Integration of a New Model](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) - -- **Agent strategy plugin**: Customize Agent thinking and decision-making strategies - > Learn more: [Agent Strategy Plugin](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation) - -- **Extension plugin**: Extend Dify platform functionality, such as Endpoints and WebAPP - > Learn more: [Extension Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) - -- **Data source plugin**: Serve as the document data source and starting point for knowledge pipelines - > Learn more: [Data Source Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin) - -- **Trigger plugin**: Automatically trigger Workflow execution upon third-party events - > Learn more: [Trigger Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/trigger-plugin) +- **Tool plugin**: Integrate third-party APIs and services. See [Dify Plugin Development: Hello World Guide](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin). +- **Model plugin**: Integrate AI models. See [Model Plugin](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules) and [Quick Integration of a New Model](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider). +- **Agent strategy plugin**: Customize Agent thinking and decision-making strategies. See [Agent Strategy Plugin](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation). +- **Extension plugin**: Extend Dify platform functionality, such as Endpoints and WebApp. See [Extension Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint). +- **Data source plugin**: Serve as the document data source and starting point for knowledge pipelines. See [Data Source Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin). +- **Trigger plugin**: Automatically trigger workflow execution on third-party events. See [Trigger Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/trigger-plugin). {/* Contributing Section @@ -163,4 +149,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider.mdx index cb63c94dd..99d9956ab 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider.mdx @@ -7,16 +7,14 @@ dimensions: standard_title: Model Provider Plugin language: en title: Model Provider Plugin -description: This comprehensive guide provides detailed instructions on creating model provider plugins, - covering project initialization, directory structure organization, model configuration methods, - writing provider code, and implementing model integration with detailed examples of core API implementations. +description: Build a model provider plugin, from project setup and provider configuration to model implementation, debugging, and publishing --- ## Prerequisites -* [Dify CLI](/en/develop-plugin/getting-started/cli) -* Basic Python programming skills and understanding of object-oriented programming -* Familiarity with the API documentation of the model provider you want to integrate +- [Dify CLI](/en/develop-plugin/getting-started/cli) +- Basic Python programming skills and understanding of object-oriented programming +- Familiarity with the API documentation of the model provider you want to integrate ## Step 1: Create and Configure a New Plugin Project @@ -38,9 +36,9 @@ Select the `LLM` type plugin template from the available options. This template For a model provider plugin, configure the following essential permissions: -* **Models** - Base permission for model operations -* **LLM** - Permission for large language model functionality -* **Storage** - Permission for file operations (if needed) +- **Models**: Base permission for model operations. +- **LLM**: Permission for large language model functionality. +- **Storage**: Permission for file operations (if needed). ![Model Plugin Permission](https://assets-docs.dify.ai/2024/12/10f3b3ee6c03a1215309f13d712455d4.png) @@ -48,7 +46,7 @@ For a model provider plugin, configure the following essential permissions: ### Directory Structure Overview -After initialization, your plugin project will have a directory structure similar to this (assuming a provider named `my_provider` supporting LLM and Embedding): +After initialization, your plugin project has a directory structure similar to this (assuming a provider named `my_provider` that supports LLM and Embedding): ```bash models/my_provider/ @@ -68,32 +66,32 @@ models/my_provider/ ## Step 2: Understand Model Configuration Methods -Dify supports two model configuration methods that determine how users will interact with your provider's models: +Dify supports two model configuration methods that determine how users interact with your provider's models: ### Predefined Models (`predefined-model`) -These are models that only require unified provider credentials to use. Once a user configures their API key or other authentication details for the provider, they can immediately access all predefined models. +Predefined models require only unified provider credentials. Once a user configures their API key or other authentication details for the provider, they can immediately access all predefined models. -**Example**: The `OpenAI` provider offers predefined models like `gpt-3.5-turbo-0125` and `gpt-4o-2024-05-13`. A user only needs to configure their OpenAI API key once to access all these models. +**Example**: The OpenAI provider offers predefined models like `gpt-3.5-turbo-0125` and `gpt-4o-2024-05-13`. A user only needs to configure their OpenAI API key once to access all these models. ### Custom Models (`customizable-model`) -These require additional configuration for each specific model instance. This approach is useful when models need individual parameters beyond the provider-level credentials. +Custom models require additional configuration for each model instance. This approach is useful when models need individual parameters beyond the provider-level credentials. -**Example**: `Xinference` supports both LLM and Text Embedding, but each model has a unique **model_uid**. Users must configure this model_uid separately for each model they want to use. +**Example**: Xinference supports both LLM and Text Embedding, but each model has a unique `model_uid`. Users must configure this `model_uid` separately for each model they want to use. -These configuration methods **can coexist** within a single provider. For instance, a provider might offer some predefined models while also allowing users to add custom models with specific configurations. +The two configuration methods can coexist within a single provider. For instance, a provider might offer some predefined models while also allowing users to add custom models with specific configurations. ## Step 3: Create Model Provider Files Creating a new model provider involves two main components: -1. **Provider Configuration YAML File** - Defines the provider's basic information, supported model types, and credential requirements -2. **Provider Class Implementation** - Implements authentication validation and other provider-level functionality +- **Provider configuration YAML file**: Defines the provider's basic information, supported model types, and credential requirements. +- **Provider class implementation**: Implements authentication validation and other provider-level functionality. -### 3.1 Create Model Provider Configuration File +### 3.1 Create the Model Provider Configuration File -The provider configuration is defined in a YAML file that declares the provider's basic information, supported model types, configuration methods, and credential rules. This file will be placed in the root directory of your plugin project. +The provider configuration is a YAML file that declares the provider's basic information, supported model types, configuration methods, and credential rules. Place it in the root directory of your plugin project. Here's an annotated example of the `anthropic.yaml` configuration file: @@ -162,7 +160,7 @@ extra: ### Custom Model Configuration -If your provider supports custom models, you need to add a `model_credential_schema` section to define what additional fields users need to configure for each individual model. This is typical for providers that support fine-tuned models or require model-specific parameters. +If your provider supports custom models, add a `model_credential_schema` section defining the additional fields users must configure for each model. This is typical for providers that support fine-tuned models or require model-specific parameters. Here's an example from the OpenAI provider: @@ -196,11 +194,11 @@ model_credential_schema: # Additional fields as needed... ``` -For complete model provider YAML specifications, please refer to the [Model Schema](/en/develop-plugin/features-and-specs/plugin-types/model-schema) documentation. +For the complete model provider YAML specification, see [Model Schema](/en/develop-plugin/features-and-specs/plugin-types/model-schema). -### 3.2 Write Model Provider Code +### 3.2 Write the Model Provider Code -Next, create a Python file for your provider class implementation. This file should be placed in the `/provider` directory with a name matching your provider (e.g., `anthropic.py`). +Next, create a Python file for your provider class in the `/provider` directory, named after your provider (e.g., `anthropic.py`). The provider class must inherit from `ModelProvider` and implement at least the `validate_provider_credentials` method: @@ -240,15 +238,15 @@ class AnthropicProvider(ModelProvider): raise ex ``` -The `validate_provider_credentials` method is crucial as it's called whenever a user tries to save their provider credentials in Dify. It should: +Dify calls `validate_provider_credentials` whenever a user saves provider credentials, so it should: -1. Attempt to validate the credentials by making a simple API call -2. Return silently if validation succeeds -3. Raise `CredentialsValidateFailedError` with a helpful message if validation fails +1. Attempt to validate the credentials by making a simple API call. +2. Return silently if validation succeeds. +3. Raise `CredentialsValidateFailedError` with a helpful message if validation fails. #### For Custom Model Providers -For providers that exclusively use custom models (where each model requires its own configuration), you can implement a simpler provider class. For example, with `Xinference`: +For providers that exclusively use custom models (where each model requires its own configuration), you can implement a simpler provider class. For example, with Xinference: ```python from dify_plugin import ModelProvider @@ -264,15 +262,15 @@ class XinferenceProvider(ModelProvider): ## Step 4: Implement Model-Specific Code -After setting up your provider, you need to implement the model-specific code that will handle API calls for each model type you support. This involves: +After setting up your provider, implement the model-specific code that handles API calls for each model type you support. This involves: -1. Creating model configuration YAML files for each specific model -2. Implementing the model type classes that handle API communication +1. Creating model configuration YAML files for each specific model. +2. Implementing the model type classes that handle API communication. -For detailed instructions on these steps, please refer to: +For detailed instructions, see: -* [Model Design Rules](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules) - Standards for integrating predefined models -* [Model Schema](/en/develop-plugin/features-and-specs/plugin-types/model-schema) - Standards for model configuration files +- [Model Design Rules](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules): Standards for integrating predefined models. +- [Model Schema](/en/develop-plugin/features-and-specs/plugin-types/model-schema): Standards for model configuration files. ### 4.1 Define Model Configuration (YAML) @@ -314,7 +312,7 @@ pricing: # Optional pricing information ### 4.2 Implement Model Calling Code (Python) -Create a Python file for each model type you're supporting (e.g., `llm.py` in the `models/llm/` directory). This class will handle API communication, parameter transformation, and result formatting. +Create a Python file for each model type you support (e.g., `llm.py` in the `models/llm/` directory). This class handles API communication, parameter transformation, and result formatting. Here's an example implementation structure for an LLM: @@ -409,48 +407,49 @@ class MyProviderLargeLanguageModel(LargeLanguageModel): The most important method to implement is `_invoke`, which handles the core API communication. This method should: -1. Transform Dify's standardized inputs into the format required by the provider's API -2. Make the API call with proper error handling -3. Transform the API response into Dify's standardized output format -4. Handle both streaming and non-streaming modes +1. Transform Dify's standardized inputs into the format required by the provider's API. +2. Make the API call with proper error handling. +3. Transform the API response into Dify's standardized output format. +4. Handle both streaming and non-streaming modes. ## Step 5: Debug and Test Your Plugin -Dify provides a remote debugging capability that allows you to test your plugin during development: +Dify supports remote debugging, so you can test your plugin during development: -1. In your Dify instance, go to "Plugin Management" and click "Debug Plugin" to get your debug key and server address +1. In your Dify instance, go to **Plugin Management** and click **Debug Plugin** to get your debug key and server address. 2. Configure your local environment with these values in a `.env` file: -```dotenv -INSTALL_METHOD=remote -REMOTE_INSTALL_URL=:5003 -REMOTE_INSTALL_KEY=****-****-****-****-**** -``` + ```dotenv + INSTALL_METHOD=remote + REMOTE_INSTALL_URL=:5003 + REMOTE_INSTALL_KEY=****-****-****-****-**** + ``` -3. Run your plugin locally with `python -m main` and test it in Dify +3. Run your plugin locally with `python -m main` and test it in Dify. ## Step 6: Package and Publish When your plugin is ready: 1. Package it using the scaffolding tool: + ```bash dify plugin package models/ ``` -2. Test the packaged plugin locally before submitting +2. Test the packaged plugin locally before submitting. -3. Submit a pull request to the [Dify official plugins repository](https://github.com/langgenius/dify-official-plugins) +3. Submit a pull request to the [Dify official plugins repository](https://github.com/langgenius/dify-official-plugins). For more details on the publishing process, see the [Publishing Overview](/en/develop-plugin/publishing/marketplace-listing/release-overview). ## Reference Resources -- [Quick Integration of a New Model](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) - How to add new models to existing providers -- [Basic Concepts of Plugin Development](/en/develop-plugin/getting-started/getting-started-dify-plugin) - Return to the plugin development getting started guide -- [Model Schema](/en/develop-plugin/features-and-specs/plugin-types/model-schema) - Learn detailed model configuration specifications -- [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) - Learn about plugin manifest file configuration -- [Dify Plugin SDK Reference](https://github.com/langgenius/dify-plugin-sdks) - Look up base classes, data structures, and error types +- [Quick Integration of a New Model](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider): How to add new models to existing providers. +- [Basic Concepts of Plugin Development](/en/develop-plugin/getting-started/getting-started-dify-plugin): Return to the plugin development getting started guide. +- [Model Schema](/en/develop-plugin/features-and-specs/plugin-types/model-schema): Detailed model configuration specifications. +- [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications): Plugin manifest file configuration. +- [Dify Plugin SDK Reference](https://github.com/langgenius/dify-plugin-sdks): Base classes, data structures, and error types. {/* Contributing Section @@ -461,4 +460,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin.mdx index fba9578a3..111c1a882 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin.mdx @@ -1,22 +1,22 @@ --- title: Data Source Plugin -description: Build a Dify 1.9.0+ datasource plugin that feeds documents into the knowledge pipeline, with architecture, code samples, and debugging steps +description: Build a Dify 1.9.0+ data source plugin that feeds documents into the knowledge pipeline --- -Data source plugins are a new type of plugin introduced in Dify 1.9.0. In a knowledge pipeline, they serve as the document data source and the starting point for the entire pipeline. +Data source plugins, introduced in Dify 1.9.0, supply documents to a knowledge pipeline and serve as the starting point for the entire pipeline. -This article describes how to develop a data source plugin, covering plugin architecture, code examples, and debugging methods, to help you quickly develop and launch your data source plugin. +This guide covers the plugin architecture, code examples, and debugging methods you need to build and launch a data source plugin. ## Prerequisites -Before reading on, ensure you have a basic understanding of the knowledge pipeline and some knowledge of plugin development. You can find relevant information here: +You should have a basic understanding of the knowledge pipeline and plugin development: - [Step 2: Knowledge Pipeline Orchestration](/en/use-dify/knowledge/knowledge-pipeline/knowledge-pipeline-orchestration) - [Dify Plugin Development: Hello World Guide](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) -## **Data Source Plugin Types** +## Data Source Plugin Types -Dify supports three types of data source plugins: web crawler, online document, and online drive. When implementing the plugin code, the class that provides the plugin's functionality must inherit from a specific data source class. Each of the three plugin types corresponds to a different parent class. +Dify supports three types of data source plugins: web crawler, online document, and online drive. Each type corresponds to a different parent class, and the class that implements your plugin's functionality must inherit from it. To learn how to inherit from a parent class to implement plugin functionality, see [Tool Plugin: Prepare Tool Code](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin#4-prepare-tool-code). @@ -38,9 +38,9 @@ The relationship between data source types and data source plugin types is illus ### Create a Data Source Plugin -You can use the scaffolding command-line tool to create a data source plugin by selecting the `datasource` type. After completing the setup, the command-line tool will automatically generate the plugin project code. +Create a data source plugin with the scaffolding command-line tool by selecting the `datasource` type. After you complete the setup, the tool generates the plugin project code. -```powershell +```bash dify plugin init ``` @@ -60,7 +60,7 @@ A data source plugin consists of three main components: - The `provider` directory: Contains the plugin provider's description and authentication implementation code. - The `datasources` directory: Contains the description and core logic for fetching data from the data source. -``` +```text ├── _assets │   └── icon.svg ├── datasources @@ -78,20 +78,22 @@ A data source plugin consists of three main components: #### Set the Correct Version and Tag -- In the `manifest.yaml` file, set the minimum supported Dify version as follows: +- In the `manifest.yaml` file, set the minimum supported Dify version: ```yaml minimum_dify_version: 1.9.0 ``` -- In the `manifest.yaml` file, add the following tag to display the plugin under the data source category in the Dify Marketplace: + +- In the same file, add the following tag so the plugin appears under the data source category in the Dify Marketplace: ```yaml tags: - rag ``` -- In the `requirements.txt` file, set the plugin SDK version used for data source plugin development as follows: - ```yaml +- In the `requirements.txt` file, set the plugin SDK version: + + ```text dify-plugin>=0.5.0,<0.6.0 ``` @@ -122,7 +124,7 @@ datasources: #### Create the Provider Code File -- When using API Key authentication mode, the provider code file for data source plugins is identical to that for tool plugins. You only need to change the parent class inherited by the provider class to `DatasourceProvider`. +- With API Key authentication, the provider code file is identical to that of a tool plugin. You only need to change the provider class's parent class to `DatasourceProvider`. ```python class YourDatasourceProvider(DatasourceProvider): @@ -135,9 +137,10 @@ datasources: except Exception as e: raise ToolProviderCredentialValidationError(str(e)) ``` -- When using OAuth authentication mode, data source plugins differ slightly from tool plugins. When obtaining access permissions via OAuth, data source plugins can simultaneously return the username and avatar to be displayed on the frontend. Therefore, `_oauth_get_credentials` and `_oauth_refresh_credentials` need to return a `DatasourceOAuthCredentials` type that contains `name`, `avatar_url`, `expires_at`, and `credentials`. - The `DatasourceOAuthCredentials` class is defined as follows and must be set to the corresponding type when returned: +- With OAuth authentication, data source plugins differ slightly from tool plugins: when obtaining access via OAuth, they can also return the username and avatar to display on the frontend. `_oauth_get_credentials` and `_oauth_refresh_credentials` must therefore return a `DatasourceOAuthCredentials` object containing `name`, `avatar_url`, `expires_at`, and `credentials`. + + The `DatasourceOAuthCredentials` class is defined as follows: ```python class DatasourceOAuthCredentials(BaseModel): @@ -235,9 +238,9 @@ output_schema: description: the description of the website ``` -In the main logic code for a web crawler plugin, the class must inherit from `WebsiteCrawlDatasource` and implement the `_get_website_crawl` method. You then need to use the `create_crawl_message` method to return the web crawl message. +In the main logic code for a web crawler plugin, the class must inherit from `WebsiteCrawlDatasource` and implement the `_get_website_crawl` method, using the `create_crawl_message` method to return the crawl results. -To crawl multiple web pages and return them in batches, you can set `WebSiteInfo.status` to `processing` and use the `create_crawl_message` method to return each batch of crawled pages. After all pages have been crawled, set `WebSiteInfo.status` to `completed`. +To crawl multiple web pages and return them in batches, set `WebSiteInfo.status` to `processing` and call `create_crawl_message` for each batch of crawled pages. After all pages have been crawled, set `WebSiteInfo.status` to `completed`. ```python class YourDataSource(WebsiteCrawlDatasource): @@ -344,11 +347,11 @@ output_schema: In the main logic code for an online drive plugin, the class must inherit from `OnlineDriveDatasource` and implement two methods: `_browse_files` and `_download_file`. -When a user runs the plugin, it first calls `_browse_files` to get a file list. At this point, `prefix` is empty, indicating a request for the root directory's file list. The file list contains both folder and file type variables. If the user opens a folder, the `_browse_files` method is called again. At this point, the `prefix` in `OnlineDriveBrowseFilesRequest` will be the folder ID used to retrieve the file list within that folder. +When a user runs the plugin, it first calls `_browse_files` to get a file list. At this point, `prefix` is empty, indicating a request for the root directory's file list. The list contains both folder and file entries. If the user opens a folder, `_browse_files` is called again, and the `prefix` in `OnlineDriveBrowseFilesRequest` is the folder ID used to retrieve the file list within that folder. After a user selects a file, the plugin uses the `_download_file` method and the file ID to get the file's content. You can use the `_get_mime_type_from_filename` method to get the file's MIME type, allowing the pipeline to handle different file types appropriately. -When the file list contains multiple files, you can set `OnlineDriveFileBucket.is_truncated` to `True` and set `OnlineDriveFileBucket.next_page_parameters` to the parameters needed to fetch the next page of the file list, such as the next page's request ID or URL, depending on the service provider. +When the file list contains multiple files, you can set `OnlineDriveFileBucket.is_truncated` to `True` and `OnlineDriveFileBucket.next_page_parameters` to the parameters needed to fetch the next page, such as the next page's request ID or URL, depending on the service provider. @@ -413,12 +416,12 @@ For storage services like AWS S3, the `prefix`, `bucket`, and `id` variables hav - `id`: Since the `_download_file` method does not use the `prefix` variable, the full file path must be included in the `id`. For example, `id=container1/folder1/file1.txt` indicates retrieving the `file1.txt` file from the `folder1` folder in the `container1` bucket. - You can refer to the specific implementations of the [official Google Drive plugin](https://github.com/langgenius/dify-official-plugins/blob/main/datasources/google_cloud_storage/datasources/google_cloud_storage.py) and the [official AWS S3 plugin](https://github.com/langgenius/dify-official-plugins/blob/main/datasources/aws_s3_storage/datasources/aws_s3_storage.py). + For reference implementations, see the [official Google Drive plugin](https://github.com/langgenius/dify-official-plugins/blob/main/datasources/google_cloud_storage/datasources/google_cloud_storage.py) and the [official AWS S3 plugin](https://github.com/langgenius/dify-official-plugins/blob/main/datasources/aws_s3_storage/datasources/aws_s3_storage.py). ## Debug the Plugin -Data source plugins support two debugging methods: remote debugging or installing as a local plugin for debugging. Note the following: +Data source plugins support two debugging methods: remote debugging and installing the plugin locally. Note the following: - If the plugin uses OAuth authentication, the `redirect_uri` for remote debugging differs from that of a local plugin. Update the relevant configuration in your service provider's OAuth App accordingly. - While data source plugins support single-step debugging, we still recommend testing them in a complete knowledge pipeline to ensure full functionality. @@ -437,7 +440,7 @@ Before packaging and publishing, make sure you've completed all of the following In the plugin directory, run the following command to generate a `.difypkg` plugin package: -``` +```bash dify plugin package . -o your_datasource.difypkg ``` @@ -459,4 +462,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/develop-a-slack-bot-plugin.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/develop-a-slack-bot-plugin.mdx index fbc3c5d66..61614a035 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/develop-a-slack-bot-plugin.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/develop-a-slack-bot-plugin.mdx @@ -7,70 +7,67 @@ dimensions: standard_title: Slack Bot language: en title: Slack Bot -description: This guide provides a complete walkthrough for developing a Slack Bot - plugin, covering project initialization, configuration form editing, feature implementation, - debugging, endpoint setup, verification, and packaging. You'll need the Dify plugin - scaffolding tool and a pre-created Slack App to build an AI-powered chatbot on Slack. +description: Build a Slack Bot plugin that connects a Dify app to Slack, from project setup through debugging and packaging --- -**What You’ll Learn**: - -Gain a solid understanding of how to build a Slack Bot that’s powered by AI, one that can respond to user questions right inside Slack. If you haven't developed a plugin before, we recommend reading the [Plugin Development Quick Start Guide](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) first. +In this guide, you'll build an AI-powered Slack Bot that answers user questions right inside Slack. If you haven't developed a plugin before, read the [Plugin Development Quick Start Guide](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) first. ## Project Background -The Dify plugin ecosystem focuses on making integrations simpler and more accessible. In this guide, we’ll use Slack as an example, walking you through the process of developing a Slack Bot plugin. This allows your team to chat directly with an LLM within Slack, significantly improving how efficiently they can use AI. +A Slack Bot plugin lets your team chat with an LLM directly in Slack, putting AI where conversations already happen. -Slack is an open, real-time communication platform with a robust API. Among its features is a webhook-based event system, which is quite straightforward to develop on. We’ll leverage this system to create a Slack Bot plugin, illustrated in the diagram below: +Slack is an open, real-time communication platform with a robust API, including a webhook-based event system that is straightforward to build on. This guide uses that system to create the Slack Bot plugin, illustrated in the diagram below: ![Slack Bot Diagram](https://assets-docs.dify.ai/2025/01/a0865d18f1ca4051601ca53fa6f92db2.png) -> To avoid confusion, the following concepts are explained: -> -> * **Slack Bot** A chatbot on the Slack platform, acting as a virtual user you can interact with in real-time. -> * **Slack Bot Plugin** A plugin in the Dify Marketplace that connects a Dify application with Slack. This guide focuses on how to develop that plugin. + +Two similar terms appear throughout this guide: + +- **Slack Bot**: A chatbot on the Slack platform—a virtual user you can interact with in real time. +- **Slack Bot plugin**: A plugin in the Dify Marketplace that connects a Dify application with Slack. This guide shows you how to build it. + -**How It Works (A Simple Overview)**: +### How It Works -1. **Send a Message to the Slack Bot** +1. **A user messages the Slack Bot** - When a user in Slack sends a message to the Bot, the Slack Bot immediately issues a webhook request to the Dify platform. + When a user in Slack sends a message to the Bot, the Slack Bot immediately issues a webhook request to the Dify platform. -2. **Forward the Message to the Slack Bot Plugin** +2. **Slack forwards the message to the Slack Bot plugin** - The Dify platform triggers the Slack Bot plugin, which relays the details to the Dify application, similar to entering a recipient’s address in an email system. By setting up a Slack webhook address through Slack’s API and entering it in the Slack Bot plugin, you establish this connection. The plugin then processes the Slack request and sends it on to the Dify application, where the LLM analyzes the user’s input and generates a response. + The Dify platform triggers the Slack Bot plugin, which relays the message to the Dify application—much like an email system delivering to a recipient's address. You establish this connection by setting up a Slack webhook address through Slack's API and entering it in the plugin. The plugin processes the Slack request and forwards it to the Dify application, where the LLM analyzes the input and generates a response. -3. **Return the Response to Slack** +3. **The plugin returns the response to Slack** - Once the Slack Bot plugin receives the reply from the Dify application, it sends the LLM’s answer back through the same route to the Slack Bot. Users in Slack then see a more intelligent, interactive experience right where they’re chatting. + Once the plugin receives the reply from the Dify application, it sends the LLM's answer back along the same route to the Slack Bot, so users get the response right where they're chatting. ## Prerequisites -- **Dify plugin developing tool**: For more information, see [Initializing the Development Tool](/en/develop-plugin/getting-started/cli). -- **Python environment (version 3.12)**: Refer to the [Python official downloads page](https://www.python.org/downloads/) or ask an LLM for a complete setup guide. -- Create a Slack App and Get an OAuth Token +- **Dify plugin development tool**: See [Initializing the Development Tool](/en/develop-plugin/getting-started/cli). +- **Python environment (version 3.12)**: See the [Python official downloads page](https://www.python.org/downloads/). +- **A Slack App with an OAuth token**: See the steps below. -Go to the [Slack API platform](https://api.slack.com/apps), create a Slack app from scratch, and pick the workspace where it will be deployed. +To create the Slack App, go to the [Slack API platform](https://api.slack.com/apps), create an app from scratch, and pick the workspace where it will be deployed. - ![](https://assets-docs.dify.ai/2025/01/c1fd0ac1467faf5a3ebf3818bb234aa8.png) + ![Create a Slack App](https://assets-docs.dify.ai/2025/01/c1fd0ac1467faf5a3ebf3818bb234aa8.png) -1. **Enable Webhooks**: +1. **Enable Webhooks**: ![Enable Webhooks](https://assets-docs.dify.ai/2025/01/7112e0710300f1db16827e17f3deac00.png) -2. **Install the App in Your Slack Workspace**: +2. **Install the App in Your Slack Workspace**: ![Install the App in Your Slack Workspace](https://assets-docs.dify.ai/2025/01/88c360ff4f7b04fea52174ce330522fa.png) -3. **Obtain an OAuth Token** for future plugin development: +3. **Obtain an OAuth Token** for plugin development: ![Obtain an OAuth Token for Future Plugin Development](https://assets-docs.dify.ai/2025/01/dcd8ec947253f2ef9ae121ed77ec9f26.png) @@ -78,7 +75,7 @@ Go to the [Slack API platform](https://api.slack.com/apps), create a Slack app f ## 1. Develop the Plugin -Now we’ll dive into the actual coding. Before starting, make sure you’ve read [Quick Start: Developing an Extension Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) or have already built a Dify plugin before. +Before you start coding, make sure you've read [Quick Start: Developing an Extension Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) or have built a Dify plugin before. ### 1.1 Initialize the Project @@ -98,9 +95,9 @@ For additional details on reverse-invoking Dify services within a plugin, see [R ### 1.2 Edit the Configuration Form -This plugin needs to know which Dify app should handle the replies, as well as the Slack App token to authenticate the bot’s responses. Therefore, you’ll add these two fields to the plugin’s form. +The plugin needs two pieces of information: which Dify app handles the replies, and the Slack App token that authenticates the bot's responses. Add both fields to the plugin's form. -Modify the YAML file in the group directory (for example, `group/slack.yaml`). The form’s filename is determined by the info you provided when creating the plugin, so adjust it accordingly. +Modify the YAML file in the `group` directory (for example, `group/slack.yaml`). The form's filename comes from the information you provided when creating the plugin, so adjust the path accordingly. **Sample Code**: @@ -147,19 +144,18 @@ endpoints: - endpoints/slack.yaml ``` -Explanation of the Configuration Fields: +Two configuration fields deserve a closer look: -``` +```yaml - name: app type: app-selector scope: chat ``` -* **type**: Set to app-selector, which allows users to forward messages to a specific Dify app when using this plugin. - -* **scope**: Set to chat, meaning the plugin can only interact with app types such as agent, chatbot, or chatflow. +- **`type`**: Set to `app-selector`, which lets users forward messages to a specific Dify app when using this plugin. +- **`scope`**: Set to `chat`, meaning the plugin can only interact with app types such as agent, chatbot, or chatflow. -Finally, in the `endpoints/slack.yaml` file, change the request method to POST to handle incoming Slack messages properly. +Finally, in the `endpoints/slack.yaml` file, change the request method to `POST` so the endpoint can handle incoming Slack messages. **Sample Code**: @@ -173,7 +169,7 @@ extra: source: "endpoints/slack.py" ``` -## 2. Edit the function code +## 2. Edit the Function Code Modify the `endpoints/slack.py` file and add the following code: @@ -257,10 +253,10 @@ class SlackEndpoint(Endpoint): Go to the Dify platform and obtain the remote debugging address and key for your plugin. - ![](https://assets-docs.dify.ai/2025/01/8d24006f0cabf5bf61640a9023c45db8.png) + ![Get the Remote Debugging Address and Key](https://assets-docs.dify.ai/2025/01/8d24006f0cabf5bf61640a9023c45db8.png) -Back in your plugin project, copy the `.env.example` file and rename it to `.env`. +Back in your plugin project, copy the `.env.example` file, rename it to `.env`, and fill in the debugging details: ```bash INSTALL_METHOD=remote @@ -268,15 +264,17 @@ REMOTE_INSTALL_URL=debug.dify.ai:5003 REMOTE_INSTALL_KEY=********-****-****-****-************ ``` -Run `python -m main` to start the plugin. You should now see your plugin installed in the Workspace on Dify’s plugin management page. Other team members will also be able to access it. +Start the plugin: ```bash python -m main ``` +You should now see the plugin installed in your Workspace on Dify's plugin management page, where other team members can also access it. + ### Configure the Plugin Endpoint -From the plugin management page in Dify, locate the newly installed test plugin and create a new endpoint. Provide a name, a Bot token, and select the app you want to connect. +On Dify's plugin management page, locate the newly installed test plugin and create a new endpoint. Enter a name and your **Bot Token**, then select the app you want to connect. ![Test Plugins](https://assets-docs.dify.ai/2025/01/07f87e8a2786d6f5f05195961c5630c3.png) @@ -312,17 +310,17 @@ Next, complete the Slack App setup: ## 4. Verify the Plugin -In your code, `self.session.app.chat.invoke` is used to call the Dify application, passing in parameters such as `app_id` and `query`. The response is then returned to the Slack Bot. Run `python -m main` again to restart your plugin for debugging, and check whether Slack correctly displays the Dify App’s reply: +The plugin calls the Dify application through `self.session.app.chat.invoke`, passing in parameters such as `app_id` and `query`, and returns the response to the Slack Bot. Run `python -m main` again to restart the plugin, then check that Slack displays the Dify app's reply: - ![In Your Code, Self](https://assets-docs.dify.ai/2025/01/6fc872d1343ce8503d63c5222f7f26f9.png) + ![Slack Displays the Dify App Reply](https://assets-docs.dify.ai/2025/01/6fc872d1343ce8503d63c5222f7f26f9.png) --- ## 5. Package the Plugin (Optional) -Once you confirm that the plugin works correctly, you can package and name it via the following command. After it runs, you’ll find a `slack_bot.difypkg` file in the current directory: your final plugin package. For detailed packaging steps, refer to [Package as a Local File and Share](/en/develop-plugin/publishing/marketplace-listing/release-by-file). +Once you confirm the plugin works correctly, package it with the following command. The command produces a `slack_bot.difypkg` file in the current directory—your final plugin package. For detailed packaging steps, see [Package as a Local File and Share](/en/develop-plugin/publishing/marketplace-listing/release-by-file). ```bash # Replace ./slack_bot with your actual plugin project path. @@ -330,7 +328,7 @@ Once you confirm that the plugin works correctly, you can package and name it vi dify plugin package ./slack_bot ``` -Congratulations! You’ve successfully developed, tested, and packaged a plugin! +Congratulations—you've developed, tested, and packaged a plugin! --- @@ -342,32 +340,34 @@ You can now upload it to the [Dify Marketplace repository](https://github.com/la ## Related Resources -- [Plugin Development Basics](/en/develop-plugin/getting-started/getting-started-dify-plugin) - Comprehensive overview of Dify plugin development -- [Plugin Development Quick Start Guide](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) - Start developing plugins from scratch -- [Develop an Extension Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) - Learn about extension plugin development -- [Reverse Invocation of Dify Services](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation) - Understand how to call Dify platform capabilities -- [Reverse Invocation: App](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app) - Learn how to call apps within the platform -- [Publishing Plugins](/en/develop-plugin/publishing/marketplace-listing/release-overview) - Learn the publishing process -- [Publishing to Dify Marketplace](/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace) - Marketplace publishing guide -- [Endpoint Detailed Definition](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) - Detailed Endpoint definition +- [Plugin Development Basics](/en/develop-plugin/getting-started/getting-started-dify-plugin): Comprehensive overview of Dify plugin development +- [Plugin Development Quick Start Guide](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin): Start developing plugins from scratch +- [Develop an Extension Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint): Extension plugin development +- [Reverse Invocation of Dify Services](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation): How to call Dify platform capabilities +- [Reverse Invocation: App](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app): How to call apps within the platform +- [Publishing Plugins](/en/develop-plugin/publishing/marketplace-listing/release-overview): The publishing process +- [Publishing to Dify Marketplace](/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace): Marketplace publishing guide +- [Endpoint Detailed Definition](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint): Endpoint reference ## Further Reading -For a complete Dify plugin project example, visit the [GitHub repository](https://github.com/langgenius/dify-plugins). You’ll also find additional plugins with full source code and implementation details. +For a complete Dify plugin project example, visit the [GitHub repository](https://github.com/langgenius/dify-plugins). You'll also find additional plugins with full source code and implementation details. -If you want to explore more about plugin development, check the following: +To explore more about plugin development, see the following: **Quick Starts**: + - [Develop an Extension Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) - [Develop a Model Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) - [Bundle Plugins: Packaging Multiple Plugins](/en/develop-plugin/features-and-specs/advanced-development/bundle) **Plugin Interface Docs**: -- [Defining Plugin Information via Manifest File](/en/develop-plugin/features-and-specs/plugin-types/plugin-info-by-manifest) - Manifest structure -- [Endpoint](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) - Endpoint detailed definition -- [Reverse Invocation](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation) - Reverse-calling Dify capabilities -- [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) - Tool specifications -- [Model Schema](/en/develop-plugin/features-and-specs/plugin-types/model-schema) - Model + +- [Defining Plugin Information via Manifest File](/en/develop-plugin/features-and-specs/plugin-types/plugin-info-by-manifest): Manifest structure +- [Endpoint](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint): Endpoint reference +- [Reverse Invocation](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation): Calling Dify capabilities from a plugin +- [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications): Tool specifications +- [Model Schema](/en/develop-plugin/features-and-specs/plugin-types/model-schema): Model schema reference {/* Contributing Section @@ -378,4 +378,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/dev-guides-and-walkthroughs/develop-a-slack-bot-plugin.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/develop-flomo-plugin.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/develop-flomo-plugin.mdx index 7e35ca043..fab72f914 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/develop-flomo-plugin.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/develop-flomo-plugin.mdx @@ -5,7 +5,7 @@ language: en standard_title: Flomo Tool (10-min) --- -## What you'll build +## What You'll Build By the end of this guide, you'll have created a Dify plugin that: @@ -23,7 +23,7 @@ By the end of this guide, you'll have created a Dify plugin that: -## Step 1: Install the Dify CLI and create a project +## Step 1: Install the Dify CLI and Create a Project @@ -44,7 +44,8 @@ By the end of this guide, you'll have created a Dify plugin that: - Verify installation: + Verify the installation: + ```bash dify version ``` @@ -58,9 +59,10 @@ By the end of this guide, you'll have created a Dify plugin that: ``` Follow the prompts to set up your plugin: - - Name it "flomo" - - Select "tool" as the plugin type - - Complete other required fields + + - Name it `flomo` + - Select `tool` as the plugin type + - Complete the other required fields @@ -68,14 +70,14 @@ By the end of this guide, you'll have created a Dify plugin that: cd flomo ``` - This will create the basic structure for your plugin with all necessary files. + The project contains the basic structure for your plugin with all necessary files. -## Step 2: Define your plugin manifest +## Step 2: Define Your Plugin Manifest -The manifest.yaml file defines your plugin's metadata, permissions, and capabilities. +The `manifest.yaml` file defines your plugin's metadata, permissions, and capabilities. Create a `manifest.yaml` file: @@ -111,7 +113,7 @@ meta: entrypoint: main ``` -## Step 3: Create the tool definition +## Step 3: Create the Tool Definition A tool plugin uses two YAML files: a **provider** file that declares credentials and lists the tools, and one **tool** file per callable tool. See [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) for the full schema. @@ -181,7 +183,7 @@ extra: source: tools/flomo.py ``` -## Step 4: Implement core utility functions +## Step 4: Implement Core Utility Functions Create a utility module in `utils/flomo_utils.py` for API interaction: @@ -279,17 +281,19 @@ class FlomoTool(Tool): Always handle exceptions gracefully and return user-friendly error messages. Remember that your plugin represents your brand in the Dify ecosystem. -## Step 7: Test your plugin +## Step 7: Test Your Plugin Copy the example environment file: + ```bash cp .env.example .env ``` Edit the `.env` file with your Dify environment details: - ``` + + ```bash INSTALL_METHOD=remote REMOTE_INSTALL_URL=debug-plugin.dify.dev:5003 REMOTE_INSTALL_KEY=your_debug_key @@ -308,12 +312,11 @@ Always handle exceptions gracefully and return user-friendly error messages. Rem - In your Dify instance, navigate to plugins and find your debugging plugin (marked as "debugging"). - Add your Flomo API credentials and test sending a note. + In your Dify instance, open the **Plugins** page and find your plugin (marked as **debugging**). Add your Flomo API credentials and test sending a note. -## Step 8: Package and distribute +## Step 8: Package and Distribute When you're ready to share your plugin: @@ -335,17 +338,17 @@ This creates a `plugin.difypkg` file you can upload to the Dify Marketplace. - Ensure all required files are present and the manifest.yaml structure is valid. + Ensure all required files are present and the `manifest.yaml` structure is valid. ## Summary -You've built a functioning Dify plugin that connects with an external API service! This same pattern works for integrating with thousands of services - from databases and search engines to productivity tools and custom APIs. +You've built a functioning Dify plugin that connects with an external API service. The same pattern works for integrating with thousands of services—from databases and search engines to productivity tools and custom APIs. - Write your README.md in English (en_US) describing functionality, setup, and usage examples + Write your `README.md` in English (en_US) describing functionality, setup, and usage examples Create additional README files like `readme/README_zh_Hans.md` for other languages @@ -373,4 +376,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/dev-guides-and-walkthroughs/develop-flomo-plugin.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/develop-md-exporter.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/develop-md-exporter.mdx index 88192eacf..f865be0f8 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/develop-md-exporter.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/develop-md-exporter.mdx @@ -5,9 +5,9 @@ language: en standard_title: Building a Markdown Exporter Plugin --- -## What you'll build +## What You'll Build -In this guide, you'll learn how to build a practical Dify plugin that exports conversations into popular document formats. By the end, your plugin will: +You'll build a practical Dify plugin that exports conversations into popular document formats. By the end, your plugin will: - Convert markdown text to Word documents (.docx) - Export conversations as PDF files @@ -23,7 +23,7 @@ In this guide, you'll learn how to build a practical Dify plugin that exports co -## Step 1: Set up your environment +## Step 1: Set Up Your Environment @@ -35,7 +35,7 @@ In this guide, you'll learn how to build a practical Dify plugin that exports co ``` - Get the latest Dify CLI from the [Dify GitHub releases page](https://github.com/langgenius/dify-plugin-daemon/releases) + Get the latest Dify CLI from the [Dify GitHub releases page](https://github.com/langgenius/dify-plugin-daemon/releases). ```bash # Download appropriate version @@ -47,6 +47,7 @@ In this guide, you'll learn how to build a practical Dify plugin that exports co Verify installation: + ```bash dify version ``` @@ -60,13 +61,14 @@ In this guide, you'll learn how to build a practical Dify plugin that exports co ``` Follow the prompts: - - Name: "md_exporter" - - Type: "tool" - - Complete other details as prompted + + - **Name**: `md_exporter` + - **Type**: `tool` + - Complete the remaining details as prompted. -## Step 2: Define plugin manifest +## Step 2: Define the Plugin Manifest Create the `manifest.yaml` file to define your plugin's metadata: @@ -102,7 +104,7 @@ meta: entrypoint: main ``` -## Step 3: Define the Word export tool +## Step 3: Define the Word Export Tool Create a `word_export.yaml` file to define the Word document export tool: @@ -143,7 +145,7 @@ tool_schema: zh_Hans: 导出文档的名称(无需扩展名) ``` -## Step 4: Define the PDF export tool +## Step 4: Define the PDF Export Tool Create a `pdf_export.yaml` file for PDF exports: @@ -184,7 +186,7 @@ tool_schema: zh_Hans: 导出文档的名称(无需扩展名) ``` -## Step 5: Install required dependencies +## Step 5: Install Required Dependencies Create or update `requirements.txt` with the necessary libraries: @@ -195,7 +197,7 @@ weasyprint>=59.0 beautifulsoup4>=4.12.2 ``` -## Step 6: Implement the Word export functionality +## Step 6: Implement the Word Export Create a utility module in `utils/docx_utils.py`: @@ -254,7 +256,7 @@ def convert_markdown_to_docx(markdown_text, document_name=None): ``` -## Step 7: Implement the PDF export functionality +## Step 7: Implement the PDF Export Create a utility module in `utils/pdf_utils.py`: @@ -320,7 +322,7 @@ def convert_markdown_to_pdf(markdown_text, document_name=None): ``` -## Step 8: Create tool implementations +## Step 8: Create the Tool Implementations First, create the Word export tool in `tools/word_export.py`: @@ -422,7 +424,7 @@ class PDFExportTool(Tool): ``` -## Step 9: Create the entrypoint +## Step 9: Create the Entrypoint Create a `main.py` file at the root of your project: @@ -442,17 +444,19 @@ plugin = PluginRunner( ``` -## Step 10: Test your plugin +## Step 10: Test Your Plugin First, create your `.env` file from the template: + ```bash cp .env.example .env ``` Configure it with your Dify environment details: - ``` + + ```dotenv INSTALL_METHOD=remote REMOTE_INSTALL_URL=debug-plugin.dify.dev:5003 REMOTE_INSTALL_KEY=your_debug_key @@ -472,7 +476,7 @@ plugin = PluginRunner( -## Step 11: Package for distribution +## Step 11: Package for Distribution When you're ready to share your plugin: @@ -482,7 +486,7 @@ dify plugin package ./ This creates a `plugin.difypkg` file for distribution. -## Creative use cases +## Creative Use Cases @@ -493,27 +497,27 @@ This creates a `plugin.difypkg` file for distribution. -## Beyond the basics +## Beyond the Basics Here are some interesting ways to extend this plugin: -- **Custom templates**: Add company branding or personalized styles -- **Multi-format support**: Expand to export as HTML, Markdown, or other formats -- **Image handling**: Process and include images from conversations -- **Table support**: Implement proper formatting for data tables -- **Collaborative editing**: Add integration with Google Docs or similar platforms +- **Custom templates**: Add company branding or personalized styles. +- **Multi-format support**: Expand to export as HTML, Markdown, or other formats. +- **Image handling**: Process and include images from conversations. +- **Table support**: Implement proper formatting for data tables. +- **Collaborative editing**: Add integration with Google Docs or similar platforms. - -The core challenge in document conversion is maintaining formatting and structure. The approach used in this plugin first converts markdown to HTML (an intermediate format), then processes that HTML into the target format. + +The core challenge in document conversion is maintaining formatting and structure. This plugin first converts markdown to HTML as an intermediate format, then processes that HTML into the target format. -This two-step process provides flexibility: you could extend it to support additional formats by simply adding new output modules that work with the HTML representation. +The two-step process provides flexibility: you can support additional formats by adding new output modules that work with the HTML representation. -For PDF generation, WeasyPrint was chosen because it offers high-quality PDF rendering with CSS support. For Word documents, python-docx provides granular control over document structure. +For PDF generation, the plugin uses WeasyPrint because it offers high-quality PDF rendering with CSS support. For Word documents, python-docx provides granular control over document structure. ## Summary -You've built a practical plugin that adds real value to the Dify platform by enabling users to export conversations in professional document formats. This functionality bridges the gap between AI conversations and traditional document workflows. +You've built a practical plugin that lets users export conversations in professional document formats, bridging the gap between AI conversations and traditional document workflows. diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/develop-multimodal-data-processing-tool.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/develop-multimodal-data-processing-tool.mdx index 3f7f0a335..e51dc26ee 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/develop-multimodal-data-processing-tool.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/develop-multimodal-data-processing-tool.mdx @@ -5,17 +5,16 @@ description: Configure a tool plugin to emit images, audio, or video so the Know In knowledge pipelines, the Knowledge Base node supports input in two multimodal data formats: `multimodal-Parent-Child` and `multimodal-General`. -When developing a tool plugin for multimodal data processing, to ensure that the plugin's multimodal output (such as text, images, audio, video, etc.) can be correctly recognized and embedded by the Knowledge Base node, you need to complete the following configuration: +For the Knowledge Base node to recognize and embed a tool plugin's multimodal output (such as text, images, audio, or video), complete two configurations: -- **In the tool code file**, call the tool session interface to upload files and construct the `files` object. - -- **In the tool provider YAML file**, declare the `output_schema` as either `multimodal-Parent-Child` or `multimodal-General`. +- **In the tool code file**: Call the tool session interface to upload files and construct the `files` object. +- **In the tool provider YAML file**: Declare the `output_schema` as either `multimodal-Parent-Child` or `multimodal-General`. ## Upload Files and Construct File Objects -When processing multimodal data (such as images), you need to first upload the file using Dify's tool session tool to obtain the file metadata. +When processing multimodal data such as images, first upload the file through Dify's tool session to obtain the file metadata. -The following example uses the official Dify plugin, **Dify Extractor**, to demonstrate how to upload a file and construct a `files` object. +The following example, taken from the official **Dify Extractor** plugin, shows how to upload a file and construct a `files` object. ```python # Upload the file using the tool session @@ -28,41 +27,42 @@ file_res = self._tool.session.file.upload( # Generate a Markdown image reference using the file preview URL image_url = f"![image]({file_res.preview_url})" ``` -The upload interface returns an `UploadFileResponse` object containing the file information. Its structure is as follows: -```python - from enum import Enum - from pydantic import BaseModel +The upload interface returns an `UploadFileResponse` object containing the file information: + +```python +from enum import Enum +from pydantic import BaseModel - class UploadFileResponse(BaseModel): - class Type(str, Enum): - DOCUMENT = "document" - IMAGE = "image" - VIDEO = "video" - AUDIO = "audio" +class UploadFileResponse(BaseModel): + class Type(str, Enum): + DOCUMENT = "document" + IMAGE = "image" + VIDEO = "video" + AUDIO = "audio" - @classmethod - def from_mime_type(cls, mime_type: str): - if mime_type.startswith("image/"): - return cls.IMAGE - if mime_type.startswith("video/"): - return cls.VIDEO - if mime_type.startswith("audio/"): - return cls.AUDIO - return cls.DOCUMENT - id: str - name: str - size: int - extension: str - mime_type: str - type: Type | None = None - preview_url: str | None = None + @classmethod + def from_mime_type(cls, mime_type: str): + if mime_type.startswith("image/"): + return cls.IMAGE + if mime_type.startswith("video/"): + return cls.VIDEO + if mime_type.startswith("audio/"): + return cls.AUDIO + return cls.DOCUMENT + id: str + name: str + size: int + extension: str + mime_type: str + type: Type | None = None + preview_url: str | None = None ``` -You can map the file information (such as `name`, `size`, `extension`, `mime_type`, etc.) to the `files` field in the multimodal output structure. +Map the file information (`name`, `size`, `extension`, `mime_type`, and so on) to the `files` field in the multimodal output structure. - ```yaml multimodal_parent_child_structure highlight={22-62} expandable + ```json multimodal_parent_child_structure highlight={22-62} expandable { "$id": "https://dify.ai/schemas/v1/multimodal_parent_child_structure.json", "$schema": "http://json-schema.org/draft-07/schema#", @@ -143,7 +143,7 @@ You can map the file information (such as `name`, `size`, `extension`, `mime_typ } ``` - ```yaml multimodal_general_structure highlight={18-56} expandable + ```json multimodal_general_structure highlight={18-56} expandable { "$id": "https://dify.ai/schemas/v1/multimodal_general_structure.json", "$schema": "http://json-schema.org/draft-07/schema#", @@ -214,9 +214,9 @@ You can map the file information (such as `name`, `size`, `extension`, `mime_typ ## Declare Multimodal Output Structure -The structure of multimodal data is defined by Dify's official JSON schema. +Dify's official JSON schemas define the structure of multimodal data. -To enable the Knowledge Base node to recognize the plugin's multimodal output type, you need to point the `result` field under `output_schema` in the plugin's provider YAML file to the corresponding official schema URL. +To let the Knowledge Base node recognize the plugin's multimodal output type, point the `result` field under `output_schema` in the plugin's provider YAML file to the corresponding official schema URL. ```yaml output_schema: @@ -230,7 +230,7 @@ output_schema: # $ref: "https://dify.ai/schemas/v1/multimodal_general_structure.json" ``` -Taking `multimodal-Parent-Child` as an example, a complete YAML configuration is as follows: +For example, a complete YAML configuration using `multimodal-Parent-Child` looks like this: ```yaml expandable identity: @@ -270,4 +270,4 @@ output_schema: extra: python: source: tools/parent_child_chunk.py -``` \ No newline at end of file +``` diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/endpoint.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/endpoint.mdx index 433fbfb8c..e51c5ae8b 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/endpoint.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/endpoint.mdx @@ -7,33 +7,29 @@ dimensions: standard_title: Endpoint language: en title: Endpoint Plugin -description: Authors Yeuoly, Allen. This document details the structure and implementation - of Endpoints in Dify plugins, using the Neko Cat project as an example. It covers - defining Endpoint groups, configuring interfaces, implementing the _invoke method, - and handling requests and responses. The document explains the meaning and usage - of various YAML configuration fields. +description: Define, configure, and implement HTTP Endpoints in a Dify plugin, using the Neko Cat project as an example --- -This document uses the [Neko Cat](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/neko) project as an example to explain the structure of Endpoints within a plugin. Endpoints are HTTP interfaces exposed by the plugin, which can be used for integration with external systems. For the complete plugin code, see the [GitHub repository](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/neko). +Endpoints are HTTP interfaces exposed by a plugin for integration with external systems. This guide explains their structure using the [Neko Cat](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/neko) project as an example. For the complete plugin code, see the [GitHub repository](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/neko). ## Group Definition -An `Endpoint` group is a collection of multiple `Endpoints`. When creating a new `Endpoint` within a Dify plugin, you might need to fill in the following configuration. +An Endpoint group is a collection of multiple Endpoints. When you create a new Endpoint in a Dify plugin, you may need to fill in the following configuration. - ![](https://assets-docs.dify.ai/2024/11/763dbf86e4319591415dc5a1b6948ccb.png) + ![Endpoint Group Configuration Form](https://assets-docs.dify.ai/2024/11/763dbf86e4319591415dc5a1b6948ccb.png) -Besides the `Endpoint Name`, you can add new form items by writing the group's configuration information. After clicking save, you can see the multiple interfaces it contains, which will use the same configuration information. +Besides the **Endpoint Name**, you can add form items by writing the group's configuration. After saving, you can see the multiple interfaces the group contains, all sharing the same configuration. - ![Besides the Endpoint Name, You Can Add New Form Items by Writing the Group's](https://assets-docs.dify.ai/2024/11/b778b7093b7df0dc80a476c65ddcbe58.png) + ![Endpoint Group Interface List](https://assets-docs.dify.ai/2024/11/b778b7093b7df0dc80a476c65ddcbe58.png) -### **Structure** +### Structure -* `settings` (map[string] [ProviderConfig](/en/develop-plugin/features-and-specs/plugin-types/general-specifications#providerconfig)): Endpoint configuration definition. -* `endpoints` (list[string], required): Points to the specific `endpoint` interface definitions. +- **`settings`** (map[string] [ProviderConfig](/en/develop-plugin/features-and-specs/plugin-types/general-specifications#providerconfig)): Endpoint configuration definition. +- **`endpoints`** (list[string], required): Points to the specific `endpoint` interface definitions. ```yaml settings: @@ -57,11 +53,11 @@ endpoints: ## Interface Definition -* `path` (string): Follows the Werkzeug interface standard. -* `method` (string): Interface method, only supports `HEAD`, `GET`, `POST`, `PUT`, `DELETE`, `OPTIONS`. -* `extra` (object): Configuration information beyond the basic details. - * `python` (object) - * `source` (string): The source code that implements this interface. +- **`path`** (string): Follows the Werkzeug interface standard. +- **`method`** (string): Interface method; supports only `HEAD`, `GET`, `POST`, `PUT`, `DELETE`, and `OPTIONS`. +- **`extra`** (object): Configuration information beyond the basic details. + - **`python`** (object) + - **`source`** (string): The source code that implements this interface. ```yaml path: "/duck/" @@ -73,15 +69,15 @@ extra: ## Interface Implementation -You need to implement a subclass that inherits from `dify_plugin.Endpoint` and implement the `_invoke` method. +Implement a subclass of `dify_plugin.Endpoint` and its `_invoke` method. -* **Input Parameters** - * `r` (Request): The `Request` object from `werkzeug`. - * `values` (Mapping): Path parameters parsed from the path. - * `settings` (Mapping): Configuration information for this `Endpoint`. -* **Return** - * A `Response` object from `werkzeug`, supports streaming responses. - * Directly returning a string is not supported. +- **Input parameters** + - **`r`** (Request): The `Request` object from `werkzeug`. + - **`values`** (Mapping): Path parameters parsed from the path. + - **`settings`** (Mapping): Configuration information for this Endpoint. +- **Return** + - A `Response` object from `werkzeug`; streaming responses are supported. + - Returning a string directly is not supported. Example code: @@ -106,20 +102,20 @@ class Duck(Endpoint): ## Notes -* Endpoints are only instantiated when the plugin is called; they are not long-running services. -* Pay attention to security when developing Endpoints and avoid executing dangerous operations. -* Endpoints can be used to handle Webhook callbacks or provide interfaces for other systems to connect. +- Endpoints are only instantiated when the plugin is called; they are not long-running services. +- Pay attention to security when developing Endpoints, and avoid executing dangerous operations. +- Endpoints can handle webhook callbacks or provide interfaces for other systems to connect to. -If you are learning plugin development, it is recommended to first read the [Getting Started with Plugin Development](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) and the [Developer Cheatsheet](/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet). +If you're new to plugin development, start with [Getting Started with Plugin Development](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) and the [Developer Cheatsheet](/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet). ## Related Resources -* [Basic Concepts of Plugin Development](/en/develop-plugin/getting-started/getting-started-dify-plugin) - Understand the overall architecture of plugin development. -* [Neko Cat Example](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) - An example of extension plugin development. -* [General Specifications Definition](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) - Understand common structures like ProviderConfig. -* [Develop a Slack Bot Plugin Example](/en/develop-plugin/dev-guides-and-walkthroughs/develop-a-slack-bot-plugin) - Another plugin development example. -* [Getting Started with Plugin Development](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) - Develop a plugin from scratch. -* [Reverse Invocation of Dify Services](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app) - Learn how to use the reverse invocation feature. +- [Basic Concepts of Plugin Development](/en/develop-plugin/getting-started/getting-started-dify-plugin): The overall architecture of plugin development. +- [Neko Cat Example](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint): An example of extension plugin development. +- [General Specifications Definition](/en/develop-plugin/features-and-specs/plugin-types/general-specifications): Common structures like ProviderConfig. +- [Develop a Slack Bot Plugin Example](/en/develop-plugin/dev-guides-and-walkthroughs/develop-a-slack-bot-plugin): Another plugin development example. +- [Getting Started with Plugin Development](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin): Develop a plugin from scratch. +- [Reverse Invocation of Dify Services](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app): Use the reverse invocation feature. {/* Contributing Section @@ -130,4 +126,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/dev-guides-and-walkthroughs/endpoint.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/tool-oauth.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/tool-oauth.mdx index e79c602d0..1a0fe9c9a 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/tool-oauth.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/tool-oauth.mdx @@ -45,35 +45,35 @@ sequenceDiagram ### Flow 1: OAuth Client Setup (Admin / Developer Flow) - On Dify Cloud, Dify team would create OAuth apps for popular tool plugins and set up OAuth clients, saving users the trouble to configure this themselves. + On Dify Cloud, the Dify team creates OAuth apps for popular tool plugins and sets up OAuth clients, so users don't need to configure this themselves. - Admins of Self-Hosted Dify instances must go through this setup flow. + Admins of self-hosted Dify instances must go through this setup flow. -Dify instance's admins or developers first need to register an OAuth app at the third-party service as a trusted application. From this, they'll be able to obtain the necessary credentials to configure the Dify tool provider as an OAuth client. +Admins or developers of a Dify instance first register an OAuth app with the third-party service as a trusted application. This provides the credentials needed to configure the Dify tool provider as an OAuth client. -As an example, here are the steps to setting up an OAuth client for Dify's Gmail tool provider: +As an example, here are the steps to set up an OAuth client for Dify's Gmail tool provider: - 1. Go to [Google Cloud Console](https://console.cloud.google.com) and create a new project, or select existing one - 2. Enable the required APIs (e.g., Gmail API) + 1. Go to [Google Cloud Console](https://console.cloud.google.com) and create a new project, or select an existing one. + 2. Enable the required APIs (e.g., Gmail API). - - 1. Navigate to **APIs & Services** \> **OAuth consent screen** - 2. Choose **External** user type for public plugins - 3. Fill in application name, user support email, and developer contact - 4. Add authorized domains if needed - 5. For testing: Add test users in the **Test users** section + + 1. Navigate to **APIs & Services** \> **OAuth consent screen**. + 2. Choose the **External** user type for public plugins. + 3. Fill in the application name, user support email, and developer contact. + 4. Add authorized domains if needed. + 5. For testing, add test users in the **Test users** section. - 1. Go to **APIs & Services** \> **Credentials** - 2. Click **Create Credentials** \> **OAuth 2.0 Client IDs** - 3. Choose **Web application** type - 4. A`client_id` and a`client_secret` will be generated. Save these as the credentials. + 1. Go to **APIs & Services** \> **Credentials**. + 2. Click **Create Credentials** \> **OAuth 2.0 Client IDs**. + 3. Choose the **Web application** type. + 4. A `client_id` and a `client_secret` will be generated. Save these as the credentials. - Enter the client_id and client_secret on the OAuth Client configuration popup to set up the tool provider as a client. + Enter the `client_id` and `client_secret` in the OAuth Client configuration popup to set up the tool provider as a client. ![OAuth Client Settings Dialog](/images/develop-plugin/dev-guide/oauth-client-settings-dialog.png) @@ -88,13 +88,13 @@ As an example, here are the steps to setting up an OAuth client for Dify's Gmail - Dify displays the `redirect_uri` in the OAuth Client configuration popup. It usually follows the format: + Dify displays the `redirect_uri` in the OAuth Client configuration popup. It usually follows the format: ```bash https://{your-dify-domain}/console/api/oauth/plugin/{plugin-id}/{provider-name}/{tool-name}/callback ``` - For self-hosted Dify, the `your-dify-domain` should be consistent with the `CONSOLE_WEB_URL`. + For self-hosted Dify, `your-dify-domain` should match `CONSOLE_WEB_URL`. @@ -115,7 +115,7 @@ After configuring OAuth clients, individual Dify users can now authorize your pl ### 1. Define OAuth Schema in Provider Manifest -The `oauth_schema` section of the provider manifest definitions tells Dify what credentials your plugin OAuth needs and what the OAuth flow will produce. Two schemas are required for setting up OAuth: +The `oauth_schema` section of the provider manifest tells Dify what credentials your plugin's OAuth setup needs and what the OAuth flow produces. Setting up OAuth requires two schemas: #### client_schema @@ -134,7 +134,7 @@ oauth_schema: ``` - The `url` field links directly to help documentations for the third-party service. This helps confused admins / developers. + The `url` field links to the third-party service's help documentation, giving admins and developers a reference during setup. #### credentials_schema @@ -153,22 +153,22 @@ Specifies what the user authorization flow produces (Dify manages these automati ``` - Include both `oauth_schema` and `credentials_for_provider` to offer OAuth \+ API key auth options. + Include `oauth_schema` and `credentials_for_provider` together to offer both OAuth and API key authentication options. ### 2. Complete Required OAuth Methods in Tool Provider -Add these imports to where your `ToolProvider` is implemented: +Add these imports where your `ToolProvider` is implemented: ```python from dify_plugin.entities.oauth import ToolOAuthCredentials from dify_plugin.errors.tool import ToolProviderCredentialValidationError, ToolProviderOAuthError ``` -Your `ToolProvider` class must implement these three OAuth methods (taking `GmailProvider` as an example): +Your `ToolProvider` class must implement these three OAuth methods (using `GmailProvider` as an example): - Under no circumstances should the `client_secret` be returned in the credentials of `ToolOAuthCredentials`, as this could lead to security issues. + Never return the `client_secret` in the credentials of `ToolOAuthCredentials`; doing so could lead to security issues. @@ -205,7 +205,7 @@ def _oauth_get_credentials( ) -> ToolOAuthCredentials: """ Exchange authorization code for access token and refresh token. This is called - to creates ONE credential set for one account connection + to create ONE credential set for one account connection. """ # Extract authorization code from OAuth callback code = request.args.get("code") @@ -279,8 +279,8 @@ def _oauth_refresh_credentials( self, redirect_uri: str, system_credentials: Mapping[str, Any], credentials: Mapping[str, Any] ) -> ToolOAuthCredentials: """ - Refresh the credentials using refresh token. - Dify calls this automatically when tokens expire + Refresh the credentials using the refresh token. + Dify calls this automatically when tokens expire. """ refresh_token = credentials.get("refresh_token") if not refresh_token: @@ -346,7 +346,7 @@ def _oauth_refresh_credentials( ### 3. Access Tokens in Your Tools -You may use OAuth credentials to make authenticated API calls in your `Tool` implementation like so: +Use OAuth credentials to make authenticated API calls in your `Tool` implementation: ```python class YourTool(BuiltinTool): @@ -361,13 +361,13 @@ class YourTool(BuiltinTool): `self.runtime.credentials` automatically provides the current user's tokens. Dify handles refresh automatically. -For plugins that support both OAuth and API_KEY authentication, you can use `self.runtime.credential_type` to differentiate between the two authentication types. +For plugins that support both OAuth and `API_KEY` authentication, use `self.runtime.credential_type` to differentiate between the two authentication types. ### 4. Specify the Correct Versions OAuth requires a recent SDK and Dify version. Pin the plugin SDK in `requirements.txt`: -``` +```text dify_plugin>=0.5.0 ``` @@ -395,4 +395,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/dev-guides-and-walkthroughs/tool-oauth.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin.mdx index 01eb404ab..d1898aed4 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin.mdx @@ -7,22 +7,18 @@ dimensions: standard_title: Tool Plugin language: en title: Tool Plugin -description: This document provides detailed instructions on how to develop tool plugins - for Dify, using Google Search as an example to demonstrate a complete tool plugin - development process. The content includes plugin initialization, template selection, - tool provider configuration file definition, adding third-party service credentials, - tool functionality code implementation, debugging, and packaging for release. +description: Develop a Dify tool plugin from initialization to packaging, using Google Search as a worked example --- -Tools refer to third-party services that can be called by Chatflow / Workflow / Agent-type applications, providing complete API implementation capabilities to enhance Dify applications. For example, adding extra features like online search, image generation, and more. +Tools are third-party services that Chatflow, Workflow, and Agent applications can call. They extend Dify applications with capabilities such as online search and image generation. ![Tool Plugin Example](https://assets-docs.dify.ai/2024/12/7e7bcf1f9e3acf72c6917ea9de4e4613.png) -In this article, **"Tool Plugin"** refers to a complete project that includes tool provider files, functional code, and other structures. A tool provider can include multiple Tools (which can be understood as additional features provided within a single tool), structured as follows: +In this guide, a *tool plugin* is a complete project that includes tool provider files, functional code, and supporting structures. A tool provider can bundle multiple tools, each offering a distinct capability: -``` +```text - Tool Provider - Tool A - Tool B @@ -32,14 +28,14 @@ In this article, **"Tool Plugin"** refers to a complete project that includes to ![Tool Plugin Structure](https://assets-docs.dify.ai/2025/02/60c4c86a317d865133aa460592eac079.png) -This article will use `Google Search` as an example to demonstrate how to quickly develop a tool plugin. +This guide uses Google Search as an example to walk through tool plugin development. ## Prerequisites -- Dify plugin scaffolding tool -- Python environment (version 3.12) +- Dify plugin scaffolding tool +- Python environment (version 3.12) -For detailed instructions on how to prepare the plugin development scaffolding tool, please refer to [Initializing Development Tools](/en/develop-plugin/getting-started/cli). +To set up the scaffolding tool, see [Initializing Development Tools](/en/develop-plugin/getting-started/cli). ## Create a New Project @@ -55,13 +51,17 @@ If you have renamed the binary file to `dify` and copied it to the `/usr/local/b dify plugin init ``` -> In the following text, `dify` will be used as a command line example. If you encounter any issues, please replace the `dify` command with the path to the command line tool. + +The following examples use `dify` as the command. If you run into issues, replace `dify` with the path to your command-line tool. + ## Choose Plugin Type and Template -All templates in the scaffolding tool provide complete code projects. In this example, select the `Tool` plugin. +Each template in the scaffolding tool is a complete code project. For this example, select the `Tool` plugin. -> If you are already familiar with plugin development and do not need to rely on templates, you can refer to the [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) guide to complete the development of different types of plugins. + +If you are already familiar with plugin development and don't need a template, see the [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) guide to build any plugin type. + ![Plugin Type: Tool](https://assets-docs.dify.ai/2024/12/dd3c0f9a66454e15868eabced7b74fd6.png) @@ -69,16 +69,18 @@ All templates in the scaffolding tool provide complete code projects. In this ex ### Configure Plugin Permissions -The plugin also needs permissions to read from the Dify platform. Grant the following permissions to this example plugin: +The plugin also needs permissions to read from the Dify platform. Grant this example plugin the following permissions: -- Tools -- Apps -- Enable persistent storage Storage, allocate default size storage -- Allow registering Endpoints +- Tools +- Apps +- Enable persistent storage, with the default storage size +- Allow registering Endpoints -> Use the arrow keys in the terminal to select permissions, and use the "Tab" button to grant permissions. + +In the terminal, use the arrow keys to select permissions and the Tab key to grant them. + -After checking all permission items, press Enter to complete the plugin creation. The system will automatically generate the plugin project code. +After checking all permission items, press Enter to complete the plugin creation. The system generates the plugin project code automatically. ![Plugin Permissions](https://assets-docs.dify.ai/2024/12/9cf92c2e74dce55e6e9e331d031e5a9f.png) @@ -88,24 +90,24 @@ After checking all permission items, press Enter to complete the plugin creation ### 1. Create the Tool Provider File -The tool provider file is a yaml format file, which can be understood as the basic configuration entry for the tool plugin, used to provide necessary authorization information to the tool. +The tool provider file is a YAML file that serves as the plugin's base configuration, supplying the authorization information the tool needs. -Go to the `/provider` path in the plugin template project and rename the yaml file to `google.yaml`. This `yaml` file will contain information about the tool provider, including the provider's name, icon, author, and other details. This information will be displayed when installing the plugin. +In the plugin template project, go to the `/provider` directory and rename the YAML file to `google.yaml`. This file describes the tool provider: name, icon, author, and other details shown when the plugin is installed. -**Example Code** +Example code: ```yaml -identity: # Basic information of the tool provider +identity: # Basic information about the tool provider author: Your-name # Author - name: google # Name, unique, cannot have the same name as other providers - label: # Label, for frontend display + name: google # Unique name; must not duplicate another provider's name + label: # Label shown in the frontend en_US: Google # English label zh_Hans: Google # Chinese label - description: # Description, for frontend display + description: # Description shown in the frontend en_US: Google # English description zh_Hans: Google # Chinese description - icon: icon.svg # Tool icon, needs to be placed in the _assets folder - tags: # Tags, for frontend display + icon: icon.svg # Tool icon; must be placed in the _assets folder + tags: # Tags shown in the frontend - search ``` @@ -117,10 +119,10 @@ plugins: - 'google.yaml' ``` -Where `google.yaml` needs to use its absolute path in the plugin project. In this example, it is located in the project root directory. The identity field in the YAML file is explained as follows: `identity` contains basic information about the tool provider, including author, name, label, description, icon, etc. +`google.yaml` must be referenced by its absolute path within the plugin project; in this example, it sits in the project root directory. In the YAML file, `identity` holds the tool provider's basic information: author, name, label, description, and icon. -- The icon needs to be an attachment resource and needs to be placed in the `_assets` folder in the project root directory. -- Tags can help users quickly find plugins through categories. Below are all the currently supported tags. +- The icon must be an attachment resource placed in the `_assets` folder in the project root directory. +- Tags help users find plugins by category. These are all the currently supported tags: ```python class ToolLabelEnum(Enum): @@ -142,11 +144,11 @@ class ToolLabelEnum(Enum): OTHER = 'other' ``` -### **2. Complete Third-Party Service Credentials** +### 2. Add Third-Party Service Credentials -For development convenience, we choose to use the Google Search API provided by the third-party service `SerpApi`. `SerpApi` requires an API Key for use, so we need to add the `credentials_for_provider` field in the `yaml` file. +For convenience, this example uses the Google Search API provided by the third-party service SerpApi. SerpApi requires an API key, so add a `credentials_for_provider` field to the YAML file. -The complete code is as follows: +The complete code: ```yaml identity: @@ -163,7 +165,7 @@ identity: icon: icon.svg tags: - search -credentials_for_provider: #Add credentials_for_provider field +credentials_for_provider: # Add the credentials_for_provider field serpapi_api_key: type: secret-input required: true @@ -184,15 +186,15 @@ extra: source: google.py ``` -- The sub-level structure of `credentials_for_provider` needs to meet the requirements of [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications). -- You need to specify which tools the provider includes. This example only includes one `tools/google_search.yaml` file. -- As a provider, in addition to defining its basic information, you also need to implement some of its code logic, so you need to specify its implementation logic. In this example, we put the code file for the functionality in `google.py`, but we won't implement it yet, but instead write the code for `google_search` first. +- The sub-level structure of `credentials_for_provider` must meet the requirements in [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications). +- Specify which tools the provider includes. This example includes only one file, `tools/google_search.yaml`. +- Besides its basic information, a provider needs code logic, so specify its implementation file. This example uses `google.py`, but leave it unimplemented for now and write the `google_search` tool code first. ### 3. Fill in the Tool YAML File -A tool plugin can have multiple tool functions, and each tool function needs a `yaml` file for description, including basic information about the tool function, parameters, output, etc. +A tool plugin can contain multiple tools, each described by its own YAML file covering basic information, parameters, and output. -Still using the `GoogleSearch` tool as an example, create a new `google_search.yaml` file in the `/tools` folder. +Continuing with the `GoogleSearch` tool, create a new `google_search.yaml` file in the `/tools` folder. ```yaml identity: @@ -227,30 +229,30 @@ extra: source: tools/google_search.py ``` -- `identity` contains basic information about the tool, including name, author, label, description, etc. -- `parameters` parameter list - - `name` (required) parameter name, unique, cannot have the same name as other parameters. - - `type` (required) parameter type, currently supports `string`, `number`, `boolean`, `select`, `secret-input` five types, corresponding to string, number, boolean, dropdown, encrypted input box. For sensitive information, please use the `secret-input` type. - - `label` (required) parameter label, for frontend display. - - `form` (required) form type, currently supports `llm`, `form` two types. - - In Agent applications, `llm` means that the parameter is inferred by the LLM itself, `form` means that parameters can be preset in advance to use this tool. - - In Workflow applications, both `llm` and `form` need to be filled in by the frontend, but `llm` parameters will be used as input variables for the tool node. - - `required` whether required - - In `llm` mode, if the parameter is required, the Agent will be required to infer this parameter. - - In `form` mode, if the parameter is required, the user will be required to fill in this parameter on the frontend before the conversation begins. - - `options` parameter options - - In `llm` mode, Dify will pass all options to the LLM, and the LLM can infer based on these options. - - In `form` mode, when `type` is `select`, the frontend will display these options. - - `default` default value. - - `min` minimum value, can be set when the parameter type is `number`. - - `max` maximum value, can be set when the parameter type is `number`. - - `human_description` introduction for frontend display, supports multiple languages. - - `placeholder` prompt text for the input field, can be set when the form type is `form` and the parameter type is `string`, `number`, `secret-input`, supports multiple languages. - - `llm_description` introduction passed to the LLM. To make the LLM better understand this parameter, please write as detailed information as possible about this parameter here, so that the LLM can understand the parameter. - -### 4. Prepare Tool Code - -After filling in the configuration information for the tool, you can start writing the code for the tool's functionality, implementing the logical purpose of the tool. Create `google_search.py` in the `/tools` directory with the following content: +- **`identity`**: Basic information about the tool, including name, author, label, and description. +- **`parameters`**: The parameter list. + - **`name`** (required): Parameter name; must be unique among the tool's parameters. + - **`type`** (required): Parameter type. One of `string`, `number`, `boolean`, `select`, or `secret-input`, rendered as a string, number, boolean, dropdown, or encrypted input box. Use `secret-input` for sensitive information. + - **`label`** (required): Parameter label, shown in the frontend. + - **`form`** (required): Form type, either `llm` or `form`. + - In Agent applications, `llm` means the LLM infers the parameter itself, while `form` means the parameter can be preset before using the tool. + - In Workflow applications, both `llm` and `form` parameters are filled in via the frontend, but `llm` parameters are used as input variables for the tool node. + - **`required`** (optional): Whether the parameter is required. + - In `llm` mode, a required parameter must be inferred by the Agent. + - In `form` mode, a required parameter must be filled in on the frontend before the conversation begins. + - **`options`** (optional): Parameter options. + - In `llm` mode, Dify passes all options to the LLM, which can infer based on them. + - In `form` mode, the frontend displays the options when `type` is `select`. + - **`default`** (optional): Default value. + - **`min`** (optional): Minimum value; applies when the parameter type is `number`. + - **`max`** (optional): Maximum value; applies when the parameter type is `number`. + - **`human_description`** (optional): Description shown in the frontend; supports multiple languages. + - **`placeholder`** (optional): Hint text for the input field; applies when the form type is `form` and the parameter type is `string`, `number`, or `secret-input`. Supports multiple languages. + - **`llm_description`** (optional): Description passed to the LLM. Write it in as much detail as possible so the LLM understands the parameter. + +### 4. Write the Tool Code + +With the tool configuration in place, write the code that implements the tool's logic. Create `google_search.py` in the `/tools` directory with the following content: ```python from collections.abc import Generator @@ -297,11 +299,11 @@ class GoogleSearchTool(Tool): yield self.create_json_message(valuable_res) ``` -This example means requesting `serpapi` and using `self.create_json_message` to return a formatted `json` data string. If you want to learn more about return data types, you can refer to the [Remote Debugging Plugins](/en/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin) and [Persistent Storage KV](/en/develop-plugin/features-and-specs/plugin-types/persistent-storage-kv) documents. +This code sends a request to `serpapi` and uses `self.create_json_message` to return formatted JSON data. To learn more about return data types, see [Remote Debugging Plugins](/en/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin) and [Persistent Storage KV](/en/develop-plugin/features-and-specs/plugin-types/persistent-storage-kv). ### 5. Complete the Tool Provider Code -Finally, you need to create an implementation code for the provider to implement the credential validation logic. If credential validation fails, a `ToolProviderCredentialValidationError` exception will be thrown. After validation succeeds, the `google_search` tool service will be correctly requested. +Finally, implement the provider's credential validation logic. If validation fails, the code raises a `ToolProviderCredentialValidationError` exception; once validation succeeds, the `google_search` tool service is requested correctly. Create a `google.py` file in the `/provider` directory with the following content: @@ -325,15 +327,15 @@ class GoogleProvider(ToolProvider): ## Debug the Plugin -After completing plugin development, you need to test whether the plugin can function properly. Dify provides a convenient remote debugging method to help you quickly verify the plugin's functionality in a test environment. +After development, test whether the plugin works correctly. Dify provides remote debugging so you can quickly verify the plugin's functionality in a test environment. -Go to the ["Plugin Management"](https://cloud.dify.ai/plugins) page to obtain the remote server address and debugging Key. +Go to the [Plugin Management](https://cloud.dify.ai/plugins) page to get the remote server address and debug key. ![Remote Debug Key](https://assets-docs.dify.ai/2024/12/053415ef127f1f4d6dd85dd3ae79626a.png) -Return to the plugin project, copy the `.env.example` file and rename it to `.env`, then fill in the remote server address and debugging Key information you obtained. +Back in the plugin project, copy the `.env.example` file, rename it to `.env`, and fill in the remote server address and debug key. `.env` file: @@ -343,7 +345,7 @@ REMOTE_INSTALL_URL=debug.dify.ai:5003 REMOTE_INSTALL_KEY=********-****-****-****-************ ``` -Run the `python -m main` command to start the plugin. On the plugins page, you can see that the plugin has been installed in the Workspace, and other members of the team can also access the plugin. +Run `python -m main` to start the plugin. On the **Plugins** page, you can see the plugin installed in the workspace, where other team members can also access it. ![Run the Python -M Main Command to Start the Plugin](https://assets-docs.dify.ai/2024/11/0fe19a8386b1234755395018bc2e0e35.png) @@ -351,7 +353,7 @@ Run the `python -m main` command to start the plugin. On the plugins page, you c ## Package the Plugin (Optional) -After confirming that the plugin can run normally, you can package and name the plugin using the following command line tool. After running, you will discover a `google.difypkg` file in the current folder, which is the final plugin package. +Once the plugin runs correctly, package and name it with the following command. It produces a `google.difypkg` file in the current folder—the final plugin package. ```bash # Replace ./google with the actual path of the plugin project @@ -359,36 +361,36 @@ After confirming that the plugin can run normally, you can package and name the dify plugin package ./google ``` -Congratulations, you have completed the entire process of developing, debugging, and packaging a tool-type plugin! +Congratulations—you've developed, debugged, and packaged a tool plugin! ## Publish the Plugin (Optional) -If you want to publish the plugin to the Dify Marketplace, please ensure that your plugin follows the specifications in [Publish to Dify Marketplace](/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace). After passing the review, the code will be merged into the main branch and automatically launched to the [Dify Marketplace](https://marketplace.dify.ai/). +To publish the plugin to the Dify Marketplace, make sure it follows the specifications in [Publish to Dify Marketplace](/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace). After the review passes, the code is merged into the main branch and automatically released on the [Dify Marketplace](https://marketplace.dify.ai/). -[Publishing Overview](/en/develop-plugin/publishing/marketplace-listing/release-overview) +For the full process, see the [Publishing Overview](/en/develop-plugin/publishing/marketplace-listing/release-overview). ## Explore More -### **Quick Start**: +### Quick Start -- [Developing Extension Plugins](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) -- [Developing Model Plugins](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) -- [Bundle Plugins: Packaging Multiple Plugins](/en/develop-plugin/features-and-specs/advanced-development/bundle) +- [Developing Extension Plugins](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) +- [Developing Model Plugins](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) +- [Bundle Plugins: Packaging Multiple Plugins](/en/develop-plugin/features-and-specs/advanced-development/bundle) -### **Plugin Interface Documentation**: +### Plugin Interface Documentation -- [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) - Manifest Structure and Tool Specifications -- [Endpoint](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) - Detailed Endpoint Definition -- [Reverse Invocation](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation) - Reverse Invocation of Dify Capabilities -- [Model Schema](/en/develop-plugin/features-and-specs/plugin-types/model-schema) - Models -- [Agent Plugins](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation) - Extending Agent Strategies +- [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications): Manifest structure and tool specifications. +- [Endpoint](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint): Detailed Endpoint definition. +- [Reverse Invocation](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation): Reverse invocation of Dify capabilities. +- [Model Schema](/en/develop-plugin/features-and-specs/plugin-types/model-schema): Models. +- [Agent Plugins](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation): Extending Agent strategies. -## Next Learning Steps +## Next Steps -- [Remote Debugging Plugins](/en/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin) - Learn more advanced debugging techniques -- [Persistent Storage](/en/develop-plugin/features-and-specs/plugin-types/persistent-storage-kv) - Learn how to use data storage in plugins -- [Slack Bot Plugin Development Example](/en/develop-plugin/dev-guides-and-walkthroughs/develop-a-slack-bot-plugin) - View a more complex plugin development case -- [Tool Plugin](/en/develop-plugin/features-and-specs/plugin-types/tool) - Explore advanced features of tool plugins +- [Remote Debugging Plugins](/en/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin): Learn more advanced debugging techniques. +- [Persistent Storage](/en/develop-plugin/features-and-specs/plugin-types/persistent-storage-kv): Use data storage in plugins. +- [Slack Bot Plugin Development Example](/en/develop-plugin/dev-guides-and-walkthroughs/develop-a-slack-bot-plugin): A more complex plugin development case. +- [Tool Plugin](/en/develop-plugin/features-and-specs/plugin-types/tool): Advanced features of tool plugins. {/* Contributing Section @@ -399,4 +401,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/trigger-plugin.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/trigger-plugin.mdx index cb7b26dc9..af8c9b147 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/trigger-plugin.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/trigger-plugin.mdx @@ -5,39 +5,37 @@ description: Build a Dify 1.10.0+ trigger plugin that turns third-party webhook ## What Is a Trigger Plugin? -Triggers were introduced in Dify v1.10.0 as a new type of start node. Unlike functional nodes such as Code, Tool, or Knowledge Retrieval, the purpose of a trigger is to **convert third-party events into an input format that Dify can recognize and process**. +Triggers were introduced in Dify v1.10.0 as a new type of start node. Unlike functional nodes such as Code, Tool, or Knowledge Retrieval, a trigger **converts third-party events into an input format that Dify can recognize and process**. ![Trigger Plugin Intro](/images/develop-plugin/dev-guide/trigger-plugin-intro.png) -For example, if you configure Dify as the `new email` event receiver in Gmail, every time you receive a new email, Gmail automatically sends an event to Dify that can be used to trigger a workflow. However: +For example, if you configure Dify as the `new email` event receiver in Gmail, Gmail automatically sends an event to Dify every time you receive a new email, and that event can trigger a workflow. However: - Gmail's original event format is not compatible with Dify's input format. - - There are thousands of platforms worldwide, each with its own unique event format. -Therefore, we need trigger plugins to define and parse these events from different platforms and in various formats, and to unify them into an input format that Dify can accept. +Trigger plugins close this gap: they define and parse events from different platforms and unify them into an input format that Dify can accept. ## Technical Overview -Dify triggers are implemented based on webhooks, a widely adopted mechanism across the web. Many mainstream SaaS platforms (like GitHub, Slack, and Linear) support webhooks with comprehensive developer documentation. +Dify triggers are built on webhooks, a widely adopted mechanism across the web. Mainstream SaaS platforms such as GitHub, Slack, and Linear support webhooks and document them thoroughly. -A webhook can be understood as an HTTP-based event dispatcher. **Once an event-receiving address is configured, these SaaS platforms automatically push event data to the target server whenever a subscribed event occurs.** +A webhook is an HTTP-based event dispatcher: once you configure an event-receiving address, the platform automatically pushes event data to that address whenever a subscribed event occurs. To handle webhook events from different platforms in a unified way, Dify defines two core concepts: **Subscription** and **Event**. -- **Subscription**: Webhook-based event dispatch requires **registering Dify's network address on a third-party platform's developer console as the target server. In Dify, this configuration process is called a *Subscription*.** - -- **Event**: A platform may send multiple types of events (such as *email received*, *email deleted*, or *email marked as read*), all of which are pushed to the registered address. A trigger plugin can handle multiple event types, with each event corresponding to a plugin trigger node in a Dify workflow. +- **Subscription**: The configuration that registers Dify's network address as the target server in a third-party platform's developer console. +- **Event**: A platform may send multiple types of events (such as *email received*, *email deleted*, or *email marked as read*), all pushed to the registered address. A trigger plugin can handle multiple event types, and each event corresponds to a Plugin Trigger node in a Dify workflow. ## Plugin Development -The development process for a trigger plugin is consistent with that of other plugin types (Tool, Data Source, Model, etc.). +Developing a trigger plugin follows the same process as other plugin types (Tool, Data Source, Model, and so on). -You can create a development template using the `dify plugin init` command. The generated file structure follows the standard plugin format specification. +Create a development template with the `dify plugin init` command. The generated file structure follows the standard plugin format specification. -``` +```text ├── _assets │   └── icon.svg ├── events @@ -55,18 +53,16 @@ You can create a development template using the `dify plugin init` command. The ``` - `manifest.yaml`: Describes the plugin's basic metadata. - - `provider` directory: Contains the provider's metadata, the code for creating subscriptions, and the code for classifying events after receiving webhook requests. - -- **`events` directory: Contains the code for event handling and filtering, which supports local event filtering at the node level. You can create subdirectories to group related events.** +- `events` directory: Contains the code for event handling and filtering, which supports local event filtering at the node level. You can create subdirectories to group related events. - For trigger plugins, the minimum required Dify version must be set to `1.10.0`, and the SDK version must be `>= 0.6.0`. + For trigger plugins, set the minimum required Dify version to `1.10.0` and the SDK version to `>= 0.6.0`. -Next, we'll use GitHub as an example to illustrate the development process of a trigger plugin. +The following sections use GitHub as an example to walk through the development process. -### Subscription Creation +### Create a Subscription Webhook configuration methods vary significantly across mainstream SaaS platforms: @@ -82,11 +78,11 @@ For platforms like Notion, creating a subscription requires the user to manually ![Paste URL to Create a New Subscription](/images/develop-plugin/dev-guide/trigger-plugin-manual-webhook-setup.png) -To implement subscription creation via manual URL pasting, you need to modify two files: `github.yaml` and `github.py`. +To support subscription creation via manual URL pasting, modify two files: `github.yaml` and `github.py`. - Since GitHub webhooks use an encryption mechanism, a secret key is required to decrypt and validate incoming requests. Therefore, you need to declare `webhook_secret` in `github.yaml`. + GitHub webhooks use an encryption mechanism, so a secret key is required to decrypt and validate incoming requests. Declare `webhook_secret` in `github.yaml`. ```yaml subscription_schema: @@ -105,15 +101,15 @@ To implement subscription creation via manual URL pasting, you need to modify tw - First, we need to implement the `dispatch_event` interface. All requests sent to the callback URL are processed by this interface, and the processed events will be displayed in the **Request Logs** section for debugging and verification. + First, implement the `dispatch_event` interface. All requests sent to the callback URL are processed by this interface, and the processed events appear in the **Request Logs** section for debugging and verification. ![Manual Setup](/images/develop-plugin/dev-guide/trigger-plugin-manual-webhook-setup-config.png) - In the code, you can retrieve the `webhook_secret` declared in `github.yaml` via `subscription.properties`. + In the code, you can retrieve the `webhook_secret` declared in `github.yaml` via `subscription.properties`. - The `dispatch_event` method needs to determine the event type based on the request content. In the example below, this event extraction is handled by the `_dispatch_trigger_event` method. + The `dispatch_event` method determines the event type from the request content. In the example below, the `_dispatch_trigger_event` method handles this extraction. For the complete code sample, see [Dify's GitHub trigger plugin](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/github_trigger). @@ -140,11 +136,11 @@ To implement subscription creation via manual URL pasting, you need to modify tw -### Event Handling +### Handle Events Once an event is extracted, the corresponding implementation must filter the original HTTP request and transform it into an input format that Dify workflows can accept. -Taking the Issue event as an example, you can define the event and its implementation through `events/issues/issues.yaml` and `events/issues/issues.py`, respectively. The event's output can be defined in the `output_schema` section of `issues.yaml`, which follows the same JSON Schema specification as tool plugins. +Taking the Issue event as an example, define the event in `events/issues/issues.yaml` and its implementation in `events/issues/issues.py`. Define the event's output in the `output_schema` section of `issues.yaml`, which follows the same JSON Schema specification as tool plugins. @@ -206,9 +202,9 @@ Taking the Issue event as an example, you can define the event and its implement -### Event Filtering +### Filter Events -To filter out certain events (for example, to focus only on Issue events with a specific label), you can add `parameters` to the event definition in `issues.yaml`. Then, in the `_on_event` method, you can throw an `EventIgnoreError` exception to filter out events that do not meet the configured criteria. +To filter out certain events (for example, to focus only on Issue events with a specific label), add `parameters` to the event definition in `issues.yaml`. Then, in the `_on_event` method, raise an `EventIgnoreError` exception for events that don't meet the configured criteria. @@ -255,9 +251,9 @@ To filter out certain events (for example, to focus only on Issue events with a -### Subscription Creation via OAuth or API Key +### Create Subscriptions via OAuth or API Key -To enable automatic subscription creation via OAuth or API key, you need to modify the `github.yaml` and `github.py` files. +To enable automatic subscription creation via OAuth or API key, modify the `github.yaml` and `github.py` files. @@ -305,14 +301,12 @@ To enable automatic subscription creation via OAuth or API key, you need to modi `subscription_constructor` is a concept abstracted by Dify to define how a subscription is constructed. It includes the following fields: - - `parameters` (optional): Defines the parameters required to create a subscription, such as the event types to subscribe to or the target GitHub repository - - - `credentials_schema` (optional): Declares the required credentials for creating a subscription with an API key or access token, such as `access_tokens` for GitHub. - - - `oauth_schema` (optional): Required for implementing subscription creation via OAuth. For details on how to define it, see [Add OAuth Support to Your Tool Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/tool-oauth). + - `parameters` (optional): Defines the parameters required to create a subscription, such as the event types to subscribe to or the target GitHub repository. + - `credentials_schema` (optional): Declares the credentials required to create a subscription with an API key or access token, such as `access_tokens` for GitHub. + - `oauth_schema` (optional): Required for subscription creation via OAuth. For details on how to define it, see [Add OAuth Support to Your Tool Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/tool-oauth). - In `github.py`, create a `Constructor` class to implement the automatic subscription logic. + In `github.py`, create a `Constructor` class to implement the automatic subscription logic. ```python class GithubSubscriptionConstructor(TriggerSubscriptionConstructor): @@ -391,7 +385,7 @@ To enable automatic subscription creation via OAuth or API key, you need to modi Once you have modified these two files, you'll see the **Create with API Key** option in the Dify interface. -Automatic subscription creation via OAuth can also be implemented in the same `Constructor` class: by adding an `oauth_schema` field under `subscription_constructor`, you can enable OAuth authentication. +The same `Constructor` class also supports automatic subscription creation via OAuth: add an `oauth_schema` field under `subscription_constructor` to enable OAuth authentication. ![OAuth & API Key Options](/images/develop-plugin/dev-guide/trigger-plugin-oauth-apikey.png) @@ -399,7 +393,7 @@ Automatic subscription creation via OAuth can also be implemented in the same `C ## Explore More -The interface definitions and implementation methods of core classes in trigger plugin development are as follows. +The interface definitions for the core classes in trigger plugin development are as follows. ### Trigger @@ -414,8 +408,8 @@ class Trigger(ABC): Implementation checklist: 1. Validate the webhook request: - - Check signature/HMAC using properties when you create the subscription from subscription.properties - - Verify request is from expected source + - Check the signature/HMAC using the properties stored in subscription.properties when the subscription was created + - Verify the request is from the expected source 2. Extract event information: - Parse event type from headers or body - Extract relevant payload data @@ -486,10 +480,10 @@ class TriggerSubscriptionConstructor(ABC, OAuthProviderProtocol): Implementation checklist: 1. Use the endpoint parameter provided by Dify 2. Register webhook with external service using their API - 3. Store all necessary information in Subscription.properties for future operations(e.g., dispatch_event) + 3. Store all necessary information in Subscription.properties for future operations (e.g., dispatch_event) 4. Return Subscription with: - expires_at: Set appropriate expiration time - - endpoint: The webhook endpoint URL allocated by Dify for receiving events, same with the endpoint parameter + - endpoint: The webhook endpoint URL allocated by Dify for receiving events, same as the endpoint parameter - parameters: The parameters of the subscription - properties: All configuration and external IDs @@ -552,7 +546,7 @@ class TriggerSubscriptionConstructor(ABC, OAuthProviderProtocol): 2. For lease-based subscriptions (e.g., Microsoft Graph): - Use the information in Subscription.properties to call service's lease renewal API if available - Handle renewal limits (some services limit renewal count) - - Update the Subscription.properties and Subscription.expires_at for next time renewal if needed + - Update Subscription.properties and Subscription.expires_at for the next renewal if needed Args: subscription: Current subscription with properties @@ -564,7 +558,7 @@ class TriggerSubscriptionConstructor(ABC, OAuthProviderProtocol): Returns: Subscription: Same subscription with extended expiration - or new properties and expires_at for next time renewal + or new properties and expires_at for the next renewal Raises: SubscriptionError: For operational failures (API errors, invalid credentials) @@ -654,7 +648,7 @@ class Event(ABC): To be implemented by subclasses. - Also, it's optional to implement, that's why it's not an abstract method. + Implementing it is optional, which is why it's not an abstract method. """ raise NotImplementedError( "This plugin should implement `_fetch_parameter_options` method to enable dynamic select parameter" @@ -670,4 +664,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/dev-guides-and-walkthroughs/trigger-plugin.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/advanced-development/bundle.mdx b/en/develop-plugin/features-and-specs/advanced-development/bundle.mdx index b2b7cc3aa..96b3247a1 100644 --- a/en/develop-plugin/features-and-specs/advanced-development/bundle.mdx +++ b/en/develop-plugin/features-and-specs/advanced-development/bundle.mdx @@ -7,37 +7,33 @@ dimensions: standard_title: Bundle language: en title: Bundle Plugin Package -description: This document introduces the concept and development method of Bundle - plugin packages. Bundle plugin packages can aggregate multiple plugins together, - supporting three types (Marketplace, GitHub, and Package). The document details - the entire process of creating a Bundle project, adding different types of dependencies, - and packaging the Bundle project. +description: Package multiple plugins into a Bundle with Marketplace, GitHub, and Package dependencies --- -A Bundle plugin package is a collection of multiple plugins. It allows packaging several plugins within a single plugin, enabling batch installation and providing more powerful services. +A Bundle plugin package is a collection of multiple plugins packaged together, so users can install them all in one step. -You can use the Dify CLI tool to package multiple plugins into a Bundle. Bundle plugin packages come in three types: +Use the Dify CLI tool to package multiple plugins into a Bundle. Bundle dependencies come in three types: -* `Marketplace` type. Stores the plugin's ID and version information. During import, the specific plugin package will be downloaded from the Dify Marketplace. -* `GitHub` type. Stores the GitHub repository address, release version number, and asset filename. During import, Dify will access the corresponding GitHub repository to download the plugin package. -* `Package` type. The plugin package is stored directly within the Bundle. It does not store reference sources, but this might lead to a larger Bundle package size. +- **`Marketplace`**: Stores the plugin's ID and version. During import, Dify downloads the plugin package from the Dify Marketplace. +- **`GitHub`**: Stores the GitHub repository address, release version number, and asset filename. During import, Dify downloads the plugin package from the corresponding GitHub repository. +- **`Package`**: Stores the plugin package directly within the Bundle. No reference source is stored, but this can make the Bundle file larger. ## Prerequisites -* Dify plugin scaffolding tool -* Python environment (version 3.12) +- Dify plugin scaffolding tool +- Python environment (version 3.12) -For detailed instructions on how to prepare the plugin development scaffolding tool, please refer to [Initialize Development Tools](/en/develop-plugin/getting-started/cli). +To set up the plugin development scaffolding tool, see [Initialize Development Tools](/en/develop-plugin/getting-started/cli). ## Create a Bundle Project -In the current directory, run the scaffolding command-line tool to create a new plugin package project. +In the current directory, run the scaffolding command-line tool to create a new plugin package project: ```bash ./dify-plugin-darwin-arm64 bundle init ``` -If you have renamed the binary file to `dify` and copied it to the `/usr/local/bin` path, you can run the following command to create a new plugin project: +If you have renamed the binary to `dify` and copied it to `/usr/local/bin`, run: ```bash dify bundle init @@ -47,49 +43,45 @@ dify bundle init Follow the prompts to configure the plugin name, author information, and plugin description. If you are collaborating as a team, you can also enter the organization name as the author. -> The name must be 1-128 characters long and can only contain letters, numbers, hyphens, and underscores. + +The name must be 1–128 characters long and can only contain letters, numbers, hyphens, and underscores. + ![Bundle Basic Information](https://assets-docs.dify.ai/2024/12/03a1c4cdc72213f09523eb1b40832279.png) -After filling in the information and pressing Enter, the Bundle plugin project directory will be automatically created. +Press Enter, and the Bundle plugin project directory is created automatically. - ![Filling in the Information and Pressing Enter, the Bundle Plugin Project](https://assets-docs.dify.ai/2024/12/356d1a8201fac3759bf01ee64e79a52b.png) + ![Bundle Plugin Project Directory](https://assets-docs.dify.ai/2024/12/356d1a8201fac3759bf01ee64e79a52b.png) ### 2. Add Dependencies -* **Marketplace** - -Execute the following command: +#### Marketplace ```bash dify-plugin bundle append marketplace . --marketplace_pattern=langgenius/openai:0.0.1 ``` -Where `marketplace_pattern` is the reference to the plugin in the marketplace, in the format `organization_name/plugin_name:version_number`. - -* **GitHub** +`marketplace_pattern` is the reference to the plugin in the Marketplace, in the format `organization_name/plugin_name:version_number`. -Execute the following command: +#### GitHub ```bash dify-plugin bundle append github . --repo_pattern=langgenius/openai:0.0.1/openai.difypkg ``` -Where `repo_pattern` is the reference to the plugin on GitHub, in the format `organization_name/repository_name:release/asset_name`. +`repo_pattern` is the reference to the plugin on GitHub, in the format `organization_name/repository_name:release/asset_name`. -* **Package** - -Execute the following command: +#### Package ```bash dify-plugin bundle append package . --package_path=./openai.difypkg ``` -Where `package_path` is the directory of the plugin package. +`package_path` is the path to the plugin package. ## Package the Bundle Project @@ -99,7 +91,7 @@ Run the following command to package the Bundle plugin: dify-plugin bundle package ./bundle ``` -After executing the command, a `bundle.difybndl` file will be automatically created in the current directory. This file is the final packaged result. +This creates a `bundle.difybndl` file in the current directory—the final packaged result. {/* Contributing Section @@ -110,4 +102,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/advanced-development/bundle.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/advanced-development/customizable-model.mdx b/en/develop-plugin/features-and-specs/advanced-development/customizable-model.mdx index 56e472100..18dd82e1b 100644 --- a/en/develop-plugin/features-and-specs/advanced-development/customizable-model.mdx +++ b/en/develop-plugin/features-and-specs/advanced-development/customizable-model.mdx @@ -7,34 +7,25 @@ dimensions: standard_title: Customizable Model language: en title: Integrate Custom Models -description: This document details how to integrate custom models into Dify, using - the Xinference model as an example. It covers the complete process, including creating - model provider files, writing code based on model type, implementing model invocation - logic, handling exceptions, debugging, and publishing. It specifically details the - implementation of core methods like LLM invocation, token calculation, credential - validation, and parameter generation. +description: Integrate a custom model into Dify, using Xinference as an example --- -A **custom model** refers to an LLM that you deploy or configure on your own. This document uses the [Xinference model](https://inference.readthedocs.io/en/latest/) as an example to demonstrate how to integrate a custom model into your **model plugin**. +A **custom model** is an LLM that you deploy or configure yourself. This guide uses [Xinference](https://inference.readthedocs.io/en/latest/) as an example to show how to integrate a custom model into your **model plugin**. -By default, a custom model automatically includes two parameters (its **model type** and **model name**) and does not require additional definitions in the provider YAML file. +By default, a custom model automatically includes two parameters, its **model type** and **model name**, so the provider YAML file needs no additional definitions. -You do not need to implement `validate_provider_credential` in your provider configuration file. During runtime, based on the user’s choice of model type or model name, Dify automatically calls the corresponding model layer’s `validate_credentials` method to verify credentials. +You do not need to implement `validate_provider_credential` in your provider configuration file. At runtime, Dify calls the corresponding model layer's `validate_credentials` method based on the model type and model name the user selects. ## Integrate a Custom Model Plugin -Below are the steps to integrate a custom model: +Integrating a custom model takes four steps: -1. **Create a Model Provider File**\ - Identify the model types your custom model will include. -2. **Create Code Files by Model Type**\ - Depending on the model’s type (e.g., `llm` or `text_embedding`), create separate code files. Ensure that each model type is organized into distinct logical layers for easier maintenance and future expansion. -3. **Develop the Model Invocation Logic**\ - Within each model-type module, create a Python file named for that model type (for example, `llm.py`). Define a class in the file that implements the specific model logic, conforming to the system’s model interface specifications. -4. **Debug the Plugin**\ - Write unit and integration tests for the new provider functionality, ensuring that all components work as intended. +1. **Create a model provider file**: Identify the model types your custom model will include. +2. **Create code files by model type**: Create separate code files for each model type (e.g., `llm` or `text_embedding`). Keeping each model type in its own logical layer simplifies maintenance and future expansion. +3. **Develop the model invocation logic**: Within each model-type module, create a Python file named for that model type (for example, `llm.py`). Define a class in the file that implements the model logic, conforming to the system's model interface specifications. +4. **Debug the plugin**: Write unit and integration tests for the new provider functionality, ensuring that all components work as intended. -### 1. **Create a Model Provider File** +### 1. Create the Model Provider File In your plugin’s `/provider` directory, create a `xinference.yaml` file. @@ -107,7 +98,7 @@ Every model in Xinference requires a `model_name`: en_US: Input model name ``` -Because Xinference must be locally deployed, users need to supply the server address (server\_url) and model UID. For instance: +Because Xinference is locally deployed, users must also supply the server address (`server_url`) and model UID: ```yaml - variable: server_url @@ -131,15 +122,15 @@ Because Xinference must be locally deployed, users need to supply the server add en_US: Enter the model uid ``` -Once you’ve defined these parameters, the YAML configuration for your custom model provider is complete. Next, create the functional code files for each model defined in this config. +This completes the YAML configuration for your custom model provider. Next, create the code files for each model defined in the configuration. ### 2. Develop the Model Code -Since Xinference supports llm, rerank, speech2text, and tts, you should create corresponding directories under /models, each containing its respective feature code. +Xinference supports `llm`, `rerank`, `speech2text`, and `tts`, so create a corresponding directory under `/models` for each type, each containing its feature code. -Below is an example for an llm-type model. You’d create a file named llm.py, then define a class (such as XinferenceAILargeLanguageModel) that extends \_\_base.large\_language\_model.LargeLanguageModel. This class should include: +Below is an example for an `llm` type model. Create a file named `llm.py`, then define a class such as `XinferenceAILargeLanguageModel` that extends `__base.large_language_model.LargeLanguageModel`. The class must implement the following methods. -* **LLM Invocation** +#### LLM Invocation The core method for invoking the LLM, supporting both streaming and synchronous responses: @@ -170,9 +161,9 @@ def _invoke( """ ``` -You’ll need two separate functions to handle streaming and synchronous responses. Python treats any function containing `yield` as a generator returning type `Generator`, so it’s best to split them: +Implement streaming and synchronous responses as separate functions. Python treats any function containing `yield` as a generator that returns `Generator`, so splitting them keeps the return types clean: -```yaml +```python def _invoke(self, stream: bool, **kwargs) -> Union[LLMResult, Generator]: if stream: return self._handle_stream_response(**kwargs) @@ -186,9 +177,9 @@ def _handle_sync_response(self, **kwargs) -> LLMResult: return LLMResult(**response) ``` -* **Pre-calculating Input Tokens** +#### Pre-calculate Input Tokens -If your model doesn’t provide a token-counting interface, simply return 0: +If your model doesn't provide a token-counting interface, return `0`: ```python def get_num_tokens( @@ -206,7 +197,7 @@ def get_num_tokens( Alternatively, you can call `self._get_num_tokens_by_gpt2(text: str)` from the `AIModel` base class, which uses a GPT-2 tokenizer. Remember this is an approximation and may not match your model exactly. -* **Validating Model Credentials** +#### Validate Model Credentials Similar to provider-level credential checks, but scoped to a single model: @@ -217,11 +208,11 @@ def validate_credentials(self, model: str, credentials: dict) -> None: """ ``` -* **Dynamic Model Parameters Schema** +#### Dynamic Model Parameters Schema -Unlike [predefined models](/en/develop-plugin/features-and-specs/plugin-types/model-schema), no YAML is defining which parameters a model supports. You must generate a parameter schema dynamically. +Unlike [predefined models](/en/develop-plugin/features-and-specs/plugin-types/model-schema), no YAML file defines which parameters a model supports, so you must generate the parameter schema dynamically. -For example, Xinference supports `max_tokens`, `temperature`, and `top_p`. Some other providers (e.g., `OpenLLM`) may support parameters like `top_k` only for certain models. This means you need to adapt your schema to each model’s capabilities: +For example, Xinference supports `max_tokens`, `temperature`, and `top_p`. Other providers (e.g., `OpenLLM`) may support parameters like `top_k` only for certain models, so the schema must adapt to each model's capabilities: ```python def get_customizable_model_schema(self, model: str, credentials: dict) -> AIModelEntity | None: @@ -286,19 +277,15 @@ def get_customizable_model_schema(self, model: str, credentials: dict) -> AIMode return entity ``` -* **Error Mapping** +#### Error Mapping -When an error occurs during model invocation, map it to the appropriate InvokeError type recognized by the runtime. This lets Dify handle different errors in a standardized manner: +When an error occurs during model invocation, map it to one of the runtime's `InvokeError` types so Dify can handle different errors consistently: -Runtime Errors: - -``` -• `InvokeConnectionError` -• `InvokeServerUnavailableError` -• `InvokeRateLimitError` -• `InvokeAuthorizationError` -• `InvokeBadRequestError` -``` +- `InvokeConnectionError` +- `InvokeServerUnavailableError` +- `InvokeRateLimitError` +- `InvokeAuthorizationError` +- `InvokeBadRequestError` ```python @property @@ -317,36 +304,34 @@ def _invoke_error_mapping(self) -> dict[type[InvokeError], list[type[Exception]] For more details on interface methods, see the [Model Documentation](https://docs.dify.ai/zh/develop-plugin/features-and-specs/plugin-types/model-schema). -To view the complete code files discussed in this guide, visit the [GitHub Repository](https://github.com/langgenius/dify-official-plugins/tree/main/models/xinference). +For the complete code files discussed in this guide, see the [GitHub repository](https://github.com/langgenius/dify-official-plugins/tree/main/models/xinference). ### 3. Debug the Plugin -After finishing development, test the plugin to ensure it runs correctly. For more details, refer to: +After development, test the plugin to make sure it runs correctly. For details, see: ### 4. Publish the Plugin -If you’d like to list this plugin on the Dify Marketplace, see: - -Publish to Dify Marketplace +To list the plugin on the Dify Marketplace, see Publish to Dify Marketplace. ## Explore More **Quick Start**: -* [Develop Extension Plugin](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) -* [Develop Tool Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) -* [Bundle Plugins: Package Multiple Plugins](/en/develop-plugin/features-and-specs/advanced-development/bundle) +- [Develop Extension Plugin](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) +- [Develop Tool Plugin](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) +- [Bundle Plugins: Package Multiple Plugins](/en/develop-plugin/features-and-specs/advanced-development/bundle) **Plugins Endpoint Docs**: -* [Manifest](/en/develop-plugin/features-and-specs/plugin-types/plugin-info-by-manifest) Structure -* [Endpoint](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) Definitions -* [Reverse-Invocation of the Dify Service](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation) -* [Tools](/en/develop-plugin/features-and-specs/plugin-types/tool) -* [Models](/en/develop-plugin/features-and-specs/plugin-types/model-schema) +- [Manifest](/en/develop-plugin/features-and-specs/plugin-types/plugin-info-by-manifest) Structure +- [Endpoint](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) Definitions +- [Reverse-Invocation of the Dify Service](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation) +- [Tools](/en/develop-plugin/features-and-specs/plugin-types/tool) +- [Models](/en/develop-plugin/features-and-specs/plugin-types/model-schema) {/* Contributing Section @@ -357,4 +342,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/advanced-development/customizable-model.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app.mdx b/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app.mdx index 2525c615d..0aa1eaf89 100644 --- a/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app.mdx +++ b/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app.mdx @@ -7,31 +7,28 @@ dimensions: standard_title: Reverse Invocation App language: en title: App -description: This document details how plugins can reverse invoke App services within - the Dify platform. It covers three types of interfaces Chat interface (for Chatbot/Agent/Chatflow - applications), Workflow interface, and Completion interface, providing entry points, - invocation specifications, and practical code examples for each. +description: Call the Chat, Workflow, and Completion interfaces of Dify Apps from your plugin --- -Reverse invoking an App means that a plugin can access data from an App within Dify. This module supports both streaming and non-streaming App calls. If you are unfamiliar with the basic concepts of reverse invocation, please first read [Reverse Invocation of Dify Services](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation). +A plugin can reverse invoke an App within Dify to access its data, with both streaming and non-streaming calls. If you are unfamiliar with the basics of reverse invocation, first read [Reverse Invocation of Dify Services](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation). **Interface Types**: -* For `Chatbot/Agent/Chatflow` type applications, they are all chat-based applications and thus share the same input and output parameter types. Therefore, they can be uniformly treated as the **Chat Interface.** -* For Workflow applications, they occupy a separate **Workflow Interface.** -* For Completion (text generation application) applications, they occupy a separate **Completion Interface**. +- **Chat Interface**: `Chatbot`, `Agent`, and `Chatflow` applications are all chat-based and share the same input and output parameter types, so they share this interface. +- **Workflow Interface**: Used by Workflow applications. +- **Completion Interface**: Used by Completion (text generation) applications. -Please note that plugins are only allowed to access Apps within the Workspace where the plugin resides. +Plugins can only access Apps within the Workspace where the plugin resides. ## Call the Chat Interface -### **Entry Point** +### Entry Point ```python self.session.app.chat ``` -### **Interface Specification** +### Interface Specification ```python def invoke( @@ -45,11 +42,11 @@ Please note that plugins are only allowed to access Apps within the Workspace wh pass ``` -When `response_mode` is `streaming`, this interface will directly return `Generator[dict]`. Otherwise, it returns `dict`. For specific interface fields, please refer to the return results of `ServiceApi`. +When `response_mode` is `streaming`, this interface returns `Generator[dict]`; otherwise it returns `dict`. For the specific interface fields, see the return results of `ServiceApi`. -### **Use Case** +### Use Case -We can call a Chat type App within an `Endpoint` and return the result directly. +This example calls a Chat type App within an `Endpoint` and returns the result directly: ```python import json @@ -81,13 +78,13 @@ class Duck(Endpoint): ## Call the Workflow Interface -### **Entry Point** +### Entry Point ```python self.session.app.workflow ``` -### **Interface Specification** +### Interface Specification ```python def invoke( @@ -102,13 +99,13 @@ class Duck(Endpoint): ## Call the Completion Interface -### **Entry Point** +### Entry Point ```python self.session.app.completion ``` -**Interface Specification** +### Interface Specification ```python def invoke( @@ -138,4 +135,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-model.mdx b/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-model.mdx index 2c42e92f2..d7d741095 100644 --- a/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-model.mdx +++ b/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-model.mdx @@ -7,28 +7,24 @@ dimensions: standard_title: Reverse Invocation Model language: en title: Reverse Invocation Model -description: This document details how plugins can reverse invoke model services within - the Dify platform. It covers specific methods for reverse invoking LLM, Summary, - TextEmbedding, Rerank, TTS, Speech2Text, and Moderation models. Each model invocation - includes its entry point, interface parameter descriptions, practical usage code - examples, and best practice recommendations for invoking models. +description: Invoke LLM, embedding, rerank, TTS, speech-to-text, and moderation models from your plugin --- -Reverse invoking a Model refers to the ability of a plugin to call Dify's internal LLM capabilities, including all model types and functions within the platform, such as TTS, Rerank, etc. If you are not familiar with the basic concepts of reverse invocation, please read [Reverse Invocation of Dify Services](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation) first. +A plugin can reverse invoke Dify's internal LLM capabilities, including all model types and functions within the platform, such as TTS and Rerank. If you are unfamiliar with the basics of reverse invocation, first read [Reverse Invocation of Dify Services](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation). -However, please note that invoking a model requires passing a `ModelConfig` type parameter. Its structure can be referenced in the [General Specifications Definition](/en/develop-plugin/features-and-specs/plugin-types/general-specifications), and this structure will have slight differences for different types of models. +Every model invocation takes a `ModelConfig` type parameter. Its structure is defined in the [General Specifications Definition](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) and varies slightly by model type. -For example, for `LLM` type models, it also needs to include `completion_params` and `mode` parameters. You can manually construct this structure or use `model-selector` type parameters or configurations. +For example, `LLM` type models also require `completion_params` and `mode` parameters. You can construct this structure manually or use `model-selector` type parameters or configurations. ## Invoke LLM -**Entry Point** +### Entry Point ```python self.session.model.llm ``` -**Endpoint** +### Interface ```python def invoke( @@ -42,11 +38,11 @@ For example, for `LLM` type models, it also needs to include `completion_params` pass ``` -Please note that if the model you are invoking does not have `tool_call` capability, the `tools` passed here will not take effect. +If the model you are invoking does not have `tool_call` capability, the `tools` passed here will not take effect. -**Use Case** +### Use Case -If you want to invoke OpenAI's `gpt-4o-mini` model within a `Tool`, please refer to the following example code: +This example invokes OpenAI's `gpt-4o-mini` model within a `Tool`: ```python from collections.abc import Generator @@ -83,11 +79,11 @@ class LLMTool(Tool): yield self.create_text_message(text=chunk.delta.message.content) ``` -Note that the `query` parameter from `tool_parameters` is passed in the code. +Note that the code passes the `query` parameter from `tool_parameters`. -## **Best Practice** +### Best Practice -It is not recommended to manually construct `LLMModelConfig`. Instead, allow users to select the model they want to use on the UI. In this case, you can modify the tool's parameter list by adding a `model` parameter as follows: +Avoid constructing `LLMModelConfig` manually. Instead, let users select the model they want in the UI by adding a `model` parameter to the tool's parameter list: ```yaml identity: @@ -136,7 +132,7 @@ extra: source: tools/llm.py ``` -Please note that in this example, the `scope` of `model` is specified as `llm`. This means the user can only select `llm` type parameters. Thus, the code from the previous use case can be modified as follows: +Because the `scope` of the `model` parameter is `llm`, users can only select `llm` type models. The previous use case then becomes: ```python from collections.abc import Generator @@ -170,18 +166,15 @@ class LLMTool(Tool): ## Invoke Summary -You can request this endpoint to summarize a piece of text. It will use the system model within your current workspace to summarize the text. +This interface summarizes a piece of text using the system model within your current workspace. -**Entry Point** +### Entry Point ```python self.session.model.summary ``` -**Endpoint** - -* `text` is the text to be summarized. -* `instruction` is the additional instruction you want to add, allowing you to summarize the text stylistically. +### Interface ```python def invoke( @@ -189,15 +182,18 @@ You can request this endpoint to summarize a piece of text. It will use the syst ) -> str: ``` +- **`text`**: The text to summarize. +- **`instruction`**: Additional instructions, letting you control the style of the summary. + ## Invoke TextEmbedding -**Entry Point** +### Entry Point ```python self.session.model.text_embedding ``` -**Endpoint** +### Interface ```python def invoke( @@ -211,13 +207,13 @@ You can request this endpoint to summarize a piece of text. It will use the syst ## Invoke Rerank -**Entry Point** +### Entry Point ```python self.session.model.rerank ``` -**Endpoint** +### Interface ```python def invoke( @@ -228,13 +224,13 @@ You can request this endpoint to summarize a piece of text. It will use the syst ## Invoke TTS -**Entry Point** +### Entry Point ```python self.session.model.tts ``` -**Endpoint** +### Interface ```python def invoke( @@ -243,17 +239,17 @@ You can request this endpoint to summarize a piece of text. It will use the syst pass ``` -Please note that the `bytes` stream returned by the `tts` endpoint is an `mp3` audio byte stream. Each iteration returns a complete audio segment. If you want to perform more in-depth processing tasks, please choose an appropriate library. +The `bytes` stream returned by the `tts` interface is an `mp3` audio byte stream, and each iteration returns a complete audio segment. For more in-depth processing, choose an appropriate audio library. ## Invoke Speech2Text -**Entry Point** +### Entry Point ```python self.session.model.speech2text ``` -**Endpoint** +### Interface ```python def invoke( @@ -262,24 +258,24 @@ Please note that the `bytes` stream returned by the `tts` endpoint is an `mp3` a pass ``` -Where `file` is an audio file encoded in `mp3` format. +Here, `file` is an audio file encoded in `mp3` format. ## Invoke Moderation -**Entry Point** +### Entry Point ```python self.session.model.moderation ``` -**Endpoint** +### Interface ```python def invoke(self, model_config: ModerationModelConfig, text: str) -> bool: pass ``` -If this endpoint returns `true`, it indicates that the `text` contains sensitive content. +A return value of `true` indicates that the `text` contains sensitive content. ## Related Resources @@ -298,4 +294,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-model.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-node.mdx b/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-node.mdx index 003b91b58..a1d4288ab 100644 --- a/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-node.mdx +++ b/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-node.mdx @@ -7,26 +7,22 @@ dimensions: standard_title: Reverse Invocation Node language: en title: Node -description: This document describes how plugins can reverse invoke the functionality - of Chatflow/Workflow application nodes within the Dify platform. It primarily covers - the invocation methods for two specific nodes, ParameterExtractor and QuestionClassifier. - The document details the entry points, interface parameters, and example code for - invoking these two nodes. +description: Invoke the Parameter Extractor and Question Classifier nodes from your plugin --- -Reverse invoking a Node means that a plugin can access the capabilities of certain nodes within a Dify Chatflow/Workflow application. +A plugin can reverse invoke the capabilities of certain nodes within a Dify Chatflow/Workflow application. -The `ParameterExtractor` and `QuestionClassifier` nodes in `Workflow` encapsulate complex Prompt and code logic, enabling tasks that are difficult to solve with hardcoding through LLMs. Plugins can call these two nodes. +Plugins can call the `ParameterExtractor` and `QuestionClassifier` nodes. Both encapsulate complex prompt and code logic, using LLMs to handle tasks that are difficult to solve with hardcoded rules. ## Call the Parameter Extractor Node -### **Entry Point** +### Entry Point ```python self.session.workflow_node.parameter_extractor ``` -### **Interface** +### Interface ```python def invoke( @@ -39,11 +35,16 @@ The `ParameterExtractor` and `QuestionClassifier` nodes in `Workflow` encapsulat pass ``` -Here, `parameters` is a list of parameters to be extracted, `model` conforms to the `LLMModelConfig` specification, `query` is the source text for parameter extraction, and `instruction` provides any additional instructions that might be needed for the LLM. For the structure of `NodeResponse`, please refer to this [document](/en/develop-plugin/features-and-specs/plugin-types/general-specifications#noderesponse). +- **`parameters`**: The list of parameters to extract. +- **`model`**: Conforms to the `LLMModelConfig` specification. +- **`query`**: The source text for parameter extraction. +- **`instruction`**: Any additional instructions the LLM might need. -### **Use Case** +For the structure of `NodeResponse`, see the [General Specifications Definition](/en/develop-plugin/features-and-specs/plugin-types/general-specifications#noderesponse). -To extract a person's name from a conversation, you can refer to the following code: +### Use Case + +This example extracts a person's name from a conversation: ```python from collections.abc import Generator @@ -82,13 +83,13 @@ class ParameterExtractorTool(Tool): ## Call the Question Classifier Node -### **Entry Point** +### Entry Point ```python self.session.workflow_node.question_classifier ``` -### **Interface** +### Interface ```python def invoke( @@ -101,7 +102,7 @@ class ParameterExtractorTool(Tool): pass ``` -`ClassConfig` is also exported from `dify_plugin.entities.workflow_node`. The interface parameters are consistent with `ParameterExtractor`. The final result is stored in `response.outputs["class_name"]`. +`ClassConfig` is also exported from `dify_plugin.entities.workflow_node`. The interface parameters match those of `ParameterExtractor`, and the final result is stored in `response.outputs["class_name"]`. {/* Contributing Section @@ -112,4 +113,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-node.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-tool.mdx b/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-tool.mdx index d0f292e0e..e65c789a9 100644 --- a/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-tool.mdx +++ b/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-tool.mdx @@ -7,35 +7,30 @@ dimensions: standard_title: Reverse Invocation Tool language: en title: Tool -description: This document details how plugins can reverse invoke Tool services within - the Dify platform. It covers three types of tool invocation methods calling installed - tools (Built-in Tool), calling Workflow as Tool, and calling custom tools (Custom - Tool). Each method includes corresponding entry points and interface parameter descriptions. +description: Call installed tools, Workflow as Tool, and custom tools from your plugin --- -Reverse invoking a Tool means that a plugin can call other tool-type plugins within the Dify platform. If you are unfamiliar with the basic concepts of reverse invocation, please first read [Reverse Invocation of Dify Services](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation). +A plugin can reverse invoke other tool-type plugins within the Dify platform. If you are unfamiliar with the basics of reverse invocation, first read [Reverse Invocation of Dify Services](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation). Consider the following scenarios: -* A tool-type plugin has implemented a function, but the result is not as expected, requiring post-processing of the data. -* A task requires a web scraper, and you want the flexibility to choose the scraping service. -* You need to aggregate results from multiple tools, but it's difficult to handle using a Workflow application. +- A tool-type plugin implements a function, but the result is not as expected and the data needs post-processing. +- A task requires a web scraper, and you want the flexibility to choose the scraping service. +- You need to aggregate results from multiple tools, which is difficult to handle in a Workflow application. -In these cases, you need to call other existing tools within your plugin. These tools might be from the marketplace, a self-built Workflow as a Tool, or a custom tool. - -These requirements can be met by calling the `self.session.tool` field of the plugin. +In these cases, your plugin needs to call other existing tools: tools from the marketplace, a self-built Workflow as a Tool, or a custom tool. All of them are available through the plugin's `self.session.tool` field. ## Call Installed Tools -Allows the plugin to call various tools installed in the current Workspace, including other tool-type plugins. +Call any tool installed in the current Workspace, including other tool-type plugins. -**Entry Point** +### Entry Point ```python self.session.tool ``` -**Interface** +### Interface ```python def invoke_builtin_tool( @@ -44,19 +39,21 @@ Allows the plugin to call various tools installed in the current Workspace, incl pass ``` -Here, `provider` is the plugin ID plus the tool provider name, formatted like `langgenius/google/google`. `tool_name` is the specific tool name, and `parameters` are the arguments passed to the tool. +- **`provider`**: The plugin ID plus the tool provider name, formatted like `langgenius/google/google`. +- **`tool_name`**: The specific tool name. +- **`parameters`**: The arguments passed to the tool. ## Call Workflow as Tool -For more information on Workflow as Tool, please refer to the [Tool Plugin documentation](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin). +See the [Tool Plugin documentation](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) for more information on Workflow as Tool. -**Entry Point** +### Entry Point ```python self.session.tool ``` -**Interface** +### Interface ```python def invoke_workflow_tool( @@ -65,17 +62,18 @@ For more information on Workflow as Tool, please refer to the [Tool Plugin docum pass ``` -In this case, `provider` is the ID of this tool, and `tool_name` is specified during the creation of the tool. +- **`provider`**: The ID of this tool. +- **`tool_name`**: The name specified when the tool was created. ## Call Custom Tool -**Entry Point** +### Entry Point ```python self.session.tool ``` -**Interface** +### Interface ```python def invoke_api_tool( @@ -84,7 +82,8 @@ In this case, `provider` is the ID of this tool, and `tool_name` is specified du pass ``` -Here, `provider` is the ID of this tool, and `tool_name` is the `operation_id` from the OpenAPI specification. If it doesn't exist, it's the `tool_name` automatically generated by Dify, which can be found on the tool management page. +- **`provider`**: The ID of this tool. +- **`tool_name`**: The `operation_id` from the OpenAPI specification. If no `operation_id` exists, this is the `tool_name` automatically generated by Dify, which you can find on the tool management page. ## Related Resources @@ -103,4 +102,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-tool.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation.mdx b/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation.mdx index 1bed8b3db..b5d96ed7d 100644 --- a/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation.mdx +++ b/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation.mdx @@ -7,29 +7,17 @@ dimensions: standard_title: Reverse Invocation language: en title: Reverse Invocation of Dify Services -description: This document briefly introduces the reverse invocation capability of - Dify plugins, meaning plugins can call specified services within the main Dify platform. - It lists four types of modules that can be invoked, App (access App data), Model - (call model capabilities within the platform), Tool (call other tool plugins within - the platform), and Node (call nodes within a Chatflow/Workflow application). +description: Call App, Model, Tool, and Node services in the Dify platform from your plugin --- -Plugins can freely call some services within the main Dify platform to enhance their capabilities. +Through reverse invocation, plugins can call services within the main Dify platform to extend their capabilities. ## Callable Dify Modules -* [App](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app) - - Plugins can access data from Apps within the Dify platform. -* [Model](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-model) - - Plugins can reverse invoke LLM capabilities within the Dify platform, including all model types and functions within the platform, such as TTS, Rerank, etc. -* [Tool](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-tool) - - Plugins can call other tool-type plugins within the Dify platform. -* [Node](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-node) - - Plugins can call nodes within a specific Chatflow/Workflow application in the Dify platform. +- **[App](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app)**: Access data from Apps within the Dify platform. +- **[Model](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-model)**: Invoke LLM capabilities within the Dify platform, including all model types and functions such as TTS and Rerank. +- **[Tool](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-tool)**: Call other tool-type plugins within the Dify platform. +- **[Node](/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation-node)**: Call nodes within a specific Chatflow/Workflow application in the Dify platform. ## Related Resources @@ -47,4 +35,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/advanced-development/reverse-invocation.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/plugin-types/general-specifications.mdx b/en/develop-plugin/features-and-specs/plugin-types/general-specifications.mdx index 5d2c2aab3..be3aa9232 100644 --- a/en/develop-plugin/features-and-specs/plugin-types/general-specifications.mdx +++ b/en/develop-plugin/features-and-specs/plugin-types/general-specifications.mdx @@ -7,264 +7,282 @@ dimensions: standard_title: General Specs language: en title: General Specs -description: This article will briefly introduce common structures in plugin development. During development, it is strongly recommended to read this alongside [Basic Concepts of Plugin Development](/en/develop-plugin/getting-started/getting-started-dify-plugin) and the [Developer Cheatsheet](/en/develop-plugin/getting-started/cli) for a better understanding of the overall architecture. +description: Common data structures shared across plugin types, including I18nObject, ProviderConfig, ModelConfig, NodeResponse, and ToolSelector --- +This page covers structures common to all plugin types. Read it alongside [Basic Concepts of Plugin Development](/en/develop-plugin/getting-started/getting-started-dify-plugin) and the [Developer Cheatsheet](/en/develop-plugin/getting-started/cli) for a picture of the overall architecture. + ## Path Specifications -When filling in file paths in Manifest or any yaml files, follow these two specifications depending on the type of file: +File paths in the manifest or any YAML file follow two rules, depending on the file type: -* If the target file is a multimedia file such as an image or video, for example when filling in the plugin's `icon`, you should place these files in the `_assets` folder under the plugin's root directory. -* If the target file is a regular text file, such as `.py` or `.yaml` code files, you should fill in the absolute path of the file within the plugin project. +- Multimedia files such as images and videos (for example, the plugin's `icon`) go in the `_assets` folder under the plugin's root directory. +- Regular text files, such as `.py` or `.yaml` code files, are referenced by their absolute path within the plugin project. ## Common Structures -When defining plugins, there are some data structures that can be shared between tools, models, and Endpoints. These shared structures are defined here. +Some data structures are shared between tools, models, and Endpoints. They are defined here. ### I18nObject -`I18nObject` is an internationalization structure that conforms to the [IETF BCP 47](https://tools.ietf.org/html/bcp47) standard. Currently, four languages are supported: +`I18nObject` is an internationalization structure that conforms to the [IETF BCP 47](https://tools.ietf.org/html/bcp47) standard. Four languages are supported: - English (United States) + English (United States). - Simplified Chinese + Simplified Chinese. - Japanese + Japanese. - Portuguese (Brazil) + Portuguese (Brazil). ### ProviderConfig -`ProviderConfig` is a common provider form structure, applicable to both `Tool` and `Endpoint` +`ProviderConfig` is a common provider form structure used by both `Tool` and `Endpoint`. - Form item name + Form item name. - Display labels following [IETF BCP 47](https://tools.ietf.org/html/bcp47) standard + Display labels, following the [IETF BCP 47](https://tools.ietf.org/html/bcp47) standard. - Form field type - determines how the field will be rendered in the UI + Form field type. Determines how the field is rendered in the UI. - Optional range specification, varies based on the value of `type` + Optional range specification. Varies based on the value of `type`. - Whether the field cannot be empty + Whether the field must not be empty. - Default value, only supports basic types: `float`, `int`, `string` + Default value. Only supports basic types: `float`, `int`, `string`. - Available options, only used when type is `select` + Available options. Only used when `type` is `select`. - Help document link label, following [IETF BCP 47](https://tools.ietf.org/html/bcp47) + Help document link label, following [IETF BCP 47](https://tools.ietf.org/html/bcp47). - Help document link + Help document link. - Placeholder text in multiple languages, following [IETF BCP 47](https://tools.ietf.org/html/bcp47) + Placeholder text in multiple languages, following [IETF BCP 47](https://tools.ietf.org/html/bcp47). -### ProviderConfigOption(object) +### ProviderConfigOption (object) - The value of the option + Option value. - Display label for the option, following [IETF BCP 47](https://tools.ietf.org/html/bcp47) + Option display label, following [IETF BCP 47](https://tools.ietf.org/html/bcp47). -### ProviderConfigType(string) +### ProviderConfigType (string) - Configuration information that will be encrypted + Configuration information that will be encrypted. - Plain text input field + Plain text input field. - Dropdown selection field + Dropdown selection field. - Switch/toggle control + Switch/toggle control. - Model configuration selector, including provider name, model name, model parameters, etc. + Model configuration selector, including provider name, model name, and model parameters. - Application ID selector + Application ID selector. - Tool configuration selector, including tool provider, name, parameters, etc. + Tool configuration selector, including tool provider, name, and parameters. - Dataset selector (TBD) + Dataset selector (TBD). -### ProviderConfigScope(string) +### ProviderConfigScope (string) When `type` is `model-selector`: + - All model types + All model types. + - Large Language Models only + Large language models only. + - Text embedding models only + Text embedding models only. + - Reranking models only + Reranking models only. + - Text-to-speech models only + Text-to-speech models only. + - Speech-to-text models only + Speech-to-text models only. + - Content moderation models only + Content moderation models only. + - Vision models only + Vision models only. When `type` is `app-selector`: + - All application types + All application types. + - Chat applications only + Chat applications only. + - Workflow applications only + Workflow applications only. + - Completion applications only + Completion applications only. When `type` is `tool-selector`: + - All tool types + All tool types. + - Plugin tools only + Plugin tools only. + - API tools only + API tools only. + - Workflow tools only + Workflow tools only. ### ModelConfig - Model provider name containing plugin_id, in the form of `langgenius/openai/openai` + Model provider name containing the `plugin_id`, in the form `langgenius/openai/openai`. - Specific model name + Specific model name. - Enumeration of model types, refer to the [Model Design Rules](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules#modeltype) document + Model type enumeration; see [Model Design Rules](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules#modeltype). ### NodeResponse - Variables that are finally input to the node + Variables ultimately passed into the node. - Output results of the node + Output results of the node. - Data generated during node execution + Data generated during node execution. ### ToolSelector - Tool provider name + Tool provider name. - Tool name + Tool name. - Tool description + Tool description. - Tool configuration information + Tool configuration information. - Parameters that need LLM reasoning + Parameters that require LLM reasoning. - Parameter name + Parameter name. - Parameter type + Parameter type. - Whether the parameter is required + Whether the parameter is required. - Parameter description + Parameter description. - Default value + Default value. - Available options for the parameter + Available options for the parameter. ## Related Resources -- [Basic Concepts of Plugin Development](/en/develop-plugin/getting-started/getting-started-dify-plugin) - Comprehensive understanding of Dify plugin development -- [Developer Cheatsheet](/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet) - Quick reference for common commands and concepts in plugin development -- [Tool Plugin Development Details](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin) - Understanding how to define plugin information and the tool plugin development process -- [Model Design Rules](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules) - Understanding the standards for model configuration +- [Basic Concepts of Plugin Development](/en/develop-plugin/getting-started/getting-started-dify-plugin)—an overview of Dify plugin development +- [Developer Cheatsheet](/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet)—quick reference for common commands and concepts +- [Tool Plugin Development Details](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin)—defining plugin information and the tool plugin development process +- [Model Design Rules](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules)—standards for model configuration {/* Contributing Section @@ -275,4 +293,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/plugin-types/general-specifications.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules.mdx b/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules.mdx index 43a4e56e0..c981851d1 100644 --- a/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules.mdx +++ b/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules.mdx @@ -7,17 +7,14 @@ dimensions: standard_title: Model Specs language: en title: Model Specs -description: This document defines in detail the core concepts and structures for - Dify model plugin development, including model providers (Provider), AI model entities - (AIModelEntity), model types (ModelType), configuration methods (ConfigurateMethod), - model features (ModelFeature), parameter rules (ParameterRule), price configuration - (PriceConfig), and detailed data structure specifications for various credential - modes. +description: Reference for the entities that define a Dify model plugin, including Provider, AIModelEntity, model types, configuration methods, parameter rules, and credential schemas --- -A model plugin describes itself with two entities: a **Provider** (this page's [Provider](#provider) section) that handles authentication and lists supported models, and one **AIModelEntity** ([AIModelEntity](#aimodelentity)) per model declaring its type, features, and parameters. +A model plugin describes itself with two entities: a [Provider](#provider) that handles authentication and lists supported models, and one [AIModelEntity](#aimodelentity) per model declaring its type, features, and parameters. -> All entities below are `Pydantic BaseModel` subclasses from the `dify_plugin.entities.model` module. + +All entities below are `Pydantic BaseModel` subclasses from the `dify_plugin.entities.model` module. + ## Quick Decision @@ -39,14 +36,14 @@ A model plugin describes itself with two entities: a **Provider** (this page's [ ## Provider - Provider identifier, e.g.: `openai` + Provider identifier, for example `openai`. - Provider display name, i18n, can set both `en_US` (English) and `zh_Hans` (Chinese) languages + Provider display name (i18n). Supports `en_US` (English) and `zh_Hans` (Chinese). - Chinese label, if not set, will default to using `en_US` + Chinese label. Falls back to `en_US` if not set. @@ -55,531 +52,529 @@ A model plugin describes itself with two entities: a **Provider** (this page's [ - Provider description, i18n + Provider description (i18n). - Chinese description + Chinese description. - English description + English description. - Provider small icon, stored in the `_assets` directory under the corresponding provider implementation directory + Small provider icon, stored in the `_assets` directory under the provider implementation directory. - Chinese icon + Chinese icon. - English icon + English icon. - Provider large icon, stored in the `_assets` directory under the corresponding provider implementation directory + Large provider icon, stored in the `_assets` directory under the provider implementation directory. - Chinese icon + Chinese icon. - English icon + English icon. - Background color value, e.g.: #FFFFFF, if empty, will display the frontend default color value + Background color value, for example `#FFFFFF`. If empty, the frontend default color is used. - Help information + Help information. - Help title, i18n + Help title (i18n). - Chinese title + Chinese title. - English title + English title. - Help link, i18n + Help link (i18n). - Chinese link + Chinese link. - English link + English link. - Supported model types + Supported model types. - Configuration methods + Configuration methods. - Provider credential specifications + Provider credential specification. - Model credential specifications + Model credential specification. ## AIModelEntity - Model identifier, e.g.: `gpt-3.5-turbo` + Model identifier, for example `gpt-3.5-turbo`. - Model display name, i18n, can set both `en_US` (English) and `zh_Hans` (Chinese) languages + Model display name (i18n). Supports `en_US` (English) and `zh_Hans` (Chinese). - Chinese label + Chinese label. - English label + English label. - Model type + Model type. - List of supported features + Supported features. - Model properties + Model properties. - Mode (available for model type `llm`) + Mode (model type `llm`). - Context size (available for model types `llm` and `text-embedding`) + Context size (model types `llm` and `text-embedding`). - Maximum number of chunks (available for model types `text-embedding` and `moderation`) + Maximum number of chunks (model types `text-embedding` and `moderation`). - Maximum file upload limit, unit: MB. (available for model type `speech2text`) + Maximum file upload size in MB (model type `speech2text`). - Supported file extension formats, e.g.: mp3,mp4 (available for model type `speech2text`) + Supported file extensions, for example `mp3,mp4` (model type `speech2text`). - Default voice, required: alloy,echo,fable,onyx,nova,shimmer (available for model type `tts`) + Default voice; one of `alloy`, `echo`, `fable`, `onyx`, `nova`, `shimmer` (model type `tts`). - List of available voices (available for model type `tts`) + Available voices (model type `tts`). - Voice model + Voice model. - Voice model display name + Voice model display name. - Supported languages for voice model + Languages the voice model supports. - Word limit for single conversion, defaults to paragraph segmentation (available for model type `tts`) + Word limit per conversion; defaults to splitting by paragraph (model type `tts`). - Supported audio file extension formats, e.g.: mp3,wav (available for model type `tts`) + Supported audio file extensions, for example `mp3,wav` (model type `tts`). - Number of concurrent tasks supported for text-to-audio conversion (available for model type `tts`) + Number of concurrent text-to-audio conversion tasks (model type `tts`). - Maximum characters per chunk (available for model type `moderation`) + Maximum characters per chunk (model type `moderation`). - Model call parameter rules + Rules for model call parameters. - Pricing information + Pricing information. - Whether deprecated. If deprecated, the model list will no longer display it, but those already configured can continue to be used. Default is False. + Whether the model is deprecated. Deprecated models no longer appear in the model list, but existing configurations keep working. Defaults to `False`. ## ModelType - Text generation model + Text generation model. - Text embedding model + Text embedding model. - Rerank model + Rerank model. - Speech to text + Speech to text. - Text to speech + Text to speech. - Content moderation + Content moderation. ## ConfigurateMethod - Predefined model - Indicates that the user only needs to configure unified provider credentials to use predefined models under the provider. + Predefined model. The user configures unified provider credentials once to use all predefined models under the provider. - Customizable model - The user needs to add credential configuration for each model. + Customizable model. The user adds a credential configuration for each model. - Fetch from remote - Similar to the `predefined-model` configuration method, only unified provider credentials are needed, but the models are fetched from the provider using the credential information. + Fetch from remote. Like `predefined-model`, only unified provider credentials are needed, but the model list is fetched from the provider using those credentials. ## ModelFeature - Agent reasoning, generally models over 70B have chain-of-thought capabilities. + Agent reasoning. Generally, models over 70B have chain-of-thought capabilities. - Vision, i.e.: image understanding. + Vision (image understanding). - Tool calling + Tool calling. - Multiple tool calling + Multiple tool calling. - Streaming tool calling + Streaming tool calling. ## FetchFrom - Predefined model + Predefined model. - Remote model + Remote model. ## LLMMode - Text completion + Text completion. - Chat + Chat. ## ParameterRule - Actual parameter name for model call + Actual parameter name used in the model call. - Use template + Template to use. -> For details on using templates, you can refer to the examples in [Creating a New Model Provider](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider). - -There are 5 pre-configured variable content templates by default: +Five parameter templates are predefined: -* `temperature` -* `top_p` -* `frequency_penalty` -* `presence_penalty` -* `max_tokens` +- `temperature` +- `top_p` +- `frequency_penalty` +- `presence_penalty` +- `max_tokens` -You can directly set the template variable name in `use_template`, which will use the default configuration from entities.defaults.PARAMETER\_RULE\_TEMPLATE without needing to set any parameters other than `name` and `use_template`. If additional configuration parameters are set, they will override the default configuration. You can refer to `openai/llm/gpt-3.5-turbo.yaml` for examples. +Set one of these names in `use_template` to inherit the default configuration from `entities.defaults.PARAMETER_RULE_TEMPLATE`; you then only need `name` and `use_template`. Any additional parameters you set override the template defaults. See `openai/llm/gpt-3.5-turbo.yaml` and the examples in [Creating a New Model Provider](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider). - Label, i18n + Label (i18n). - Chinese label + Chinese label. - English label + English label. - Parameter type + Parameter type. - Integer + Integer. - Floating point + Floating point. - String + String. - Boolean + Boolean. - Help information + Help information (i18n). - Chinese help information + Chinese help text. - English help information + English help text. - Whether required, default is False + Whether the parameter is required. Defaults to `False`. - Default value + Default value. - Minimum value, only applicable to numeric types + Minimum value. Numeric types only. - Maximum value, only applicable to numeric types + Maximum value. Numeric types only. - Precision, decimal places to retain, only applicable to numeric types + Number of decimal places to keep. Numeric types only. - Dropdown option values, only applicable when `type` is `string`, if not set or is null, then option values are not restricted + Dropdown option values. Only applies when `type` is `string`. If not set or null, values are unrestricted. ## PriceConfig - Input unit price, i.e., Prompt unit price + Input (prompt) unit price. - Output unit price, i.e., returned content unit price + Output (returned content) unit price. - Price unit, e.g., if priced per 1M tokens, then the unit token number corresponding to the unit price is `0.000001` + Price unit. For example, if pricing is per 1M tokens, the unit token count corresponding to the unit price is `0.000001`. - Currency unit + Currency unit. ## ProviderCredentialSchema - Credential form specifications + Credential form specification. ## ModelCredentialSchema - Model identifier, default variable name is `model` + Model identifier. The default variable name is `model`. - Model form item display name + Display name of the model form item. - English + English. - Chinese + Chinese. - Model prompt content + Placeholder text for the model form item. - English + English. - Chinese + Chinese. - Credential form specifications + Credential form specification. ## CredentialFormSchema - Form item variable name + Form item variable name. - Form item label + Form item label. - English + English. - Chinese + Chinese. - Form item type + Form item type. - Whether required + Whether the form item is required. - Default value + Default value. - Form item attribute specific to `select` or `radio`, defines dropdown content + Dropdown content. Specific to the `select` and `radio` types. - Form item attribute specific to `text-input`, form item placeholder + Form item placeholder. Specific to the `text-input` type. - English + English. - Chinese + Chinese. - Form item attribute specific to `text-input`, defines maximum input length, 0 means no limit + Maximum input length. Specific to the `text-input` type. `0` means no limit. - Display when other form item values meet conditions, empty means always display + Show this item only when other form item values meet the given conditions. Empty means always show. ### FormType - Text input component + Text input component. - Password input component + Password input component. - Single-select dropdown + Single-select dropdown. - Radio component + Radio component. - Switch component, only supports `true` and `false` + Switch component. Only supports `true` and `false`. ### FormOption - Label + Label. - English + English. - Chinese + Chinese. - Dropdown option value + Dropdown option value. - Display when other form item values meet conditions, empty means always display + Show this option only when other form item values meet the given conditions. Empty means always show. ### FormShowOnObject - Other form item variable name + Variable name of the other form item. - Other form item variable value + Variable value of the other form item. ## Related Resources -- [Model Architecture Details](/en/develop-plugin/features-and-specs/plugin-types/model-schema) - Deep dive into the architecture specifications of model plugins -- [Quickly Integrate a New Model](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) - Learn how to apply these rules to add new models -- [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) - Understand the configuration of plugin manifest files -- [Create a New Model Provider](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) - Develop brand new model provider plugins +- [Model Architecture Details](/en/develop-plugin/features-and-specs/plugin-types/model-schema)—architecture specifications for model plugins +- [Quickly Integrate a New Model](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider)—apply these rules to add new models +- [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications)—plugin manifest configuration +- [Create a New Model Provider](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider)—develop a new model provider plugin {/* Contributing Section @@ -590,4 +585,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/plugin-types/model-schema.mdx b/en/develop-plugin/features-and-specs/plugin-types/model-schema.mdx index c3dc1ea28..21234776b 100644 --- a/en/develop-plugin/features-and-specs/plugin-types/model-schema.mdx +++ b/en/develop-plugin/features-and-specs/plugin-types/model-schema.mdx @@ -7,12 +7,12 @@ dimensions: standard_title: Model Schema language: en title: Model API Interface -description: Comprehensive guide to the Dify model plugin API including implementation requirements for LLM, TextEmbedding, Rerank, Speech2text, and Text2speech models, with detailed specifications for all related data structures. +description: Interfaces and data structures for implementing Dify model plugins, covering LLM, TextEmbedding, Rerank, Speech2Text, Text2Speech, and Moderation models --- ## Introduction -This document details the interfaces and data structures required to implement Dify model plugins. It serves as a technical reference for developers integrating AI models with the Dify platform. +This page is the technical reference for the interfaces and data structures you implement when integrating AI models with Dify through a model plugin. Before diving into this API reference, we recommend reading [Model Design Rules](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules) for the conceptual model and [Creating a New Model Provider](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) for a step-by-step walkthrough. @@ -65,7 +65,7 @@ def validate_provider_credentials(self, credentials: dict) -> None: CredentialsValidateFailedError: If validation fails """ try: - # Example implementation - validate using an LLM model instance + # Example implementation: validate using an LLM model instance model_instance = self.get_model_instance(ModelType.LLM) model_instance.validate_credentials( model="example-model", @@ -88,8 +88,7 @@ class XinferenceProvider(Provider): - Credential information as defined in the provider's YAML configuration under `provider_credential_schema`. - Typically includes fields like `api_key`, `organization_id`, etc. + Credential information as defined in the provider's YAML configuration under `provider_credential_schema`, typically fields such as `api_key` and `organization_id`. @@ -97,12 +96,12 @@ If validation fails, your implementation must raise a `CredentialsValidateFailed -For predefined model providers, you should implement a thorough validation method that verifies the credentials work with your API. For custom model providers (where each model has its own credentials), a simplified implementation is sufficient. +For predefined model providers, implement a thorough validation method that verifies the credentials against your API. For custom model providers (where each model has its own credentials), a simplified implementation is sufficient. ## Models -Dify supports five distinct model types, each requiring implementation of specific interfaces. However, all model types share some common requirements. +Dify supports five distinct model types, each with its own interface. All model types share the common requirements below. ### Common Interfaces @@ -273,8 +272,9 @@ def _invoke_sync(self, model, api_params, user): Message list in Dify's standardized format: - - For `completion` models: Include a single `UserPromptMessage` - - For `chat` models: Include `SystemPromptMessage`, `UserPromptMessage`, `AssistantPromptMessage`, `ToolPromptMessage` as needed + + - For `completion` models: include a single `UserPromptMessage`. + - For `chat` models: include `SystemPromptMessage`, `UserPromptMessage`, `AssistantPromptMessage`, and `ToolPromptMessage` as needed. @@ -455,9 +455,10 @@ def _invoke( A structured response containing: - - model: The model used for embedding - - embeddings: List of embedding vectors corresponding to input texts - - usage: Metadata about token usage and costs + + - `model`: The model used for embedding. + - `embeddings`: Embedding vectors in the same order as the input texts. + - `usage`: Metadata about token usage and costs. @@ -577,11 +578,11 @@ def _invoke( - Optional minimum score threshold for filtering results + Minimum score a document must reach to be included in the results - Optional limit on number of results to return + Maximum number of results to return @@ -592,8 +593,9 @@ def _invoke( A structured response containing: - - model: The model used for reranking - - docs: List of RerankDocument objects with index, text, and score + + - `model`: The model used for reranking. + - `docs`: List of `RerankDocument` objects with index, text, and score. @@ -874,9 +876,9 @@ def _invoke( return result.flagged except Exception as e: - # Log the error but default to safe if there's an API issue - # This is a conservative approach - production systems might want - # different fallback behavior + # Log the error but default to safe if there's an API issue. + # This is a conservative approach; production systems might want + # different fallback behavior. logger.error(f"Moderation API error: {str(e)}") return False ``` @@ -948,8 +950,9 @@ def _invoke( Boolean indicating content safety: - - False: The content is safe - - True: The content contains harmful material + + - `False`: The content is safe. + - `True`: The content contains harmful material. @@ -961,11 +964,11 @@ Moderation is often used as a safety mechanism. Consider the implications of fal Many moderation APIs provide detailed category scores rather than just a binary result. Consider extending this implementation to return more detailed information about specific categories of harmful content if your application needs it. -### Entities +## Entities -#### PromptMessageRole +### PromptMessageRole -Message role +The role of a message in a conversation. ```python class PromptMessageRole(Enum): @@ -978,9 +981,9 @@ class PromptMessageRole(Enum): TOOL = "tool" ``` -#### PromptMessageContentType +### PromptMessageContentType -Message content type, divided into plain text and images. +The type of message content: plain text or image. ```python class PromptMessageContentType(Enum): @@ -991,9 +994,9 @@ class PromptMessageContentType(Enum): IMAGE = 'image' ``` -#### PromptMessageContent +### PromptMessageContent -Message content base class, used only for parameter declaration, cannot be initialized. +Base class for message content. It exists only for type declarations—do not instantiate it directly. ```python class PromptMessageContent(BaseModel): @@ -1004,10 +1007,9 @@ class PromptMessageContent(BaseModel): data: str # Content data ``` -Currently supports two types: text and images, and can support text and multiple images simultaneously. -You need to initialize `TextPromptMessageContent` and `ImagePromptMessageContent` separately. +Content currently supports two types, text and image, and a single message can combine text with multiple images. Instantiate `TextPromptMessageContent` and `ImagePromptMessageContent` instead. -#### TextPromptMessageContent +### TextPromptMessageContent ```python class TextPromptMessageContent(PromptMessageContent): @@ -1017,9 +1019,9 @@ class TextPromptMessageContent(PromptMessageContent): type: PromptMessageContentType = PromptMessageContentType.TEXT ``` -When passing in text and images, text needs to be constructed as this entity as part of the `content` list. +When a message combines text and images, wrap the text in this entity and add it to the `content` list. -#### ImagePromptMessageContent +### ImagePromptMessageContent ```python class ImagePromptMessageContent(PromptMessageContent): @@ -1034,12 +1036,11 @@ class ImagePromptMessageContent(PromptMessageContent): detail: DETAIL = DETAIL.LOW # Resolution ``` -When passing in text and images, images need to be constructed as this entity as part of the `content` list. -`data` can be a `url` or an image `base64` encoded string. +When a message combines text and images, wrap each image in this entity and add it to the `content` list. `data` accepts an image URL or a base64-encoded image string. -#### PromptMessage +### PromptMessage -Base class for all Role message bodies, used only for parameter declaration, cannot be initialized. +Base class for all role-specific messages. It exists only for type declarations—do not instantiate it directly. ```python class PromptMessage(ABC, BaseModel): @@ -1047,13 +1048,13 @@ class PromptMessage(ABC, BaseModel): Model class for prompt message. """ role: PromptMessageRole # Message role - content: Optional[str | list[PromptMessageContent]] = None # Supports two types: string and content list. The content list is for multimodal needs, see PromptMessageContent for details. - name: Optional[str] = None # Name, optional. + content: Optional[str | list[PromptMessageContent]] = None # Either a string or a content list; the list form supports multimodal input, see PromptMessageContent + name: Optional[str] = None # Optional name ``` -#### UserPromptMessage +### UserPromptMessage -UserMessage message body, represents user messages. +Represents a user message. ```python class UserPromptMessage(PromptMessage): @@ -1063,9 +1064,9 @@ class UserPromptMessage(PromptMessage): role: PromptMessageRole = PromptMessageRole.USER ``` -#### AssistantPromptMessage +### AssistantPromptMessage -Represents model response messages, typically used for `few-shots` or chat history input. +Represents a model response, typically used for few-shot examples or chat history input. ```python class AssistantPromptMessage(PromptMessage): @@ -1083,19 +1084,19 @@ class AssistantPromptMessage(PromptMessage): name: str # Tool name arguments: str # Tool parameters - id: str # Tool ID, only effective for OpenAI tool call, a unique ID for tool invocation, the same tool can be called multiple times - type: str # Default is function + id: str # Tool call ID; only meaningful for OpenAI tool calls. Uniquely identifies one invocation, since the same tool can be called multiple times + type: str # Defaults to "function" function: ToolCallFunction # Tool call information role: PromptMessageRole = PromptMessageRole.ASSISTANT tool_calls: list[ToolCall] = [] # Model's tool call results (only returned when tools are passed in and the model decides to call them) ``` -Here `tool_calls` is the list of `tool call` returned by the model after passing in `tools` to the model. +`tool_calls` holds the tool calls the model returns when the request includes `tools`. -#### SystemPromptMessage +### SystemPromptMessage -Represents system messages, typically used to set system instructions for the model. +Represents a system message, typically used to set system instructions for the model. ```python class SystemPromptMessage(PromptMessage): @@ -1105,9 +1106,9 @@ class SystemPromptMessage(PromptMessage): role: PromptMessageRole = PromptMessageRole.SYSTEM ``` -#### ToolPromptMessage +### ToolPromptMessage -Represents tool messages, used to pass results to the model for next-step planning after a tool has been executed. +Represents a tool message, which passes a tool's execution result back to the model for next-step planning. ```python class ToolPromptMessage(PromptMessage): @@ -1115,12 +1116,12 @@ class ToolPromptMessage(PromptMessage): Model class for tool prompt message. """ role: PromptMessageRole = PromptMessageRole.TOOL - tool_call_id: str # Tool call ID, if OpenAI tool call is not supported, you can also pass in the tool name + tool_call_id: str # Tool call ID; if the provider doesn't support OpenAI tool calls, you can pass the tool name instead ``` -The base class's `content` passes in the tool execution result. +Pass the tool's execution result through the inherited `content` field. -#### PromptMessageTool +### PromptMessageTool ```python class PromptMessageTool(BaseModel): @@ -1130,26 +1131,25 @@ class PromptMessageTool(BaseModel): name: str # Tool name description: str # Tool description parameters: dict # Tool parameters dict - ``` -#### LLMResult +### LLMResult ```python class LLMResult(BaseModel): """ Model class for llm result. """ - model: str # Actually used model + model: str # Model actually used prompt_messages: list[PromptMessage] # Prompt message list message: AssistantPromptMessage # Reply message - usage: LLMUsage # Tokens used and cost information - system_fingerprint: Optional[str] = None # Request fingerprint, refer to OpenAI parameter definition + usage: LLMUsage # Token usage and cost information + system_fingerprint: Optional[str] = None # Request fingerprint; see OpenAI's parameter definition ``` -#### LLMResultChunkDelta +### LLMResultChunkDelta -Delta entity within each iteration in streaming response +The incremental delta within each chunk of a streaming response. ```python class LLMResultChunkDelta(BaseModel): @@ -1158,59 +1158,59 @@ class LLMResultChunkDelta(BaseModel): """ index: int # Sequence number message: AssistantPromptMessage # Reply message - usage: Optional[LLMUsage] = None # Tokens used and cost information, only returned in the last message - finish_reason: Optional[str] = None # Completion reason, only returned in the last message + usage: Optional[LLMUsage] = None # Token usage and cost information; only returned in the last chunk + finish_reason: Optional[str] = None # Completion reason; only returned in the last chunk ``` -#### LLMResultChunk +### LLMResultChunk -Iteration entity in streaming response +A single chunk in a streaming response. ```python class LLMResultChunk(BaseModel): """ Model class for llm result chunk. """ - model: str # Actually used model + model: str # Model actually used prompt_messages: list[PromptMessage] # Prompt message list - system_fingerprint: Optional[str] = None # Request fingerprint, refer to OpenAI parameter definition - delta: LLMResultChunkDelta # Changes in content for each iteration + system_fingerprint: Optional[str] = None # Request fingerprint; see OpenAI's parameter definition + delta: LLMResultChunkDelta # Content changes in this chunk ``` -#### LLMUsage +### LLMUsage ```python class LLMUsage(ModelUsage): """ Model class for llm usage. """ - prompt_tokens: int # Tokens used by prompt + prompt_tokens: int # Tokens used by the prompt prompt_unit_price: Decimal # Prompt unit price - prompt_price_unit: Decimal # Prompt price unit, i.e., unit price based on how many tokens + prompt_price_unit: Decimal # Prompt price unit, i.e., the number of tokens the unit price applies to prompt_price: Decimal # Prompt cost - completion_tokens: int # Tokens used by completion + completion_tokens: int # Tokens used by the completion completion_unit_price: Decimal # Completion unit price - completion_price_unit: Decimal # Completion price unit, i.e., unit price based on how many tokens + completion_price_unit: Decimal # Completion price unit, i.e., the number of tokens the unit price applies to completion_price: Decimal # Completion cost total_tokens: int # Total tokens used total_price: Decimal # Total cost currency: str # Currency unit - latency: float # Request time (s) + latency: float # Request latency in seconds ``` -#### TextEmbeddingResult +### TextEmbeddingResult ```python class TextEmbeddingResult(BaseModel): """ Model class for text embedding result. """ - model: str # Actually used model - embeddings: list[list[float]] # Embedding vector list, corresponding to the input texts list + model: str # Model actually used + embeddings: list[list[float]] # Embedding vectors, in the same order as the input texts usage: EmbeddingUsage # Usage information ``` -#### EmbeddingUsage +### EmbeddingUsage ```python class EmbeddingUsage(ModelUsage): @@ -1220,41 +1220,41 @@ class EmbeddingUsage(ModelUsage): tokens: int # Tokens used total_tokens: int # Total tokens used unit_price: Decimal # Unit price - price_unit: Decimal # Price unit, i.e., unit price based on how many tokens + price_unit: Decimal # Price unit, i.e., the number of tokens the unit price applies to total_price: Decimal # Total cost currency: str # Currency unit - latency: float # Request time (s) + latency: float # Request latency in seconds ``` -#### RerankResult +### RerankResult ```python class RerankResult(BaseModel): """ Model class for rerank result. """ - model: str # Actually used model - docs: list[RerankDocument] # List of reranked segments + model: str # Model actually used + docs: list[RerankDocument] # List of reranked documents ``` -#### RerankDocument +### RerankDocument ```python class RerankDocument(BaseModel): """ Model class for rerank document. """ - index: int # Original sequence number - text: str # Segment text content - score: float # Score + index: int # Index in the original docs list + text: str # Document text + score: float # Relevance score ``` ## Related Resources -- [Model Design Rules](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules) - Understand the standards for model configuration -- [Model Plugin Introduction](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules) - Quickly understand the basic concepts of model plugins -- [Quickly Integrate a New Model](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) - Learn how to add new models to existing providers -- [Create a New Model Provider](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) - Learn how to develop brand new model providers +- [Model Design Rules](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules): standards for model configuration. +- [Model Plugin Introduction](/en/develop-plugin/features-and-specs/plugin-types/model-designing-rules): core concepts of model plugins. +- [Quickly Integrate a New Model](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider): add new models to existing providers. +- [Create a New Model Provider](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider): develop a new model provider from scratch. {/* Contributing Section @@ -1265,4 +1265,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/plugin-types/model-schema.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/plugin-types/multilingual-readme.mdx b/en/develop-plugin/features-and-specs/plugin-types/multilingual-readme.mdx index b889db7b6..c42574d5e 100644 --- a/en/develop-plugin/features-and-specs/plugin-types/multilingual-readme.mdx +++ b/en/develop-plugin/features-and-specs/plugin-types/multilingual-readme.mdx @@ -23,7 +23,7 @@ A plugin's README is the first thing users read on the [Dify Marketplace](https: All files must be UTF-8 encoded. The English `README.md` always stays in the plugin root; every other language goes inside a `readme/` subdirectory. -```bash +```text your_plugin/ ├── README.md ├── readme/ @@ -66,14 +66,14 @@ Briefly describe what data the plugin sends to third parties. Link to your PRIVACY.md. ``` -Avoid putting full API reference or development notes in the README; those belong in source comments or a separate docs site. The Marketplace audience is end users picking a plugin, not contributors reading your codebase. +Avoid putting a full API reference or development notes in the README; those belong in source comments or a separate docs site. The Marketplace audience is end users picking a plugin, not contributors reading your codebase. ## How the Marketplace Picks a Language When a visitor opens your plugin's detail page, the Marketplace looks for a README matching their UI language. If a match exists in the `readme/` directory, it renders that file. Otherwise it falls back to the English `README.md`. - ![Plugin Details Page En](/images/develop-plugin/specs/plugin-details-page-en.jpeg) + ![Plugin Detail Page in English](/images/develop-plugin/specs/plugin-details-page-en.jpeg) diff --git a/en/develop-plugin/features-and-specs/plugin-types/persistent-storage-kv.mdx b/en/develop-plugin/features-and-specs/plugin-types/persistent-storage-kv.mdx index a22ee9dfa..4d559ff83 100644 --- a/en/develop-plugin/features-and-specs/plugin-types/persistent-storage-kv.mdx +++ b/en/develop-plugin/features-and-specs/plugin-types/persistent-storage-kv.mdx @@ -7,12 +7,13 @@ dimensions: standard_title: Persistent Storage KV language: en title: Persistent Storage -description: Learn how to implement persistent storage in your Dify plugins using the built-in key-value database to maintain state across interactions. +description: Store data across plugin interactions with the built-in key-value storage --- ## Overview Most plugin tools and endpoints operate in a stateless, single-round interaction model: + 1. Receive a request 2. Process data 3. Return a response @@ -21,10 +22,10 @@ Most plugin tools and endpoints operate in a stateless, single-round interaction However, many real-world applications require maintaining state across multiple interactions. This is where **persistent storage** becomes essential. -The persistent storage mechanism allows plugins to store data persistently within the same workspace, enabling stateful applications and memory features. +Persistent storage lets plugins keep data within the same workspace across interactions, enabling stateful applications and memory features. -Dify currently provides a key-value (KV) storage system for plugins, with plans to introduce more flexible and powerful storage interfaces in the future based on developer needs. +Dify currently provides a key-value (KV) storage system for plugins; more flexible and powerful storage interfaces are planned based on developer needs. ## Access Storage @@ -143,11 +144,11 @@ def delete(self, key: str) -> None: ## Common Use Cases -- **User Preferences**: Store user settings and preferences between sessions -- **Conversation History**: Maintain context from previous conversations -- **API Tokens**: Store authentication tokens securely -- **Cached Data**: Store frequently accessed data to reduce API calls -- **File Storage**: Store user-uploaded files or generated content +- **User preferences**: Store user settings and preferences between sessions. +- **Conversation history**: Maintain context from previous conversations. +- **API tokens**: Store authentication tokens securely. +- **Cached data**: Store frequently accessed data to reduce API calls. +- **File storage**: Store user-uploaded files or generated content. {/* Contributing Section @@ -158,4 +159,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/plugin-types/persistent-storage-kv.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/plugin-types/plugin-info-by-manifest.mdx b/en/develop-plugin/features-and-specs/plugin-types/plugin-info-by-manifest.mdx index 3e6131322..9832dc6cd 100644 --- a/en/develop-plugin/features-and-specs/plugin-types/plugin-info-by-manifest.mdx +++ b/en/develop-plugin/features-and-specs/plugin-types/plugin-info-by-manifest.mdx @@ -10,15 +10,13 @@ title: Manifest description: YAML schema for the plugin manifest that declares name, author, runtime, resources, permissions, and which tools/models/endpoints the plugin ships --- -The Manifest is a YAML-compliant file that defines the most basic information of a **plugin**, including but not limited to the plugin name, author, included tools, models, etc. For the overall architecture of the plugin, please refer to [Basic Concepts of Plugin Development](/en/develop-plugin/getting-started/getting-started-dify-plugin) and [Developer Cheatsheet](/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet). +The manifest is a YAML file that defines a plugin's basic information: name, author, included tools and models, and more. If the file is malformed, plugin parsing and packaging fails. -If the format of this file is incorrect, the parsing and packaging process of the plugin will fail. +For the overall plugin architecture, see [Basic Concepts of Plugin Development](/en/develop-plugin/getting-started/getting-started-dify-plugin) and the [Developer Cheatsheet](/en/develop-plugin/dev-guides-and-walkthroughs/cheatsheet). ## Code Example -Below is a simple example of a Manifest file. The meaning and function of each data item will be explained later. - -For reference code of other plugins, please refer to the [GitHub code repository](https://github.com/langgenius/dify-official-plugins/blob/main/tools/google/manifest.yaml). +Below is a simple manifest file; each field is explained in the Structure section that follows. For a real-world example, see the [Google tool plugin manifest](https://github.com/langgenius/dify-official-plugins/blob/main/tools/google/manifest.yaml). ```yaml version: 0.0.1 @@ -62,11 +60,11 @@ privacy: "./privacy.md" ## Structure - The version of the plugin. + Plugin version. - Plugin type, currently only `plugin` is supported, `bundle` will be supported in the future. + Plugin type. Currently only `plugin` is supported; `bundle` support is planned. @@ -78,7 +76,7 @@ privacy: "./privacy.md" - Creation time, required by the Marketplace not to be later than the current time. + Creation time. The Marketplace requires this to be no later than the current time. @@ -86,14 +84,14 @@ privacy: "./privacy.md" - Resources to apply for. + Resources the plugin requests. - Maximum memory usage, mainly related to AWS Lambda resource application on SaaS, unit in bytes. + Maximum memory usage in bytes. Mainly relates to AWS Lambda resource allocation on SaaS. - Permission application. + Permissions the plugin requests. Permission for reverse invocation of tools. @@ -167,29 +165,23 @@ privacy: "./privacy.md" - Maximum allowed persistent memory size, unit in bytes. + Maximum allowed persistent storage size, in bytes. - A list of `yaml` files for the specific capabilities extended by the plugin. Absolute path within the plugin package. For example, if you need to extend a model, you need to define a file similar to `openai.yaml`, fill in the file path here, and the file at this path must actually exist, otherwise packaging will fail. + Lists the YAML files for the capabilities the plugin extends, as absolute paths within the plugin package. For example, to extend a model, define a file such as `openai.yaml` and list its path here. The file must exist at that path, or packaging fails. - Extending both tools and models simultaneously is not allowed. - - - - Having no extensions is not allowed. - + The following combinations are not allowed: - - Extending both models and Endpoints simultaneously is not allowed. - - - - Currently, only one provider is supported for each type of extension. + - Extending both tools and models. + - Extending both models and Endpoints. + - Having no extensions at all. + + Currently, each extension type supports only one provider. @@ -213,11 +205,11 @@ privacy: "./privacy.md" Metadata for the plugin. - `manifest` format version, initial version `0.0.1`. + Manifest format version. The initial version is `0.0.1`. - Supported architectures, currently only `amd64` and `arm64` are supported. + Supported architectures. Currently only `amd64` and `arm64` are supported. @@ -228,17 +220,17 @@ privacy: "./privacy.md" - Language version, currently only `3.12` is supported. + Language version. Currently only `3.12` is supported. - Program entry point, should be `main` under Python. + Program entry point. For Python, this should be `main`. - Specifies the relative path or URL of the plugin's privacy policy file, e.g., `"./privacy.md"` or `"https://your-web/privacy"`. If you plan to list the plugin on the Dify Marketplace, **this field is required** to provide clear user data usage and privacy statements. For detailed filling guidelines, please refer to [Plugin Privacy Data Protection Guidelines](/en/develop-plugin/publishing/standards/privacy-protection-guidelines). + Relative path or URL of the plugin's privacy policy, for example `"./privacy.md"` or `"https://your-web/privacy"`. **Required for listing on the Dify Marketplace**, where plugins must clearly state how they use user data. For details, see the [Plugin Privacy Data Protection Guidelines](/en/develop-plugin/publishing/standards/privacy-protection-guidelines). {/* @@ -250,4 +242,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/plugin-types/plugin-info-by-manifest.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/plugin-types/plugin-logging.mdx b/en/develop-plugin/features-and-specs/plugin-types/plugin-logging.mdx index 3d40b577a..a520d14b8 100644 --- a/en/develop-plugin/features-and-specs/plugin-types/plugin-logging.mdx +++ b/en/develop-plugin/features-and-specs/plugin-types/plugin-logging.mdx @@ -1,15 +1,15 @@ --- title: Plugin Logging -description: Emit log lines from inside a plugin using the SDK plugin_logger_handler, visible during remote debugging and persisted to daemon container logs +description: Emit logs from your plugin with the SDK's plugin_logger_handler, visible during remote debugging and in daemon container logs --- -As a plugin developer, you may want to print arbitrary strings to logs during plugin processing for development or debugging purposes. +While developing or debugging a plugin, you often want to log what your code is doing. -For this purpose, the plugin SDK implements a handler for Python's standard `logging` library. By using this, you can output any string to both the **standard output during remote debugging** and the **plugin daemon container logs** (community edition only). +The plugin SDK provides a handler for Python's standard `logging` library. Add it to your logger to write any string to both the standard output during remote debugging and the plugin daemon container logs (community edition only). -## Sample +## Example -Import `plugin_logger_handler` and add it to your logger as a handler. Below is a sample code for a tool plugin. +Import `plugin_logger_handler` and add it to your logger. The following example shows a tool plugin. ```python from collections.abc import Generator @@ -48,4 +48,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/plugin-types/plugin-logging.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin.mdx b/en/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin.mdx index e55752e53..d7758ba65 100644 --- a/en/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin.mdx +++ b/en/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin.mdx @@ -10,7 +10,7 @@ title: Plugin Debugging description: Run your in-development plugin locally and attach it to a live Dify workspace for end-to-end testing, no packaging required --- -Remote debugging is the fastest way to iterate on a plugin. You run the plugin process on your laptop, and Dify treats it as if it were installed in the workspace. Saves, edits, and restarts take effect immediately. +Remote debugging is the fastest way to iterate on a plugin. You run the plugin process on your laptop, and Dify treats it as if it were installed in the workspace. Save your edits and restart the process, and the changes take effect immediately. ## Prerequisites @@ -62,7 +62,7 @@ The process stays in the foreground and logs incoming invocations. Edit your cod ## Step 4: Verify the Install -Go back to the Dify **Plugins** page. The plugin appears in the list, labelled with a debug marker. Other members of the workspace can also see and use it. +Go back to the Dify **Plugins** page. The plugin appears in the list, labeled with a debug marker. Other members of the workspace can also see and use it. ![Plugin Installed to Workspace](https://assets-docs.dify.ai/2024/12/ec26e5afc57bbfeb807719638f603807.png) @@ -93,9 +93,9 @@ Trigger the plugin as you would any other: call it from a workflow node, run it ## Related Resources -- [CLI](/en/develop-plugin/getting-started/cli) - Scaffold a plugin and set up `.env` -- [Plugin Logging](/en/develop-plugin/features-and-specs/plugin-types/plugin-logging) - Emit structured logs from inside your plugin -- [Package as Local File and Share](/en/develop-plugin/publishing/marketplace-listing/release-by-file) - Ship the plugin once debugging is done +- [CLI](/en/develop-plugin/getting-started/cli)—Scaffold a plugin and set up `.env` +- [Plugin Logging](/en/develop-plugin/features-and-specs/plugin-types/plugin-logging)—Emit structured logs from inside your plugin +- [Package as Local File and Share](/en/develop-plugin/publishing/marketplace-listing/release-by-file)—Ship the plugin once debugging is done {/* Contributing Section diff --git a/en/develop-plugin/features-and-specs/plugin-types/tool.mdx b/en/develop-plugin/features-and-specs/plugin-types/tool.mdx index dc75e9c09..9e1ac7aab 100644 --- a/en/develop-plugin/features-and-specs/plugin-types/tool.mdx +++ b/en/develop-plugin/features-and-specs/plugin-types/tool.mdx @@ -7,17 +7,12 @@ dimensions: standard_title: Tool language: en title: Tool Return -description: This document provides a detailed introduction to the data structure - and usage of Tools in Dify plugins. It covers how to return different types of messages - (image URLs, links, text, files, JSON), how to create variable and streaming variable - messages, and how to define tool output variable schemas for reference in workflows. +description: How tool plugins return messages (text, links, images, files, JSON), create standard and streaming variables, and define output schemas for workflow references --- ## Overview - -Before diving into the detailed interface documentation, make sure you have a general understanding of the tool integration process for Dify plugins. - +A tool returns its results as messages and variables. This page covers the message interfaces, variable creation, and output schema definitions. @@ -35,14 +30,12 @@ Before diving into the detailed interface documentation, make sure you have a ge ### Message Return - -Dify supports various message types such as `text`, `links`, `images`, `file BLOBs`, and `JSON`. These messages can be returned through specialized interfaces. - +Dify supports several message types—text, links, images, file blobs, and JSON—each returned through a dedicated interface. -By default, a tool's output in a workflow includes three fixed variables: `files`, `text`, and `json`. The methods below help you populate these variables with appropriate content. +By default, a tool's output in a workflow includes three fixed variables: `files`, `text`, and `json`. The methods below populate these variables. -While you can use methods like `create_image_message` to return an image, tools also support custom output variables, making it more convenient to reference specific data in a workflow. +While you can use methods like `create_image_message` to return an image, tools also support custom output variables, which make it easier to reference specific data in a workflow. ### Message Types @@ -132,29 +125,30 @@ def create_json_message(self, json: dict) -> ToolInvokeMessage: - URL to an image that will be downloaded and displayed + URL to an image that will be downloaded and displayed. - URL to be displayed as a clickable link + URL to display as a clickable link. - Text content to be displayed + Text content to display. - Raw file data in bytes format + Raw file data in bytes. - File metadata including: - - `mime_type`: The MIME type of the file (e.g., "image/png") - - Other metadata relevant to the file + File metadata, including: + + - `mime_type`: The MIME type of the file, for example `image/png`. + - Other metadata relevant to the file. - Python dictionary to be serialized as JSON + Python dictionary to serialize as JSON. @@ -208,25 +202,24 @@ def create_stream_variable_message( - Name of the variable to be created or updated + Name of the variable to create or update. Value to assign to the variable: - - For standard variables: Any Python data type - - For streaming variables: String data only + + - Standard variables: any Python data type. + - Streaming variables: string data only. -The streaming variable method (`create_stream_variable_message`) currently only supports string data. Complex data types cannot be streamed with the typewriter effect. +`create_stream_variable_message` currently only supports string data. Complex data types cannot be streamed with the typewriter effect. ## Custom Output Variables - -To reference a tool's output variables in a workflow application, you need to define which variables might be output. This is done using the [JSON Schema](https://json-schema.org/) format in your tool's manifest. - +To reference a tool's output variables in a workflow application, declare which variables the tool might output using [JSON Schema](https://json-schema.org/) in the tool's manifest. ### Define Output Schema @@ -270,24 +263,24 @@ output_schema: - The root object defining your tool's output schema + Root object defining the tool's output schema. - Must be "object" for tool output schemas + Must be `object` for tool output schemas. - Dictionary of all possible output variables + Dictionary of all possible output variables. - Definition for each output variable, including its type and description + Definition of each output variable, including its type and description. -Even with an output schema defined, you still need to actually return a variable using `create_variable_message()` in your implementation code. Otherwise, the workflow will receive `None` for that variable. +Defining an output schema is not enough on its own: your implementation must still return each variable with `create_variable_message()`. Otherwise, the workflow receives `None` for that variable. ### Example Implementation @@ -392,4 +385,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/features-and-specs/plugin-types/tool.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/getting-started/choose-plugin-type.mdx b/en/develop-plugin/getting-started/choose-plugin-type.mdx index a2e1dd7df..4aed3a788 100644 --- a/en/develop-plugin/getting-started/choose-plugin-type.mdx +++ b/en/develop-plugin/getting-started/choose-plugin-type.mdx @@ -12,7 +12,7 @@ description: A short decision guide for picking between Tool, Model, Agent Strat Dify supports several plugin types, each targeting a different extension point inside the platform. Pick the one that matches how your code will be invoked. -## Quick decision +## Quick Decision | You want to... | Build a... | | :--- | :--- | @@ -20,10 +20,10 @@ Dify supports several plugin types, each targeting a different extension point i | Make a new LLM, embedding, rerank, TTS, STT, or moderation model selectable inside Dify | [Model](/en/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider) | | Implement a custom reasoning loop for Agents (ReAct, Function Calling variant, etc.) | [Agent Strategy](/en/develop-plugin/dev-guides-and-walkthroughs/agent-strategy-plugin) | | Expose an HTTP endpoint that external services can call to drive a Dify workflow | [Extension (Endpoint)](/en/develop-plugin/dev-guides-and-walkthroughs/endpoint) | -| Ingest documents from an external system into a Knowledge Base | [Datasource](/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin) | +| Ingest documents from an external system into a knowledge base | [Datasource](/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin) | | Start a workflow when something happens upstream (a webhook fires, a file lands) | [Trigger](/en/develop-plugin/dev-guides-and-walkthroughs/trigger-plugin) | -## Common questions +## Common Questions @@ -33,14 +33,14 @@ Dify supports several plugin types, each targeting a different extension point i A Tool is an individual capability the Agent decides to call (like "search the web"). An Agent Strategy is the *reasoning loop itself*: the policy that decides which tools to call, in what order, and when to stop. Build a tool unless you're replacing how Agents think. - Datasource brings documents into a Knowledge Base for retrieval. Trigger fires a workflow in real time on an upstream event. Same systems can power both, but the consumption pattern is different: indexing vs. event-driven execution. + Datasource brings documents into a knowledge base for retrieval. Trigger fires a workflow in real time on an upstream event. The same systems can power both, but the consumption pattern differs: indexing vs. event-driven execution. Extensions are for the other direction: an outside service calls *into* Dify. Tools are for Agents/Workflows calling *out* to a service. Build an Extension when your plugin is the entry point, not the action. -## Next steps +## Next Steps Once you've picked a type, set up the CLI and scaffold a project: diff --git a/en/develop-plugin/getting-started/cli.mdx b/en/develop-plugin/getting-started/cli.mdx index 5f83d5cbb..65c586b76 100644 --- a/en/develop-plugin/getting-started/cli.mdx +++ b/en/develop-plugin/getting-started/cli.mdx @@ -10,17 +10,16 @@ title: CLI description: Install the Dify CLI, scaffold a new plugin project, and run it against a Dify instance for local development --- -Set up and package your Dify plugins using the Command Line Interface (CLI). The CLI provides a streamlined way to manage your plugin development workflow, from initialization to packaging. - -This guide will instruct you on how to use the CLI for Dify plugin development. +The Dify command line interface (CLI) manages your plugin development workflow, from project initialization to packaging. This guide covers installing the CLI, scaffolding a plugin project, and running it against a Dify instance. ## Prerequisites -Before you begin, ensure you have the following installed: -- Python version 3.12 -- Dify CLI -- Homebrew (for Mac users) -## Create a Dify Plugin Project +Before you begin, make sure you have: + +- Python 3.12 +- Homebrew (macOS only, used to install the CLI) + +## Install the CLI @@ -42,13 +41,15 @@ Before you begin, ensure you have the following installed: -Now you have successfully installed the Dify CLI. You can verify the installation by running: +Verify the installation: ```bash dify version ``` -You can create a new Dify plugin project using the following command: +## Create a Plugin Project + +Create a new plugin project with: ```bash dify plugin init @@ -74,7 +75,7 @@ Controls: ↑/↓ Navigate • Space/Tab Toggle selection • Enter Next step ``` -Choose `python` and hit Enter to proceed with the Python plugin template. +Choose `python` and press Enter to use the Python plugin template, then select the type of plugin you want to build: ```bash Select the type of plugin you want to create, and press `Enter` to continue @@ -109,14 +110,14 @@ We've provided templates to help you get started. Choose one of the options belo trigger ``` -Enter the default dify version, leave it blank to use the latest version: +When prompted for the minimal Dify version, leave it blank to use the latest version: ```bash Edit minimal Dify version requirement, leave it blank by default Minimal Dify version (press Enter to next step): ``` -Now you are ready to go! The CLI will create a new directory with the plugin name you provided, and set up the basic structure for your plugin. +The CLI creates a new directory named after your plugin and sets up the basic project structure. Move into it: ```bash cd hello-world @@ -124,13 +125,13 @@ cd hello-world ## Run the Plugin -Make sure you are in the hello-world directory +From the `hello-world` directory, copy the example environment file: ```bash cp .env.example .env ``` -Edit the `.env` file to set your plugin's environment variables, such as API keys or other configurations. You can find these variables in the Dify dashboard. Log in to your Dify environment, click the “Plugins” icon in the top right corner, then click the debug icon (or something that looks like a bug). In the pop-up window, copy the “API Key” and “Host Address”. (Please refer to your local corresponding screenshot, which shows the interface for obtaining the key and host address) +Edit the `.env` file to set your plugin's environment variables, such as API keys or other configurations. To get the debugging credentials, log in to your Dify environment, click **Plugins** in the top-right corner, then click the debug icon. In the pop-up window, copy the **API Key** and **Host Address**. ```bash INSTALL_METHOD=remote @@ -142,7 +143,7 @@ REMOTE_INSTALL_KEY=********-****-****-****-************ `REMOTE_INSTALL_URL` combines host and port in `host:port` form. The host and port are shown together in the **API Key** card on the Plugins page. -Now you can run your plugin locally using the following command: +Install the dependencies and run your plugin: ```bash pip install -r requirements.txt @@ -158,4 +159,3 @@ It will be automatically generated by the script. --- [Edit this page](https://github.com/langgenius/dify-docs/edit/main/en/develop-plugin/getting-started/cli.mdx) | [Report an issue](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml) - diff --git a/en/develop-plugin/getting-started/getting-started-dify-plugin.mdx b/en/develop-plugin/getting-started/getting-started-dify-plugin.mdx index 71c145e52..6c46d7b11 100644 --- a/en/develop-plugin/getting-started/getting-started-dify-plugin.mdx +++ b/en/develop-plugin/getting-started/getting-started-dify-plugin.mdx @@ -10,22 +10,23 @@ title: Dify Plugin description: Modular components that extend Dify AI applications with external services, custom logic, and specialized tools --- -Dify plugins are modular components that enhance AI applications with additional capabilities. They allow you to integrate external services, custom functions, and specialized tools into your Dify-built AI applications. +Dify plugins are modular components that extend your Dify-built AI applications with external services, custom functions, and specialized tools. ![Marketplace](/images/develop-plugin/get-started/marketplace.png) Through plugins, your AI applications can: + - Connect to external APIs - Process different types of data - Perform specialized calculations - Execute real-world actions -## Start here +## Start Here - + A short decision guide for picking between Tool, Model, Agent Strategy, Extension, Datasource, and Trigger plugins. @@ -68,8 +69,8 @@ Through plugins, your AI applications can: icon="puzzle-piece" href="/en/develop-plugin/dev-guides-and-walkthroughs/endpoint" > - Implement integration with external services through HTTP Webhooks - + Integrate with external services through HTTP webhooks + Learn more /console/api/oauth/plugin///to The plugin SDK refreshes tokens automatically when they expire, provided your provider implementation returns a valid `refresh_token` from the initial authorization. Confirm `OAuthCredentials.refresh_token` is populated, and that your `_oauth_refresh_credentials` method is implemented. -## Marketplace publishing +## Marketplace Publishing ### Why was my Marketplace PR rejected by the automated check? @@ -86,7 +86,7 @@ Bump `version` in `manifest.yaml`, open a new PR against `langgenius/dify-plugin Not currently. The Marketplace only accepts free plugins. Future pricing policies will be announced separately. -## Storage and limits +## Storage and Limits ### Where do plugin logs go? diff --git a/en/develop-plugin/publishing/marketplace-listing/plugin-auto-publish-pr.mdx b/en/develop-plugin/publishing/marketplace-listing/plugin-auto-publish-pr.mdx index 058383c59..a91aca7a1 100644 --- a/en/develop-plugin/publishing/marketplace-listing/plugin-auto-publish-pr.mdx +++ b/en/develop-plugin/publishing/marketplace-listing/plugin-auto-publish-pr.mdx @@ -7,104 +7,98 @@ dimensions: standard_title: Plugin Auto Publish PR language: en title: Automatically Publish Plugins via PR -description: This document describes how to automate the release process of Dify plugins using GitHub Actions, including configuration steps, parameter descriptions, and usage methods, helping plugin developers streamline the release process without manual intervention. +description: Automate plugin packaging and Marketplace PR creation with a GitHub Actions workflow that runs on every push to main --- -### Background +## Background -Updating plugins that others are actively using can be tedious. Traditionally, you would need to modify code, bump versions, push changes, create branches, package files, and submit PRs manually - a repetitive process that slows down development. +Updating a plugin that others actively use is tedious by hand: modify the code, bump the version, push changes, create a branch, package the file, and open a PR—every release. -Thus, we have created **Plugin Auto-PR**, a GitHub Actions workflow that automates the entire process. Now you can package, push, and create PRs with a single action, focusing on building great plugins. +**Plugin Auto-PR** is a GitHub Actions workflow that automates the whole sequence. One push packages the plugin and opens the Marketplace PR, so you can focus on building. -### Concepts +## Concepts -#### GitHub Actions +### GitHub Actions -GitHub Actions automates your development tasks in GitHub. - -**How it works**: When triggered (e.g., by a code push), it runs your workflow in a cloud-based virtual machine, handling everything from build to deployment automatically. +GitHub Actions automates development tasks in GitHub. When triggered (for example, by a code push), it runs your workflow in a cloud-based virtual machine, handling everything from build to deployment. ![Workflow](https://assets-docs.dify.ai/2025/04/60534de8e220f860947b32a8329a8349.png) -**Limits**: +GitHub Actions usage limits: -* Public repositories: Unlimited -* Private repositories: 2000 minutes per month +- **Public repositories**: Unlimited. +- **Private repositories**: 2000 minutes per month. -#### Plugin Auto-PR +### Plugin Auto-PR -**How it works**: +The workflow runs these steps: -1. Workflow triggers when you push code to the main branch of your plugin source repository -2. Workflow reads plugin information from the `manifest.yaml` file -3. Automatically packages the plugin as a `.difypkg` file -4. Pushes the packaged file to your forked `dify-plugins` repository -5. Creates a new branch and commits changes -6. Automatically creates a PR to merge into the upstream repository +1. Triggers when you push code to the main branch of your plugin source repository. +2. Reads plugin information from the `manifest.yaml` file. +3. Packages the plugin as a `.difypkg` file. +4. Pushes the packaged file to your forked `dify-plugins` repository. +5. Creates a new branch and commits the changes. +6. Creates a PR to merge into the upstream repository. -### Prerequisites +## Prerequisites -#### Repository +### Repositories -* You already have your own plugin source code repository (e.g., `your-name/plugin-source`) -* You already have your own forked plugin repository (e.g., `your-name/dify-plugins`) -* Your forked repository already has the plugin directory structure: +- Your own plugin source code repository (e.g., `your-name/plugin-source`). +- Your own fork of the plugin repository (e.g., `your-name/dify-plugins`). +- The plugin directory structure already in place in your fork: -``` +```text dify-plugins/ └── your-author-name └── plugin-name ``` -#### Permission - -This workflow requires appropriate permissions to function: +### Permissions -* You need to create a GitHub Personal Access Token (PAT) with sufficient permissions -* The PAT must have permission to push code to your forked repository -* The PAT must have permission to create PRs to the upstream repository +Create a GitHub Personal Access Token (PAT) that can push code to your forked repository and create PRs to the upstream repository. -### Parameters and Configuration +## Parameters and Configuration -#### Setup Requirements +### Setup Requirements -To get started with auto-publishing, you will need two key components: +Auto-publishing needs two things in place. -**manifest.yaml file**: This file drives the automation process: +The `manifest.yaml` file drives the automation: -* `name`: Your plugin’s name (affects package and branch names) -* `version`: Semantic version number (increment with each release) -* `author`: Your GitHub username (determines repository paths) +- **`name`**: Your plugin's name (affects package and branch names). +- **`version`**: Semantic version number (increment with each release). +- **`author`**: Your GitHub username (determines repository paths). -**PLUGIN\_ACTION Secret**: You need to add this secret to your plugin source repository: +The `PLUGIN_ACTION` secret in your plugin source repository holds the credentials: -* Value: Must be a Personal Access Token (PAT) with sufficient permissions -* Permission: Ability to push branches to your forked repository and create PRs to the upstream repository +- **Value**: A Personal Access Token (PAT) with sufficient permissions. +- **Permissions**: Push branches to your forked repository and create PRs to the upstream repository. -#### Automatically-Generated Parameters +### Automatically Generated Parameters -Once set up, the workflow automatically handles these parameters: +Once set up, the workflow derives these parameters for you: -* GitHub username: Read from the `author` field in `manifest.yaml` -* Author folder name: Consistent with the `author` field -* Plugin name: Read from the `name` field in `manifest.yaml` -* Branch name: `bump-{plugin-name}-plugin-{version}` -* Package filename: `{plugin-name}-{version}.difypkg` -* PR title and content: Automatically generated based on plugin name and version +- **GitHub username**: Read from the `author` field in `manifest.yaml`. +- **Author folder name**: Matches the `author` field. +- **Plugin name**: Read from the `name` field in `manifest.yaml`. +- **Branch name**: `bump-{plugin-name}-plugin-{version}`. +- **Package filename**: `{plugin-name}-{version}.difypkg`. +- **PR title and content**: Generated from the plugin name and version. -### Step-by-Step Guide +## Step-by-Step Guide Ensure you have forked the official `dify-plugins` repository and have your own plugin source repository. - Navigate to your plugin source repository, click **Settings > Secrets and variables > Actions > New repository secret**, and create a GitHub Secret: + In your plugin source repository, go to **Settings** > **Secrets and variables** > **Actions** > **New repository secret** and create a secret: - * Name: `PLUGIN_ACTION` - * Value: GitHub Personal Access Token (PAT) with write permissions to the target repository (`your-name/dify-plugins`) + - **Name**: `PLUGIN_ACTION` + - **Value**: A GitHub Personal Access Token (PAT) with write permissions to the target repository (`your-name/dify-plugins`) ![Create Secrets](https://assets-docs.dify.ai/2025/04/8abd72b677dd24752910c304c76f1c26.png) @@ -112,9 +106,9 @@ Once set up, the workflow automatically handles these parameters: - Create a `.github/workflows/` directory in your repository, create a file named `plugin-publish.yml` in this directory, and paste the workflow below. + Create a `.github/workflows/` directory in your repository, add a file named `plugin-publish.yml`, and paste in the workflow below. - At a high level the workflow runs on every push to `main`, downloads the Dify CLI, packages the plugin from the manifest, checks out your `dify-plugins` fork, and opens a PR against `langgenius/dify-plugins` with the new `.difypkg`. + At a high level, the workflow runs on every push to `main`, downloads the Dify CLI, packages the plugin from the manifest, checks out your `dify-plugins` fork, and opens a PR against `langgenius/dify-plugins` with the new `.difypkg`. ```yaml @@ -266,7 +260,7 @@ Once set up, the workflow automatically handles these parameters: - Ensure those following fields are correctly set: + Make sure these fields are set correctly: ```yaml version: 0.0.x # Version number @@ -276,47 +270,47 @@ Once set up, the workflow automatically handles these parameters: -### Usage Guide +## Usage Guide -#### First-time Setup +### First-Time Setup -When setting up the auto-publish workflow for the first time, complete these steps: +Before the first automated release, confirm that: -1. Ensure you have forked the official `dify-plugins` repository -2. Ensure your plugin source repository structure is correct -3. Set up the `PLUGIN_ACTION Secret` in your plugin source repository -4. Create the workflow file `.github/workflows/plugin-publish.yml` -5. Ensure the `name` and `author` fields in the `manifest.yaml` file are correctly configured +1. You have forked the official `dify-plugins` repository. +2. Your plugin source repository structure is correct. +3. The `PLUGIN_ACTION` secret is set in your plugin source repository. +4. The workflow file `.github/workflows/plugin-publish.yml` exists. +5. The `name` and `author` fields in `manifest.yaml` are configured correctly. -#### Subsequent Updates +### Subsequent Updates To publish new versions after setup: -1. Modify the code -2. Update the `version` field in `manifest.yaml` +1. Modify the code. +2. Update the `version` field in `manifest.yaml`. - - ![Release](https://assets-docs.dify.ai/2025/04/9eed2b9110e91e18008b399e58198f03.png) - + + ![Release](https://assets-docs.dify.ai/2025/04/9eed2b9110e91e18008b399e58198f03.png) + -3. Push all changes to the main branch -4. Wait for GitHub Actions to complete packaging, branch creation, and PR submission +3. Push all changes to the main branch. +4. Wait for GitHub Actions to complete packaging, branch creation, and PR submission. -### Outcome +## Outcome -When you push code to the main branch of your plugin source repository, GitHub Actions will automatically execute the publishing process: +When you push code to the main branch of your plugin source repository, GitHub Actions runs the publishing process automatically: -* Package the plugin in `{plugin-name}-{version}.difypkg` format -* Push the packaged file to the target repository -* Create a PR to merge into the fork repository +- Packages the plugin in `{plugin-name}-{version}.difypkg` format. +- Pushes the packaged file to the target repository. +- Creates a PR to merge into the fork repository. ![Outcome](https://assets-docs.dify.ai/2025/04/60d5de910c6ce2482c67ddec3320311f.png) -### Example Repository +## Example Repository -See [example repository](https://github.com/Yevanchen/exa-in-dify) to understand configuration and best practices. +See the [example repository](https://github.com/Yevanchen/exa-in-dify) for a working configuration and best practices. {/* Contributing Section diff --git a/en/develop-plugin/publishing/marketplace-listing/release-by-file.mdx b/en/develop-plugin/publishing/marketplace-listing/release-by-file.mdx index 2982a27bd..ad37b61f1 100644 --- a/en/develop-plugin/publishing/marketplace-listing/release-by-file.mdx +++ b/en/develop-plugin/publishing/marketplace-listing/release-by-file.mdx @@ -24,7 +24,7 @@ For wider distribution, see the [Publishing Overview](/en/develop-plugin/publish The `author` field in `manifest.yaml` and every `provider/*.yaml` must match your GitHub handle. Mismatches cause `plugin_unique_identifier is not valid` at install time. See [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) for the full manifest spec. -## Package the plugin +## Package the Plugin @@ -43,7 +43,7 @@ The `author` field in `manifest.yaml` and every `provider/*.yaml` must match you ![Generated Plugin File](https://assets-docs.dify.ai/2024/12/98e09c04273eace8fe6e5ac976443cca.png) -## Install from the file +## Install from the File @@ -69,9 +69,9 @@ The plugin is now in the workspace and ready to use in Agents, Workflows, or Too Self-hosted Dify enforces signature verification by default. Unsigned `.difypkg` files installed via Local File will be rejected unless you sign them or change the verification setting. See [Third-Party Signature Verification](/en/develop-plugin/publishing/standards/third-party-signature-verification). -## Share the file +## Share the File -Hand the `.difypkg` file to your users directly, over email, internal file share, or any channel you control. They install it with the same flow above. +Hand the `.difypkg` file to your users directly: over email, an internal file share, or any channel you control. They install it with the same flow above. If you want broader distribution instead, consider: @@ -84,7 +84,7 @@ If you want broader distribution instead, consider: -## Related resources +## Related Resources - [Publishing Overview](/en/develop-plugin/publishing/marketplace-listing/release-overview) - [Dify CLI](/en/develop-plugin/getting-started/cli) diff --git a/en/develop-plugin/publishing/marketplace-listing/release-overview.mdx b/en/develop-plugin/publishing/marketplace-listing/release-overview.mdx index 58b86524a..8e4c6956e 100644 --- a/en/develop-plugin/publishing/marketplace-listing/release-overview.mdx +++ b/en/develop-plugin/publishing/marketplace-listing/release-overview.mdx @@ -14,7 +14,7 @@ Dify supports three ways to distribute a plugin. They differ in how much vetting Before publishing, finish development and testing, and read the [Plugin Development Guidelines](/en/develop-plugin/publishing/standards/contributor-covenant-code-of-conduct). -## Choose a method +## Choose a Method @@ -42,13 +42,13 @@ Before publishing, finish development and testing, and read the [Plugin Developm Many developers ship to **GitHub first** for fast iteration, then submit to the **Marketplace** once the plugin is stable. The same `.difypkg` works for all three methods; only the distribution channel differs. -## Quick rules of thumb +## Quick Rules of Thumb - **Want broad reach and review?** Use the **Marketplace**. - **Want full control over releases and versioning?** Use **GitHub**. - **Private or one-off use?** Use a **Local File**. -## Related resources +## Related Resources diff --git a/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace.mdx b/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace.mdx index b596b50c0..a40ff8839 100644 --- a/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace.mdx +++ b/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace.mdx @@ -7,7 +7,7 @@ dimensions: standard_title: Release to Dify Marketplace language: en title: Publish to Dify Marketplace -description: Submit a plugin to the Dify Marketplace. Covers the pre-submission checklist, the 12 reviewer checks, the PR flow, and what happens after approval +description: Submit a plugin to the Dify Marketplace, from the pre-submission checklist and the 12 reviewer checks through the PR flow and what happens after approval --- The Marketplace is the official catalog of community-built and partner-built Dify plugins. Submitting your plugin here puts it one click away from every Dify user. @@ -16,7 +16,7 @@ Plugins are published by opening a Pull Request against [`langgenius/dify-plugin If you have not built a plugin yet, start with the [Tool Plugin walkthrough](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin). -## Before you submit +## Before You Submit The Dify reviewer runs an automated 12-check pre-flight on every PR. Most rejections are mechanical, and fixing them up front saves a review cycle. @@ -49,7 +49,7 @@ The Dify reviewer runs an automated 12-check pre-flight on every PR. Most reject -## Reviewer checklist +## Reviewer Checklist These are the exact checks the reviewer runs, in order. Treat this as your pre-flight before opening the PR. @@ -114,14 +114,14 @@ flowchart LR ``` -The first review usually lands within a week. If a reviewer doesn't respond in that window, they'll leave a comment explaining the delay. +The first review usually lands within a week. If it takes longer, the reviewer leaves a comment explaining the delay. Once merged to `main`, the plugin appears on [marketplace.dify.ai](https://marketplace.dify.ai/) automatically, with no separate publishing step. -## After approval +## After Approval You own the plugin from the merge onward: @@ -133,7 +133,7 @@ You own the plugin from the merge onward: While the Marketplace is in public beta, avoid breaking changes to plugins already in use. Add new fields instead of renaming existing ones; deprecate before removing. -## PR lifecycle +## PR Lifecycle | Status | What it means | What to do | | :--- | :--- | :--- | @@ -142,7 +142,7 @@ While the Marketplace is in public beta, avoid breaking changes to plugins alrea | **Stale (14 days idle)** | No response from you in two weeks | Reply on the PR to reset the timer; it can be reopened | | **Closed (30 days idle)** | Closed for inactivity | Open a fresh PR; the closed one can't be reopened | -## Frequently asked questions +## Frequently Asked Questions @@ -162,7 +162,7 @@ While the Marketplace is in public beta, avoid breaking changes to plugins alrea -## Related resources +## Related Resources diff --git a/en/develop-plugin/publishing/marketplace-listing/release-to-individual-github-repo.mdx b/en/develop-plugin/publishing/marketplace-listing/release-to-individual-github-repo.mdx index cf27430ab..b0cc12451 100644 --- a/en/develop-plugin/publishing/marketplace-listing/release-to-individual-github-repo.mdx +++ b/en/develop-plugin/publishing/marketplace-listing/release-to-individual-github-repo.mdx @@ -12,7 +12,7 @@ description: Distribute a Dify plugin from your own GitHub repository so users c Publishing through a personal GitHub repository lets you ship a plugin without going through Dify Marketplace review. Users install the plugin by entering your repo URL and selecting a release that contains a `.difypkg` asset. -**When to use this method** +This method fits when: - You want full control over versioning and the release cadence. - The plugin is open source and you want others to read, fork, or contribute to it. @@ -21,13 +21,13 @@ Publishing through a personal GitHub repository lets you ship a plugin without g For a comparison with other publishing methods, see the [Publishing Overview](/en/develop-plugin/publishing/marketplace-listing/release-overview). -### Prerequisites +## Prerequisites - A packaged plugin (`.difypkg` file). If you don't have one yet, see [Package as Local File and Share](/en/develop-plugin/publishing/marketplace-listing/release-by-file). - A GitHub account. - A Dify workspace where you (or your users) have permission to install plugins. -### Step 1: Create a GitHub repository +## Step 1: Create a GitHub Repository @@ -51,7 +51,7 @@ For a comparison with other publishing methods, see the [Publishing Overview](/e -### Step 2: Build the plugin package +## Step 2: Build the Plugin Package From the directory **above** your plugin project, run: @@ -61,7 +61,7 @@ dify plugin package ./your_plugin_project This produces `your_plugin_project.difypkg` in the current directory. -### Step 3: Publish a GitHub release +## Step 3: Publish a GitHub Release GitHub releases are how Dify discovers installable versions of your plugin. @@ -81,7 +81,7 @@ GitHub releases are how Dify discovers installable versions of your plugin. Repeat Steps 2 and 3 for each new version. Bump the `version` in `manifest.yaml` first, repackage, then create a new tag and release. -### Step 4: Install from your repository +## Step 4: Install from Your Repository Share your repository URL with users. They install it in Dify as follows: @@ -104,19 +104,19 @@ Share your repository URL with users. They install it in Dify as follows: The plugin appears on the user's Plugins page within seconds of clicking **Install**. Dify pulls the `.difypkg` from your GitHub release on demand. -### Troubleshooting +## Troubleshooting -- **`plugin_unique_identifier is not valid`**: the `author` field in `manifest.yaml` (and `provider/*.yaml`) doesn't match the GitHub handle that owns the repo. Update it, repackage, and re-release. -- **No versions appear in the install dialog**: the release has no `.difypkg` asset attached, or the repo has no releases yet. Open the release on GitHub and confirm the asset is listed under **Assets**. -- **Signature verification error**: self-hosted Dify instances may have signature verification enabled. See [Third-Party Signature Verification](/en/develop-plugin/publishing/standards/third-party-signature-verification) to sign your release, or see the [FAQ](/en/develop-plugin/publishing/faq/faq) for the bypass option. +- **`plugin_unique_identifier is not valid`**: The `author` field in `manifest.yaml` (and `provider/*.yaml`) doesn't match the GitHub handle that owns the repo. Update it, repackage, and re-release. +- **No versions appear in the install dialog**: The release has no `.difypkg` asset attached, or the repo has no releases yet. Open the release on GitHub and confirm the asset is listed under **Assets**. +- **Signature verification error**: Self-hosted Dify instances may have signature verification enabled. See [Third-Party Signature Verification](/en/develop-plugin/publishing/standards/third-party-signature-verification) to sign your release, or see the [FAQ](/en/develop-plugin/publishing/faq/faq) for the bypass option. ## Related Resources -- [Publishing Overview](/en/develop-plugin/publishing/marketplace-listing/release-overview) - Compare publishing methods -- [Package as Local File and Share](/en/develop-plugin/publishing/marketplace-listing/release-by-file) - Build a `.difypkg` package -- [Publish to Dify Marketplace](/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace) - Submit through the official marketplace -- [Third-Party Signature Verification](/en/develop-plugin/publishing/standards/third-party-signature-verification) - Sign packages for verified installs -- [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) - Manifest field reference +- [Publishing Overview](/en/develop-plugin/publishing/marketplace-listing/release-overview): Compare publishing methods. +- [Package as Local File and Share](/en/develop-plugin/publishing/marketplace-listing/release-by-file): Build a `.difypkg` package. +- [Publish to Dify Marketplace](/en/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace): Submit through the official marketplace. +- [Third-Party Signature Verification](/en/develop-plugin/publishing/standards/third-party-signature-verification): Sign packages for verified installs. +- [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications): Manifest field reference. {/* Contributing Section diff --git a/en/develop-plugin/publishing/standards/privacy-protection-guidelines.mdx b/en/develop-plugin/publishing/standards/privacy-protection-guidelines.mdx index e6382d6fc..b22de5a36 100644 --- a/en/develop-plugin/publishing/standards/privacy-protection-guidelines.mdx +++ b/en/develop-plugin/publishing/standards/privacy-protection-guidelines.mdx @@ -12,9 +12,7 @@ description: How to declare data collection and write the privacy policy require Every plugin submitted to the Dify Marketplace must be transparent about how it handles user data. This page tells you what to declare and how to write the policy reviewers expect. -The whole submission boils down to one question: - -> Does your plugin collect or transmit any user personal data, either directly or through a third-party service it calls? +The whole submission boils down to one question: does your plugin collect or transmit any user personal data, either directly or through a third-party service it calls? If yes, list the data types and link a privacy policy. If no, say so explicitly. @@ -22,11 +20,11 @@ If yes, list the data types and link a privacy policy. If no, say so explicitly. "Personal data" means any information that identifies a specific individual on its own or when combined with other data: anything that could locate, contact, or target a unique person. -## Identify the data your plugin handles +## Identify the Data Your Plugin Handles Walk through the three categories below. Anything you collect, store, log, or send to a third party must be declared. -### Direct identifiers +### Direct Identifiers - Full name, first name, last name - Email address @@ -34,7 +32,7 @@ Walk through the three categories below. Anything you collect, store, log, or se - Home address or other physical address - Government IDs (passport, driver's license, Social Security number, etc.) -### Indirect identifiers +### Indirect Identifiers - Device identifiers (IMEI, MAC address, device ID) - IP address @@ -45,7 +43,7 @@ Walk through the three categories below. Anything you collect, store, log, or se - Browsing history, purchase history - Health or financial information -### Combinable data +### Combinable Data Data that becomes identifying when joined with other data: @@ -53,13 +51,13 @@ Data that becomes identifying when joined with other data: - Occupation - Interests -### Third-party services count too +### Third-Party Services Count Too Your plugin is responsible for what the services it calls collect. If your plugin uses Slack, you must reference [Slack's privacy policy](https://slack.com/trust/privacy/privacy-policy) and disclose what Slack receives. Before submitting, read the privacy policy of every third-party API the plugin touches and make sure your declaration covers it. -## Write the privacy policy +## Write the Privacy Policy Your policy, either a `PRIVACY.md` in the plugin repository or a hosted URL, must cover: @@ -69,11 +67,11 @@ Your policy, either a `PRIVACY.md` in the plugin repository or a hosted URL, mus If you're unsure where to start, look at the privacy policy of any plugin published by the Dify team for a working template. -## Declare it in the manifest +## Declare It in the Manifest The privacy URL goes in the plugin manifest. See [General Specifications](/en/develop-plugin/features-and-specs/plugin-types/general-specifications) for the exact field. -## Common questions +## Common Questions @@ -97,7 +95,7 @@ The privacy URL goes in the plugin manifest. See [General Specifications](/en/de -## Related resources +## Related Resources - [Publishing Overview](/en/develop-plugin/publishing/marketplace-listing/release-overview) - [Plugin Development Guidelines](/en/develop-plugin/publishing/standards/contributor-covenant-code-of-conduct) diff --git a/en/develop-plugin/publishing/standards/third-party-signature-verification.mdx b/en/develop-plugin/publishing/standards/third-party-signature-verification.mdx index fe60f4c0a..61d031060 100644 --- a/en/develop-plugin/publishing/standards/third-party-signature-verification.mdx +++ b/en/develop-plugin/publishing/standards/third-party-signature-verification.mdx @@ -29,7 +29,7 @@ Two scenarios: The mechanics are the same in both cases: generate a key pair, sign with the private key, verify with the public key. -## Generate a key pair +## Generate a Key Pair ```bash dify signature generate -f your_key_pair @@ -46,7 +46,7 @@ Two files appear in the current directory: Guard the private key. Anyone who has it can sign plugins that pass verification on installations trusting your public key. -## Sign and verify a plugin +## Sign and Verify a Plugin @@ -69,7 +69,7 @@ Guard the private key. Anyone who has it can sign plugins that pass verification If you omit `-p`, `dify signature verify` checks against the Dify Marketplace public key. Any plugin not signed by Dify will fail verification in that mode. -## Enable verification on the daemon +## Enable Verification on the Daemon Admins install signed plugins by giving the plugin daemon a list of trusted public keys. @@ -117,7 +117,7 @@ Admins install signed plugins by giving the plugin daemon a list of trusted publ -## Related resources +## Related Resources - [Package as Local File and Share](/en/develop-plugin/publishing/marketplace-listing/release-by-file) - [Publish to Individual GitHub Repository](/en/develop-plugin/publishing/marketplace-listing/release-to-individual-github-repo) From d8a4980918b67729926568072a33290e84f9239f Mon Sep 17 00:00:00 2001 From: crazywoola <427733928@qq.com> Date: Wed, 10 Jun 2026 13:37:24 +0800 Subject: [PATCH 2/2] fix: update anchors to retitled tool-plugin headings Co-Authored-By: Claude Fable 5 --- .../dev-guides-and-walkthroughs/datasource-plugin.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin.mdx b/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin.mdx index 111c1a882..4c6985f3d 100644 --- a/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin.mdx +++ b/en/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin.mdx @@ -19,7 +19,7 @@ You should have a basic understanding of the knowledge pipeline and plugin devel Dify supports three types of data source plugins: web crawler, online document, and online drive. Each type corresponds to a different parent class, and the class that implements your plugin's functionality must inherit from it. - To learn how to inherit from a parent class to implement plugin functionality, see [Tool Plugin: Prepare Tool Code](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin#4-prepare-tool-code). + To learn how to inherit from a parent class to implement plugin functionality, see [Tool Plugin: Write the Tool Code](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin#4-write-the-tool-code). Each data source plugin type supports multiple data sources. For example: @@ -113,7 +113,7 @@ datasources: ``` - For more about creating a provider YAML file, see [Tool Plugin: Complete Third-Party Service Credentials](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin#2-complete-third-party-service-credentials). + For more about creating a provider YAML file, see [Tool Plugin: Add Third-Party Service Credentials](/en/develop-plugin/dev-guides-and-walkthroughs/tool-plugin#2-add-third-party-service-credentials).