Files
dify-docs/plugin-dev-en/0432-develop-flomo-plugin.mdx
2025-09-29 15:11:43 +08:00

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>