Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    skilzy-ai

    dify-tool-developer

    skilzy-ai/dify-tool-developer
    Coding
    2
    5 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Guide AI agents through Dify tool plugin development with mandatory documentation loading and direct CLI usage. Use when creating Dify tool plugins or extending Dify with custom tools.

    SKILL.md

    Dify Tool Plugin Developer

    Guide AI agents through complete Dify tool plugin development using official documentation and direct CLI commands.

    When to Use This Skill

    Activate this skill when user:

    • Mentions "Dify plugin", "Dify tool", or "Dify development"
    • Wants to create custom Dify functionality
    • Needs to extend Dify with custom tools
    • Asks about developing for Dify
    • Wants to build API integrations for Dify

    Agent Responsibilities

    ⚠️ IMPORTANT: You (the AI agent) are responsible for:

    • ✅ Creating and editing all files yourself (YAML, Python, etc.)
    • ✅ Running all CLI commands directly
    • ✅ Implementing the code based on loaded documentation
    • ✅ Testing the plugin with remote debugging
    • ✅ Packaging the final .difypkg

    DO NOT:

    • ❌ Just tell the user how to do these tasks
    • ❌ Provide instructions without executing
    • ❌ Guide the user to run commands themselves

    YOU execute everything. The user provides requirements and confirms results.

    Critical Rule: MANDATORY Documentation Loading

    ⚠️ BEFORE writing ANY code, you MUST load the referenced official documentation

    The Dify plugin framework has STRICT requirements:

    • Exact Python class structures with specific method signatures
    • Precise YAML formatting and required fields
    • Strict import patterns that must be followed exactly
    • Specific parameter handling conventions

    DO NOT guess, assume, or improvise. ALWAYS fetch and read the official documentation first.

    Documentation Fetching

    To fetch official Dify documentation, use curl:

    curl -s https://docs.dify.ai/plugin-dev-en/[doc-filename].md
    

    Available Documentation (see references/doc-map.md for complete details on what each contains):

    • 0221-initialize-development-tools.md - CLI installation and setup
    • 0222-tool-plugin.md - Complete tool plugin development guide
    • 0222-debugging-logs.md - Logging and debugging techniques
    • 0222-tool-oauth.md - OAuth authentication implementation

    MANDATORY Loading Points:

    • Before Phase 2 (initialization): Load 0222-tool-plugin.md
    • Before Phase 3 (implementation): Re-load 0222-tool-plugin.md (Developing section)
    • If OAuth needed: Load 0222-tool-oauth.md
    • During debugging: Load 0222-debugging-logs.md

    Development Workflow

    Follow this 5-phase workflow in sequence. Do not skip phases or documentation loading.

    PHASE 1: Setup & Planning

    FIRST: Load references/doc-map.md to understand the documentation structure

    Gather Requirements - Ask the user:

    1. "What functionality should this tool provide?"
    2. "Does it need to call external APIs? If so, which APIs?"
    3. "Does it require OAuth authentication? (e.g., GitHub, Google, Slack)"
    4. "What inputs should users provide to this tool?"
    5. "What outputs should the tool return?"

    Determine Requirements:

    • Tool name (lowercase, hyphens only)
    • Tool functionality description
    • Required permissions (network access, storage, etc.)
    • OAuth requirement (yes/no)
    • Python package dependencies (requests, etc.)
    • External API endpoints

    Verify Dify CLI Installation:

    dify version
    

    If the CLI is not installed or returns an error:

    1. LOAD: https://docs.dify.ai/plugin-dev-en/0221-initialize-development-tools.md
    2. Follow the installation instructions for the user's operating system
    3. Verify installation with dify version

    Option 2: Use Helper Script (Recommended)

    For automated installation, use the provided helper script:

    python scripts/install_cli.py
    

    This script will:

    • Detect your operating system and architecture automatically
    • Download the latest Dify CLI version from GitHub
    • Make the binary executable
    • Verify the installation

    Optional flags:

    # Install specific version
    python scripts/install_cli.py --version 0.4.0
    
    # Install to custom directory
    python scripts/install_cli.py --path ~/bin
    
    # Both
    python scripts/install_cli.py --version 0.4.0 --path /usr/local/bin
    

    The script provides:

    • ✅ Automatic platform detection (macOS/Linux/Windows, AMD64/ARM64)
    • ✅ Latest version detection from GitHub API
    • ✅ Progress indicator during download
    • ✅ Automatic executable permissions
    • ✅ Installation verification
    • ✅ PATH setup instructions

    PHASE 1.5: Load Required Documentation (MANDATORY)

    ⚠️ BEFORE writing ANY code, load the specific documentation needed for the planned requirements.

    Based on the requirements gathered in Phase 1, determine which documentation to load:

    Required Documentation (ALWAYS LOAD)

    1. Tool Plugin Guide (MANDATORY for all plugins):

    curl -s https://docs.dify.ai/plugin-dev-en/0222-tool-plugin.md
    

    Read sections:

    • File structure requirements
    • YAML configuration syntax
    • Tool class implementation patterns
    • Parameter handling
    • Message types

    2. Debugging Guide (MANDATORY for testing):

    curl -s https://docs.dify.ai/plugin-dev-en/0222-debugging-logs.md
    

    Conditional Documentation (Load if needed)

    3. OAuth Guide (IF OAuth authentication required):

    curl -s https://docs.dify.ai/plugin-dev-en/0222-tool-oauth.md
    

    Load this if the requirements include:

    • GitHub integration
    • Google services integration
    • Slack integration
    • Any OAuth-based authentication

    4. Initialize Tools (IF CLI not installed):

    curl -s https://docs.dify.ai/plugin-dev-en/0221-initialize-development-tools.md
    

    How to Determine What to Load

    Based on Phase 1 requirements:

    Requirement Documentation to Load
    Basic tool functionality tool-plugin.md (always)
    API integration tool-plugin.md + debugging-logs.md
    OAuth authentication tool-plugin.md + tool-oauth.md + debugging-logs.md
    Complex logic tool-plugin.md + debugging-logs.md + examples.md
    CLI installation needed initialize-development-tools.md

    ⚠️ DO NOT skip this phase. Loading the wrong documentation or insufficient documentation will result in incorrect code with syntax errors.

    After loading, confirm:

    • Understand the exact YAML structure required
    • Know the Tool class pattern to follow
    • Clear on parameter handling methods
    • Understand message types available
    • Know OAuth implementation steps (if applicable)

    Only proceed to Phase 2 after loading and understanding the required documentation.

    PHASE 2: Initialize Project

    ⚠️ MANDATORY: Load the tool-plugin.md documentation BEFORE proceeding

    Fetch Documentation:

    curl -s https://docs.dify.ai/plugin-dev-en/0222-tool-plugin.md
    

    Read These Sections:

    • "Prerequisites"
    • "Creating a New Project"
    • "Choosing Plugin Type and Template"

    Initialize the Plugin:

    Use the dify plugin init command with appropriate flags:

    dify plugin init \
      --name "your-tool-name" \
      --author "author-name" \
      --description "Clear, concise tool description" \
      --category tool \
      --language python \
      --min-dify-version "1.9.0" \
      --allow-network \      # Include if API access needed
      --allow-storage \      # Include if storage needed
      --quick                 # Skip interactive prompts
    

    Available Permission Flags:

    • --allow-network - For external API calls
    • --allow-storage - For persistent data storage
    • --allow-tool - To invoke other Dify tools
    • --allow-llm - To invoke language models
    • --storage-size <bytes> - Specify storage limit

    Verify Project Structure:

    ls -la your-tool-name/
    

    Expected files and directories:

    • manifest.yaml - Plugin manifest configuration
    • provider/ - Provider definitions and credential validation
    • tools/ - Tool implementations (YAML + Python files)
    • main.py - Plugin entry point
    • requirements.txt - Python dependencies
    • .env.example - Environment variables template

    If any files are missing, re-run the init command or check for errors.


    PHASE 3: Implement Tool

    ⚠️ MANDATORY: Re-read the tool-plugin.md "Developing the Tool Plugin" section

    This section contains CRITICAL information:

    • Exact file structure requirements
    • YAML syntax for tools/*.yaml
    • Tool class structure for tools/*.py
    • Parameter handling patterns
    • Message type formats and usage
    • Import statement patterns

    Fetch Documentation Again:

    curl -s https://docs.dify.ai/plugin-dev-en/0222-tool-plugin.md
    # Focus on section "Developing the Tool Plugin"
    

    If OAuth is Required:

    ⚠️ MANDATORY: Load the complete OAuth documentation

    curl -s https://docs.dify.ai/plugin-dev-en/0222-tool-oauth.md
    

    Read all sections:

    • Background (OAuth flows explained)
    • Define OAuth Schema in Provider Manifest
    • Complete Required OAuth Methods in Tool Provider
    • Access Tokens in Your Tools
    • Specify the Correct Versions

    Implementation Steps:

    1. Edit tools/*.yaml

    Follow the exact YAML structure from the documentation:

    identity:
      name: tool-name                    # Must match filename
      author: author-name
      label:
        en_US: Tool Display Name
        zh_Hans: 工具显示名称           # Add i18n translations
        pt_BR: Nome de Exibição
        ja_JP: ツール表示名
    description:
      human:
        en_US: Description for human users
        zh_Hans: 人类用户的描述
      llm: Detailed description for AI models to understand when to use this tool
    parameters:
      - name: parameter_name
        type: string                     # string, number, boolean, file
        required: true                   # or false for optional
        label:
          en_US: Parameter Display Name
          zh_Hans: 参数显示名称
        human_description:
          en_US: Description for users
          zh_Hans: 用户描述
        llm_description: Detailed parameter description for AI models
        form: llm                        # llm (AI extracts) or form (UI config)
    
      # Add more parameters as needed
    
    extra:
      python:
        source: tools/tool-name.py       # Must match Python filename
    

    Parameter Types:

    • string - Text input
    • number - Numeric input
    • boolean - True/false
    • file - File upload

    Form Types:

    • llm - AI extracts from user input (recommended for conversational use)
    • form - User configures in UI (for admin settings)

    2. Edit tools/*.py

    Follow the exact Tool class pattern from the documentation:

    from collections.abc import Generator
    from typing import Any
    
    from dify_plugin import Tool
    from dify_plugin.entities.tool import ToolInvokeMessage
    
    class YourToolName(Tool):
        """
        Tool for [description of what this tool does]
        """
    
        def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:
            """
            Invoke the tool with given parameters
    
            Args:
                tool_parameters: Dictionary of tool parameters
    
            Yields:
                ToolInvokeMessage: Messages to return to the user
            """
            try:
                # 1. Extract required parameters (use .get() with default)
                required_param = tool_parameters.get("param_name", "")
    
                # 2. Extract optional parameters (use .get() - returns None if missing)
                optional_param = tool_parameters.get("optional_param")
    
                # 3. Validate required parameters
                if not required_param:
                    yield self.create_text_message("Error: Required parameter 'param_name' is missing.")
                    return
    
                # 4. Implement your business logic here
                result = self._process_data(required_param, optional_param)
    
                # 5. Return results using appropriate message types
    
                # Text message (always visible to user)
                yield self.create_text_message(f"Result: {result}")
    
                # JSON message (structured data)
                yield self.create_json_message({
                    "status": "success",
                    "data": result
                })
    
                # Variable message (for workflow use)
                yield self.create_variable_message("result_variable", result)
    
                # Link message (clickable URLs)
                # yield self.create_link_message("https://example.com/result")
    
            except Exception as e:
                # Always include error handling
                yield self.create_text_message(f"Error: {str(e)}")
    
        def _process_data(self, required_param: str, optional_param: str = None) -> Any:
            """
            Helper method for business logic
    
            Args:
                required_param: Required input parameter
                optional_param: Optional input parameter
    
            Returns:
                Processed result
            """
            # Implement your logic here
    
            # Handle optional parameters
            if optional_param:
                result = f"Processed with both: {required_param}, {optional_param}"
            else:
                result = f"Processed with required only: {required_param}"
    
            return result
    

    ⚠️ CRITICAL RULES FROM DOCUMENTATION:

    1. ONE Tool class per .py file - Multiple classes will cause errors
    2. Exact method signature: _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]
    3. Use .get() for parameters - Prevents KeyError exceptions
    4. Return with yield - Not return
    5. Import from correct modules - Match documentation exactly

    Message Types Available:

    • create_text_message(text) - Display text to user
    • create_json_message(dict) - Return structured data
    • create_link_message(url) - Return clickable link
    • create_variable_message(name, value) - Set workflow variable
    • create_blob_message(data, name) - Return binary data/files

    3. Edit provider/*.yaml

    Add the new tool to the provider's tool list:

    identity:
      author: author-name
      name: plugin-name
      label:
        en_US: Plugin Display Name
        zh_Hans: 插件显示名称
      description:
        en_US: Plugin description
        zh_Hans: 插件描述
      icon: icon.svg
    
    # Only include if API keys or credentials are needed
    credentials_for_provider:
      api_key:
        type: secret-input
        required: true
        label:
          en_US: API Key
          zh_Hans: API 密钥
        placeholder:
          en_US: Enter your API key
          zh_Hans: 输入您的 API 密钥
        help:
          en_US: Get your API key from https://example.com/api-keys
          zh_Hans: 从 https://example.com/api-keys 获取您的 API 密钥
        url: https://example.com/api-keys
    
    tools:
      - tools/your-tool-name.yaml    # Add your tool here, it can be multiple tools in a single plugin
    
    extra:
      python:
        source: provider/plugin-name.py
    

    4. Edit provider/*.py

    If credentials are needed, implement validation:

    from typing import Any
    from dify_plugin.entities.tool import ToolProviderCredentials
    
    class YourPluginProvider:
        def _validate_credentials(self, credentials: dict[str, Any]) -> ToolProviderCredentials:
            """
            Validate provider credentials
    
            Args:
                credentials: Dictionary of credentials to validate
    
            Returns:
                ToolProviderCredentials object
    
            Raises:
                ToolProviderCredentialValidationError: If validation fails
            """
            try:
                # Extract credentials
                api_key = credentials.get("api_key")
    
                if not api_key:
                    raise Exception("API key is required")
    
                # Validate by making a test API call
                # import requests
                # response = requests.get(
                #     "https://api.example.com/validate",
                #     headers={"Authorization": f"Bearer {api_key}"}
                # )
                # if response.status_code != 200:
                #     raise Exception("Invalid API key")
    
                return ToolProviderCredentials(credentials=credentials)
    
            except Exception as e:
                raise ToolProviderCredentialValidationError(str(e))
    

    5. Update manifest.yaml

    Complete all internationalization fields and metadata:

    version: 0.0.1 # bump this for every new version 
    type: plugin
    author: author-name
    name: plugin-name
    label:
      en_US: Plugin Display Name
      zh_Hans: 插件显示名称
      pt_BR: Nome de Exibição do Plugin
      ja_JP: プラグイン表示名
    description:
      en_US: Detailed description of what this plugin does
      zh_Hans: 该插件功能的详细描述
      pt_BR: Descrição detalhada do que este plugin faz
      ja_JP: このプラグインの機能の詳細な説明
    icon: icon.svg
    resource:
      memory: 268435456  # 256MB
      permission:
        network:
          enabled: true  # If API access needed
        storage:
          enabled: false
          size: 0
    plugins:
      tools:
        - provider/plugin-name.yaml
    meta:
      version: 0.0.1
      arch:
        - amd64
        - arm64
      runner:
        language: python
        version: "3.12"
        entrypoint: main
      minimum_dify_version: 1.9.0
    created_at: 2025-11-04T00:00:00.000000+00:00
    privacy: PRIVACY.md
    

    6. Update requirements.txt

    Add any Python package dependencies:

    dify_plugin>=0.0.1 # you must use the dify_plugin version that the CLI added when initialized. 
    requests>=2.31.0
    # Add other dependencies as needed
    

    PHASE 4: Test & Debug

    Load Debugging Documentation:

    curl -s https://docs.dify.ai/plugin-dev-en/0222-debugging-logs.md
    

    Add Logging to Your Tool:

    According to the documentation, add logging imports and setup:

    import logging
    from dify_plugin.handlers import DifyPluginLogHandler
    
    # Set up logging
    logger = logging.getLogger(__name__)
    logger.addHandler(DifyPluginLogHandler())
    
    class YourTool(Tool):
        def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:
            logger.info(f"Tool invoked with parameters: {tool_parameters}")
    
            # Your implementation...
    
            logger.debug(f"Processing result: {result}")
    
            yield self.create_text_message(result)
    

    PHASE 4.5: Remote Testing with Debug Key (MANDATORY Before Packaging)

    ⚠️ DO NOT PACKAGE without completing this phase.

    This phase verifies the plugin works with a real Dify instance before distribution.

    Objectives

    • Test plugin with actual Dify remote host
    • Verify functionality with debug key
    • Catch integration issues before packaging
    • Ensure proper logging and error handling

    Prerequisites

    Load debugging documentation:

    curl -s https://docs.dify.ai/plugin-dev-en/0222-debugging-logs.md
    

    Steps

    1. Request Dify Remote Connection Details

    ASK the user for remote testing connection:

    "To test this plugin with your Dify instance, I need:"
    
    1. REMOTE_INSTALL_URL - e.g., https://your-dify.com or http://localhost:5003
    2. Port (if not default) - usually 5003
    3. REMOTE_INSTALL_KEY - get from Dify instance developer settings
    
    Do you have a Dify instance available for testing?
    

    If user doesn't have a Dify instance:

    • Explain they can use local Dify installation
    • Guide to set up local Dify (if needed)
    • Or note that testing will be limited to code validation only

    2. Configure Environment

    Create/update .env file with remote connection:

    cd your-tool-directory
    
    cat > .env << EOF
    INSTALL_METHOD=remote
    REMOTE_INSTALL_URL=debug.dify.ai:5003 # or user provided host
    REMOTE_INSTALL_KEY=********-****-****-****-************
    EOF
    

    3. Start Plugin in Debug Mode

    Run the plugin connected to remote host:

    cd your-tool-directory
    python -m main
    

    Expected console output:

    INFO: Plugin loaded successfully
    INFO: Connected to Dify remote host: https://your-dify-instance.com
    INFO: Registered tools: [tool-name]
    INFO: Waiting for invocations...
    

    If errors appear:

    • Check DIFY_REMOTE_HOST is accessible
    • Verify DIFY_DEBUG_KEY is correct
    • Check network connectivity
    • Review error messages carefully

    4. Test Tool Invocation from Dify

    In Dify UI:

    1. Go to Tools section
    2. Find your plugin (should appear automatically)
    3. Try invoking the tool with test inputs
    4. Observe results

    In console (watch logs):

    INFO: Tool invoked: your-tool-name
    DEBUG: Parameters: {"param1": "value1"}
    DEBUG: Processing...
    DEBUG: API call successful
    INFO: Returned result to Dify
    

    5. Test All Scenarios

    Run comprehensive tests:

    Test Case 1: Valid Input

    Input: Normal, expected parameters
    Expected: Success, correct output
    

    Test Case 2: Missing Required Parameter

    Input: Omit required parameter
    Expected: Error message, graceful handling
    

    Test Case 3: Invalid Input

    Input: Wrong type or format
    Expected: Validation error, helpful message
    

    Test Case 4: API Integration (if applicable)

    Input: Valid request requiring API call
    Expected: Successful API call, correct data returned
    

    Test Case 5: Error Conditions

    Input: Trigger expected errors (API timeout, invalid credentials, etc.)
    Expected: Proper error handling, helpful messages
    

    Test Case 6: OAuth Flow (if applicable)

    Action: Complete OAuth authorization
    Expected: Token received, API calls work with token
    

    Expected Output:

    • Plugin should start without errors
    • You should see log output
    • Tool should be ready to receive invocations
    • Guide the user to test it in the dify environment while the debug script runs.

    If Errors Occur:

    1. LOAD references/troubleshooting.md
    2. Find the error pattern
    3. Apply the documented solution
    4. Re-test

    Common Errors:

    Error Cause Solution
    Multiple subclasses of Tool in file.py Multiple Tool classes in one file Keep only one Tool class per .py file, move others to new files
    ImportError: cannot import name 'X' Import name doesn't match definition Check spelling, case, underscores in import statements
    KeyError: 'parameter_name' Parameter accessed without checking Use .get() method: param = tool_parameters.get("name", "")
    ToolProviderCredentialValidationError Credential validation failed Check API key format, test API endpoint, verify credentials

    Debug Checklist:

    • One Tool class per .py file
    • Exact import statements from docs
    • Using .get() for all parameters
    • Method signature matches docs exactly
    • YAML files have correct syntax
    • All required fields present in YAML
    • Credentials properly validated

    6. Verify Debug Logging

    Check that logs show:

    • Tool invocation with parameters
    • Processing steps
    • API calls (without sensitive data)
    • Results
    • Any errors with context

    Example good logging:

    logger.info(f"Tool invoked: {tool_name}")
    logger.debug(f"Parameters: {tool_parameters}")
    logger.debug("Calling API endpoint...")
    logger.debug(f"API response status: {response.status_code}")
    logger.info("Successfully processed request")
    

    7. Debug Issues

    If tool doesn't work as expected:

    1. Check console logs for errors
    2. Verify parameters are extracted correctly
    3. Test API calls independently
    4. Check credential validation
    5. Load references/troubleshooting.md for common issues

    Common remote testing issues:

    Issue Cause Solution
    Plugin doesn't appear Registration failed Check manifest.yaml, restart plugin
    Connection refused Wrong host URL Verify DIFY_REMOTE_HOST
    Unauthorized Invalid debug key Check DIFY_DEBUG_KEY
    Tool fails Parameter handling Verify .get() usage, check logs
    API errors Credential issues Test API key separately

    8. User Confirmation

    Before proceeding to packaging, ask user:

    "I've tested the plugin with your Dify instance. Results:
    
    ✅ Plugin loaded successfully
    ✅ Tool appears in Dify UI
    ✅ Test invocations working
    ✅ [List specific test results]
    
    Does everything work as expected? Any issues or adjustments needed?"
    

    Wait for user confirmation before packaging.

    4. Verify requirements.txt Contains Latest dify_plugin

    ⚠️ CRITICAL CHECK: Verify the dify_plugin version that CLI generated.

    The Dify CLI always creates requirements.txt with the latest dify_plugin version.

    cat your-tool-name/requirements.txt
    

    Check what version was generated:

    dify_plugin>=X.X.X
    

    DO NOT override this version. The CLI uses the latest compatible version.

    Note the version for reference:

    • This is the version your plugin will use
    • Keep this version in requirements.txt
    • Only add additional dependencies you need

    Example:

    dify_plugin>=2.4.2    # Generated by CLI - KEEP THIS
    requests>=2.31.0       # Add if you need requests
    pyyaml>=6.0           # Add if you need yaml
    

    Success Criteria (All Must Pass)

    • Plugin connects to remote Dify instance
    • Debug key configured and accepted
    • Tool appears in Dify UI
    • Tool can be invoked successfully
    • All test scenarios pass
    • Logs show clean execution
    • No errors in remote testing
    • User confirms functionality correct
    • Ready to package

    ⚠️ If ANY criterion fails:

    • DO NOT proceed to packaging
    • Debug the issue using troubleshooting.md
    • Fix and re-test
    • Only package when ALL tests pass

    PHASE 5: Package & Publish

    Load Packaging Documentation:

    curl -s https://docs.dify.ai/plugin-dev-en/0222-tool-plugin.md
    # Read the "Packaging the Plugin" section
    

    Package the Plugin:

    dify plugin package ./your-tool-directory
    

    This creates a .difypkg file in the current directory.

    Expected Output:

    ✓ plugin packaged successfully, output path: your-tool-name.difypkg
    

    Verify Package:

    ls -lh *.difypkg
    

    The file should exist and have a reasonable size (typically 10-100 KB for simple plugins).

    Publishing (Optional):

    If the user wants to publish to the Dify marketplace:

    1. Visit the Dify plugin marketplace
    2. Create an account if needed
    3. Upload the .difypkg file
    4. Fill in marketplace metadata
    5. Submit for review

    Guide the user through this process if requested.


    OAuth Implementation Guide

    If the tool requires OAuth authentication (e.g., GitHub, Google, Slack):

    ⚠️ MANDATORY: Load the complete OAuth documentation BEFORE implementing

    curl -s https://docs.dify.ai/plugin-dev-en/0222-tool-oauth.md
    

    OAuth Implementation Steps:

    1. Define OAuth Schema in provider/*.yaml:
    oauth_schema:
      client:
        - name: client_id
          type: string
          required: true
          label:
            en_US: Client ID
        - name: client_secret
          type: secret-input
          required: true
          label:
            en_US: Client Secret
      authorization:
        url: https://provider.com/oauth/authorize
        scopes:
          - scope1
          - scope2
      token:
        url: https://provider.com/oauth/token
    
    1. Implement OAuth Methods in provider/*.py:
    def get_authorization_url(self, credentials: dict) -> str:
        """Return OAuth authorization URL"""
        pass
    
    def validate_oauth_callback(self, credentials: dict, state: str, code: str) -> dict:
        """Exchange code for access token"""
        pass
    
    1. Access Tokens in Tools:
    def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:
        # Access token is available in runtime
        access_token = self.runtime.credentials.get("access_token")
    
        # Use token in API calls
        headers = {"Authorization": f"Bearer {access_token}"}
    

    Refer to the OAuth documentation for complete implementation details.


    Best Practices (From Official Documentation)

    ALWAYS:

    • Load official documentation BEFORE writing any code
    • Follow exact syntax and structure from the docs
    • Use one Tool class per .py file
    • Use .get() method for accessing parameters
    • Include comprehensive error handling
    • Add logging for debugging
    • Test thoroughly before packaging
    • Document all methods and classes
    • Validate credentials properly

    NEVER:

    • Guess at syntax or structure
    • Skip mandatory documentation loading
    • Put multiple Tool classes in one file
    • Access parameters without .get() or validation
    • Use local file I/O operations (serverless environment constraint)
    • Assume parameters exist without checking
    • Package without testing first
    • Skip error handling

    Security Considerations:

    • Always validate and sanitize user inputs
    • Never log sensitive data (API keys, passwords)
    • Use environment variables for credentials
    • Validate credentials before use
    • Handle API errors gracefully

    Progress Tracking

    Throughout the development process, keep the user informed:

    1. Current Phase: Tell the user which phase you're in
    2. Completed Steps: Show what has been accomplished
    3. Next Actions: Explain what will happen next
    4. User Input Needed: Ask for clarification when needed
    5. Problems Encountered: Report any issues and solutions

    Example Progress Update:

    ✅ Phase 1 Complete: Requirements gathered
    ✅ Phase 2 Complete: Project initialized
    🔄 Phase 3 In Progress: Implementing tool (60% done)
       ✅ YAML configuration complete
       ✅ Tool class structure created
       🔄 Adding API integration
       ⏳ Error handling pending
       ⏳ Logging setup pending
    ⏳ Phase 4 Pending: Testing & debugging
    ⏳ Phase 5 Pending: Packaging
    

    Reference Quick Access

    Load these reference files when you need specific information:

    • references/doc-map.md - Complete map of what each official doc contains
    • references/workflow.md - Detailed 5-phase workflow
    • references/cli-commands.md - Dify CLI command reference
    • references/troubleshooting.md - Common errors and solutions
    • references/examples.md - Real-world plugin examples

    Helper Script:

    Use the fetch script to quickly retrieve official docs:

    bash scripts/fetch_doc.sh tool        # Fetch tool-plugin.md
    bash scripts/fetch_doc.sh oauth       # Fetch tool-oauth.md
    bash scripts/fetch_doc.sh debug       # Fetch debugging-logs.md
    bash scripts/fetch_doc.sh init        # Fetch initialize-development-tools.md
    

    Summary

    This skill guides you through a structured 5-phase workflow:

    1. Setup & Planning - Gather requirements, verify CLI
    2. Initialize Project - Create plugin structure with CLI
    3. Implement Tool - Write YAML configs and Python code
    4. Test & Debug - Run locally, fix issues, add logging
    5. Package & Publish - Create .difypkg file, optionally publish

    Key Success Factors:

    • Always load documentation before coding
    • Follow official patterns exactly
    • Test thoroughly before packaging
    • Handle errors gracefully
    • Keep the user informed of progress

    The result will be a production-ready Dify tool plugin that follows best practices and official guidelines.

    Repository
    skilzy-ai/official-skills
    Files