Skip to main content

Plugins

Each plugin has its interface, but in general, all plugins are structured the same way. Every current plugin lives in-tree under src/dispatch/plugins/, alongside the rest of the codebase:

src/dispatch/plugins/dispatch_pluginname/
src/dispatch/plugins/dispatch_pluginname/__init__.py
src/dispatch/plugins/dispatch_pluginname/plugin.py

The __init__.py file should contain no plugin logic, and at most, a VERSION = ‘x.x.x’ line. For example, if you want to pull the version using pkg_resources (which is what we recommend), your file might contain:

try:
VERSION = __import__('pkg_resources') \
.get_distribution(__name__).version
except Exception as e:
VERSION = 'unknown'

Inside of plugin.py declare your own Plugin class:

import dispatch_pluginname
from dispatch.plugins.base.conversation import ConversationPlugin

class PluginName(ConversationPlugin):
title = 'Plugin Name'
slug = 'pluginname'
description = 'My awesome plugin!'
version = dispatch_pluginname.VERSION

author = 'Your Name'
author_url = 'https://github.com/yourname/dispatch_pluginname'

def create(self, items, **kwargs):
return "Conversation Created"

def add(self, items, **kwargs):
return "User Added"

def send(self, items, **kwargs):
return "Message sent"

Register your plugin by adding it to the shared [project.entry-points."dispatch.plugins"] table in the root pyproject.toml (every in-tree plugin registers here, not in a per-plugin file):

[project.entry-points."dispatch.plugins"]
pluginname = "dispatch.plugins.dispatch_pluginname.plugin:PluginName"

You can potentially package multiple plugin types in one package, say you want to create a conversation and conference plugins for the same third-party. To accomplish this, add multiple entries pointing at different plugins within your package:

[project.entry-points."dispatch.plugins"]
pluginnameconversation = "dispatch.plugins.dispatch_pluginname.plugin:PluginNameConversation"
pluginnameconference = "dispatch.plugins.dispatch_pluginname.plugin:PluginNameConference"

Once your plugin files are in place and registered, uv sync (or uv pip install -e .) picks it up along with the rest of the package — no separate install step is needed for an in-tree plugin.

info

A plugin can still be distributed as its own external package with its own setup.py/pyproject.toml and entry_points/[project.entry-points] table, the same way any Python package registers entry points — see Python Packaging. No current Dispatch plugin does this; it's a viable option, not the established pattern.