mirror of
https://github.com/langgenius/dify-docs.git
synced 2026-03-27 13:28:32 +07:00
335 lines
9.7 KiB
Plaintext
335 lines
9.7 KiB
Plaintext
---
|
|
title: '10-Minute Guide to Building Dify Plugins'
|
|
description: 'Learn how to build a functional Dify plugin that connects with Flomo note-taking service in just 10 minutes'
|
|
language: en
|
|
standard_title: 10-Minute Guide to Building Dify Plugins
|
|
---
|
|
|
|
## What you'll build
|
|
|
|
By the end of this guide, you'll have created a Dify plugin that:
|
|
|
|
- Connects to the Flomo note-taking API
|
|
- Allows users to save notes from AI conversations directly to Flomo
|
|
- Handles authentication and error states properly
|
|
- Is ready for distribution in the Dify Marketplace
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Time required" icon="clock">
|
|
10 minutes
|
|
</Card>
|
|
<Card title="Prerequisites" icon="list-check">
|
|
Basic Python knowledge and a Flomo account
|
|
</Card>
|
|
</CardGroup>
|
|
|
|
## Step 1: Install the Dify CLI and create a project
|
|
|
|
<Steps>
|
|
<Step title="Install Dify CLI">
|
|
<Tabs>
|
|
<Tab title="Mac">
|
|
```bash
|
|
brew tap langgenius/dify
|
|
brew install dify
|
|
```
|
|
</Tab>
|
|
<Tab title="Linux">
|
|
Get the latest Dify CLI from the [Dify GitHub releases page](https://github.com/langgenius/dify-plugin-daemon/releases)
|
|
|
|
```bash
|
|
# Download appropriate version
|
|
chmod +x dify-plugin-linux-amd64
|
|
mv dify-plugin-linux-amd64 dify
|
|
sudo mv dify /usr/local/bin/
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
Verify installation:
|
|
```bash
|
|
dify version
|
|
```
|
|
</Step>
|
|
|
|
<Step title="Initialize a plugin project">
|
|
Create a new plugin project using:
|
|
|
|
```bash
|
|
dify plugin init
|
|
```
|
|
|
|
Follow the prompts to set up your plugin:
|
|
- Name it "flomo"
|
|
- Select "tool" as the plugin type
|
|
- Complete other required fields
|
|
</Step>
|
|
|
|
<Step title="Navigate to the project">
|
|
```bash
|
|
cd flomo
|
|
```
|
|
|
|
This will create the basic structure for your plugin with all necessary files.
|
|
</Step>
|
|
</Steps>
|
|
|
|
## Step 2: Define your plugin manifest
|
|
|
|
<Info>
|
|
The manifest.yaml file defines your plugin's metadata, permissions, and capabilities.
|
|
</Info>
|
|
|
|
Create a `manifest.yaml` file:
|
|
|
|
```yaml
|
|
version: 0.0.4
|
|
type: plugin
|
|
author: yourname
|
|
label:
|
|
en_US: Flomo
|
|
zh_Hans: Flomo 浮墨笔记
|
|
created_at: "2023-10-01T00:00:00Z"
|
|
icon: icon.png
|
|
|
|
resource:
|
|
memory: 67108864 # 64MB
|
|
permission:
|
|
storage:
|
|
enabled: false
|
|
|
|
plugins:
|
|
tools:
|
|
- flomo.yaml
|
|
|
|
meta:
|
|
version: 0.0.1
|
|
arch:
|
|
- amd64
|
|
- arm64
|
|
runner:
|
|
language: python
|
|
version: 3.12
|
|
entrypoint: main
|
|
```
|
|
|
|
## Step 3: Create the tool definition
|
|
|
|
Create a `flomo.yaml` file to define your tool interface:
|
|
|
|
```yaml
|
|
identity:
|
|
author: yourname
|
|
name: flomo
|
|
label:
|
|
en_US: Flomo Note
|
|
zh_Hans: Flomo 浮墨笔记
|
|
description:
|
|
human:
|
|
en_US: Add notes to your Flomo account directly from Dify.
|
|
zh_Hans: 直接从Dify添加笔记到您的Flomo账户。
|
|
llm: >
|
|
A tool that allows users to save notes to Flomo. Use this tool when users want to save important information from the conversation. The tool accepts a 'content' parameter that contains the text to be saved as a note.
|
|
credential_schema:
|
|
api_url:
|
|
type: string
|
|
required: true
|
|
label:
|
|
en_US: API URL
|
|
zh_Hans: API URL
|
|
human_description:
|
|
en_US: Flomo API URL from your Flomo account settings.
|
|
zh_Hans: 从您的Flomo账户设置中获取的API URL。
|
|
tool_schema:
|
|
content:
|
|
type: string
|
|
required: true
|
|
label:
|
|
en_US: Note Content
|
|
zh_Hans: 笔记内容
|
|
human_description:
|
|
en_US: Content to save as a note in Flomo.
|
|
zh_Hans: 要保存为Flomo笔记的内容。
|
|
```
|
|
|
|
## Step 4: Implement core utility functions
|
|
|
|
Create a utility module in `utils/flomo_utils.py` for API interaction:
|
|
|
|
<CodeGroup>
|
|
```python utils/flomo_utils.py
|
|
import requests
|
|
|
|
def send_flomo_note(api_url: str, content: str) -> None:
|
|
"""
|
|
Send a note to Flomo via the API URL. Raises requests.RequestException on network errors,
|
|
and ValueError on invalid status codes or input.
|
|
"""
|
|
api_url = api_url.strip()
|
|
if not api_url:
|
|
raise ValueError("API URL is required and cannot be empty.")
|
|
if not api_url.startswith('https://flomoapp.com/iwh/'):
|
|
raise ValueError(
|
|
"API URL should be in the format: https://flomoapp.com/iwh/{token}/{secret}/"
|
|
)
|
|
if not content:
|
|
raise ValueError("Content cannot be empty.")
|
|
|
|
headers = {'Content-Type': 'application/json'}
|
|
response = requests.post(api_url, json={"content": content}, headers=headers, timeout=10)
|
|
|
|
if response.status_code != 200:
|
|
raise ValueError(f"API URL is not valid. Received status code: {response.status_code}")
|
|
```
|
|
</CodeGroup>
|
|
|
|
## Step 5: Implement the Tool Provider
|
|
|
|
The Tool Provider handles credential validation. Create `provider/flomo.py`:
|
|
|
|
<CodeGroup>
|
|
```python provider/flomo.py
|
|
from typing import Any
|
|
from dify_plugin import ToolProvider
|
|
from dify_plugin.errors.tool import ToolProviderCredentialValidationError
|
|
import requests
|
|
from utils.flomo_utils import send_flomo_note
|
|
|
|
class FlomoProvider(ToolProvider):
|
|
def _validate_credentials(self, credentials: dict[str, Any]) -> None:
|
|
try:
|
|
api_url = credentials.get('api_url', '').strip()
|
|
# Use utility for validation and sending test note
|
|
send_flomo_note(api_url, "Hello, #flomo https://flomoapp.com")
|
|
except ValueError as e:
|
|
raise ToolProviderCredentialValidationError(str(e))
|
|
except requests.RequestException as e:
|
|
raise ToolProviderCredentialValidationError(f"Connection error: {str(e)}")
|
|
```
|
|
</CodeGroup>
|
|
|
|
## Step 6: Implement the Tool
|
|
|
|
The Tool class handles actual API calls when the user invokes the plugin. Create `tools/flomo.py`:
|
|
|
|
<CodeGroup>
|
|
```python tools/flomo.py
|
|
from collections.abc import Generator
|
|
from typing import Any
|
|
from dify_plugin import Tool
|
|
from dify_plugin.entities.tool import ToolInvokeMessage
|
|
import requests
|
|
from utils.flomo_utils import send_flomo_note
|
|
|
|
class FlomoTool(Tool):
|
|
def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:
|
|
content = tool_parameters.get("content", "")
|
|
api_url = self.runtime.credentials.get("api_url", "")
|
|
|
|
try:
|
|
send_flomo_note(api_url, content)
|
|
except ValueError as e:
|
|
yield self.create_text_message(str(e))
|
|
return
|
|
except requests.RequestException as e:
|
|
yield self.create_text_message(f"Connection error: {str(e)}")
|
|
return
|
|
|
|
# Return success message and structured data
|
|
yield self.create_text_message(
|
|
"Note created successfully! Your content has been sent to Flomo."
|
|
)
|
|
yield self.create_json_message({
|
|
"status": "success",
|
|
"content": content,
|
|
})
|
|
```
|
|
</CodeGroup>
|
|
|
|
<Warning>
|
|
Always handle exceptions gracefully and return user-friendly error messages. Remember that your plugin represents your brand in the Dify ecosystem.
|
|
</Warning>
|
|
|
|
## Step 7: Test your plugin
|
|
|
|
<Steps>
|
|
<Step title="Set up debug environment">
|
|
Copy the example environment file:
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
Edit the `.env` file with your Dify environment details:
|
|
```
|
|
INSTALL_METHOD=remote
|
|
REMOTE_INSTALL_HOST=debug-plugin.dify.dev
|
|
REMOTE_INSTALL_PORT=5003
|
|
REMOTE_INSTALL_KEY=your_debug_key
|
|
```
|
|
|
|
You can find your debug key and host in the Dify dashboard: click the "Plugins" icon in the top right corner, then click the debug icon. In the pop-up window, copy the "API Key" and "Host Address".
|
|
</Step>
|
|
|
|
<Step title="Install dependencies and run">
|
|
```bash
|
|
pip install -r requirements.txt
|
|
python -m main
|
|
```
|
|
|
|
Your plugin will connect to your Dify instance in debug mode.
|
|
</Step>
|
|
|
|
<Step title="Test functionality">
|
|
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.
|
|
</Step>
|
|
</Steps>
|
|
|
|
## Step 9: Package and distribute
|
|
|
|
When you're ready to share your plugin:
|
|
|
|
```bash
|
|
dify plugin package ./
|
|
```
|
|
|
|
This creates a `plugin.difypkg` file you can upload to the Dify Marketplace.
|
|
|
|
## Next steps
|
|
|
|
<CardGroup cols={3}>
|
|
<Card title="Add more features" icon="plus">
|
|
Consider adding hashtag support, note search, or other Flomo API features
|
|
</Card>
|
|
<Card title="Enhance error handling" icon="shield">
|
|
Add more detailed error states and recovery flows
|
|
</Card>
|
|
<Card title="Automate releases" icon="rocket">
|
|
Configure GitHub Actions for automated package and PR creation
|
|
</Card>
|
|
</CardGroup>
|
|
|
|
<Accordion title="Common issues and troubleshooting">
|
|
<AccordionItem title="Plugin doesn't appear in debug mode">
|
|
Make sure your `.env` file is properly configured and you're using the correct debug key.
|
|
</AccordionItem>
|
|
|
|
<AccordionItem title="API authentication errors">
|
|
Double-check your Flomo API URL format. It should be in the form: `https://flomoapp.com/iwh/{token}/{secret}/`
|
|
</AccordionItem>
|
|
|
|
<AccordionItem title="Packaging fails">
|
|
Ensure all required files are present and the manifest.yaml structure is valid.
|
|
</AccordionItem>
|
|
</Accordion>
|
|
|
|
## 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.
|
|
|
|
<Note>
|
|
Remember to add a privacy policy if you plan to publish your plugin. You can create a simple PRIVACY.md file referencing Flomo's privacy policy.
|
|
Remember to write the README.md file in English (en_US) to describe your plugin's functionality, setup instructions, and usage examples.
|
|
For other languages, you can create additional README files like `readme/README_zh_Hans.md` for Simplified Chinese.
|
|
</Note>
|