> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dify.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 10-Minute Guide to Building Dify Plugins

> Learn how to build a functional Dify plugin that connects with Flomo note-taking service in just 10 minutes

## 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 theme={null}
        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 theme={null}
        # 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 theme={null}
    dify version
    ```
  </Step>

  <Step title="Initialize a plugin project">
    Create a new plugin project using:

    ```bash theme={null}
    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 theme={null}
    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 theme={null}
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 theme={null}
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 theme={null}
  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 theme={null}
  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 theme={null}
  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 theme={null}
    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 theme={null}
    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 8: Package and distribute

When you're ready to share your plugin:

```bash theme={null}
dify plugin package ./
```

This creates a `plugin.difypkg` file you can upload to the Dify Marketplace.

## FAQ and Troubleshooting

<AccordionGroup title="Common issues and troubleshooting">
  <Accordion title="Plugin doesn't appear in debug mode">
    Make sure your `.env` file is properly configured and you're using the correct debug key.
  </Accordion>

  <Accordion title="API authentication errors">
    Double-check your Flomo API URL format. It should be in the form: `https://flomoapp.com/iwh/{token}/{secret}/`
  </Accordion>

  <Accordion title="Packaging fails">
    Ensure all required files are present and the manifest.yaml structure is valid.
  </Accordion>
</AccordionGroup>

## 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.

<CardGroup cols={2}>
  <Card title="Documentation" icon="book">
    Write your README.md in English (en\_US) describing functionality, setup, and usage examples
  </Card>

  <Card title="Localization" icon="language">
    Create additional README files like `readme/README_zh_Hans.md` for other languages
  </Card>
</CardGroup>

<CheckList>
  <CheckListItem id="privacy">
    Add a privacy policy (PRIVACY.md) if publishing your plugin
  </CheckListItem>

  <CheckListItem id="documentation">
    Include comprehensive examples in documentation
  </CheckListItem>

  <CheckListItem id="testing">
    Test thoroughly with various document sizes and formats
  </CheckListItem>
</CheckList>

***

[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)
