Files
LangBot/docs/en/plugin/dev/tutor.md
T
2025-05-13 15:25:41 +00:00

7.5 KiB

Plugin Development Tutorial

This tutorial will guide you through the process of developing a plugin for LangBot.

Plugin Structure

A LangBot plugin consists of the following components:

  1. A main Python file that contains the plugin logic
  2. A manifest.yaml file that describes the plugin
  3. Optional additional files for resources, templates, etc.

Creating a Basic Plugin

Let's create a simple "Hello World" plugin that responds to a specific command.

Step 1: Create the Plugin Directory

Create a directory for your plugin in the data/plugins directory:

mkdir -p data/plugins/hello-plugin

Step 2: Create the Manifest File

Create a manifest.yaml file in your plugin directory:

name: HelloPlugin
version: 1.0.0
description: A simple hello world plugin
author: Your Name
entry: hello.py
requirements:
  - requests>=2.28.0

Step 3: Create the Plugin Code

Create a hello.py file in your plugin directory:

from langbot.plugin import Plugin, handler
from langbot.event import PersonNormalMessageReceived
from langbot.api import APIHost

class HelloPlugin(Plugin):
    def __init__(self, api_host: APIHost):
        super().__init__(api_host)
        self.api = api_host
        
    @handler(PersonNormalMessageReceived)
    def on_person_message(self, ctx):
        # Get the message content
        message = ctx.event.message.content
        
        # Check if the message is the command we want to handle
        if message == "!hello":
            # Prevent the default handling (don't send to LLM)
            ctx.prevent_default()
            
            # Send a response
            self.api.send_message(
                ctx.event.message.source,
                "Hello, World! This is my first LangBot plugin."
            )

Step 4: Install and Test the Plugin

  1. Restart LangBot or use the !plugin reload command
  2. Send the !hello command to your bot
  3. The bot should respond with "Hello, World! This is my first LangBot plugin."

Event Handling

LangBot uses an event-driven architecture. Plugins can register handlers for various events:

@handler(PersonNormalMessageReceived)
def on_person_message(self, ctx):
    # Handle the event
    pass

Common events include:

  • PersonNormalMessageReceived: Received a message from a person
  • GroupNormalMessageReceived: Received a message in a group
  • GroupInvitationReceived: Received an invitation to join a group
  • FriendRequestReceived: Received a friend request

The ctx parameter provides access to:

  • ctx.event: The event that triggered the handler
  • ctx.prevent_default(): Prevents the default handling of the event
  • ctx.add_return(key, value): Adds a return value to the event

API Access

The APIHost provides access to LangBot's API:

# Send a message
self.api.send_message(source, content)

# Get user information
user_info = self.api.get_user_info(user_id)

# Get group information
group_info = self.api.get_group_info(group_id)

# Call the LLM
response = self.api.call_llm(prompt, model="gpt-3.5-turbo")

LLM Function Registration

Plugins can register functions that can be called by the LLM during conversations:

import requests
from langbot.plugin import Plugin, llm_func
from langbot.api import APIHost

class WebSearchPlugin(Plugin):
    def __init__(self, api_host: APIHost):
        super().__init__(api_host)
        self.api = api_host
        
    @llm_func(name="search_the_web")
    def search_web(self, query: str) -> str:
        """
        Search the web for information.
        
        Args:
            query: The search query
            
        Returns:
            The search results
        """
        # Implement web search logic
        response = requests.get(
            "https://api.search.com/search",
            params={"q": query}
        )
        return response.json()["results"]

The LLM can then call this function during conversations:

User: What's the weather in New York?
Bot: Let me check that for you.
[Function call: search_the_web("weather in New York")]
The current weather in New York is 72°F and sunny.

Configuration

Plugins can have configuration options that users can set:

from langbot.plugin import Plugin, config_field
from langbot.api import APIHost

class WeatherPlugin(Plugin):
    def __init__(self, api_host: APIHost):
        super().__init__(api_host)
        self.api = api_host
        
    @config_field(name="api_key", description="API key for the weather service")
    def set_api_key(self, api_key: str):
        self.api_key = api_key

Users can set these options using the WebUI or the !plugin config command:

!plugin config WeatherPlugin api_key=your-api-key

Persistent Storage

Plugins can store data persistently:

# Store data
self.api.storage.set("key", "value")

# Retrieve data
value = self.api.storage.get("key")

# Check if a key exists
exists = self.api.storage.has("key")

# Delete a key
self.api.storage.delete("key")

Advanced Features

Command Registration

Plugins can register commands that users can use:

from langbot.plugin import Plugin, command
from langbot.api import APIHost

class EchoPlugin(Plugin):
    def __init__(self, api_host: APIHost):
        super().__init__(api_host)
        self.api = api_host
        
    @command(name="echo", description="Echo a message")
    def echo_command(self, args: str) -> str:
        """
        Echo the provided message.
        
        Usage: !echo <message>
        """
        return args

Users can then use the command:

!echo Hello, World!

Event Return Values

Handlers can add return values to events:

@handler(PersonNormalMessageReceived)
def on_person_message(self, ctx):
    # Add a return value
    ctx.add_return("reply", ["This is a reply"])

Component Extension

Plugins can extend LangBot's core components:

from langbot.plugin import Plugin, component_extension
from langbot.api import APIHost

class CustomTriggerPlugin(Plugin):
    def __init__(self, api_host: APIHost):
        super().__init__(api_host)
        self.api = api_host
        
    @component_extension("trigger")
    def custom_trigger(self, component, message):
        # Implement custom trigger logic
        if message.content.startswith("custom:"):
            return True
        return None  # Let the default trigger handle it

Publishing Your Plugin

To publish your plugin:

  1. Create a GitHub repository for your plugin
  2. Add a README.md file with installation and usage instructions
  3. Add your plugin to the LangBot Plugin Market

Best Practices

  • Keep your plugin focused on a specific functionality
  • Handle errors gracefully
  • Provide clear documentation
  • Follow Python best practices
  • Test your plugin thoroughly
  • Keep dependencies minimal

Example Plugins

Check out these example plugins for inspiration:

  • WebSearch: Search the web for information
  • ImageGen: Generate images using AI
  • Schedule: Schedule messages to be sent at specific times

Troubleshooting

If you encounter issues with your plugin:

  1. Check the logs for error messages
  2. Verify that your plugin is correctly installed
  3. Make sure your plugin's dependencies are installed
  4. Test your plugin with simple functionality first
  5. Ask for help in the community chat