Skip to main content

Use a plugin

config is typed by the plugin (definePlugin<MyConfig>()): an unknown option is a compile error, and a config declared with the plugin’s config interface can be passed as is. bot.plug(plugin, config?) returns an unplug function (not the bot, so plug() calls do not chain). Calling it first runs the plugin’s uninstall(ctx), if it has one, and then reverts, newest first, what the plugin registered through ctx.bot:
  • commands (command()), matchers (when(), onMessage(), onType()), conversations and flow triggers (conversation(), use(flow));
  • hooks (before(), after(), onError(), hook());
  • nested plugins (ctx.bot.plug());
  • flows registered at runtime with ctx.bot.registerFlow(), or created (not replaced) with ctx.bot.replaceFlow();
  • every ctx.onDispose(fn) callback.
It does not undo anything else: event listeners (ctx.bot.on() / once()), injected tools (ctx.bot.provide() / ctx.tools), locale messages (ctx.bot.locale()), scheduled jobs (schedule(), every(), delay()), idle handlers (onIdle()), a flow that replaceFlow() overwrote (it is not restored), handoff state, store writes, or timers and connections of your own. Undo those in ctx.onDispose() (or uninstall()). Calling unplug twice is a no-op. If install() throws synchronously, whatever it registered so far is rolled back before the error reaches you; if it returns a promise that rejects, the rejection goes to the 'error' event and nothing is rolled back.

Dependencies between plugins (requires)

A plugin can list the plugins it needs by name. bot.plug() checks them before running install() and throws a descriptive error when one is not plugged:
The check runs at plug time only: unplugging inbox later does not unplug crm. A plugin nested inside another one (ctx.bot.plug() from install()) may require its parent.

One instance per name (multiple)

bot.plug() refuses a plugin whose name is already plugged on the bot, so a plugin registered twice by mistake never runs its handlers twice:
A plugin meant to run several times with different configs sets multiple: true in its spec (every instance must set it). Each instance is then unplugged on its own, and any of them satisfies requires.

Built-in: slashCommands

Config: { greeting?: string; unknownMessage?: string }. The command prefix is a bot option (new Bot({ commandPrefix })), not a plugin option. The replies are built-in texts in the bot’s language. Unknown /commands get an automatic “unknown command” reply (unknownMessage).

Create a plugin

Simple plugin

Configurable plugin with cleanup

Plugin structure

definePlugin(spec) returns the spec unchanged, typed. A plugin can also be a function (config) => spec. The ctx that install receives:
install() must be synchronous and return nothingbot.plug() does not await install(). TypeScript rejects an async install (or one that returns a promise or any other value) at compile time: PluginSpec.install returns void | SyncInstallError, and the error message names the reason. In JavaScript the bot keeps going before an async install finishes, and its rejection only reaches the 'error' event: nothing is rolled back and the plugin counts as plugged; the ESLint rule no-async-plugin-install covers that case. If your plugin needs async setup (open a connection, load an SDK), keep install synchronous and resolve lazily on first use, reporting configuration errors without crashing. That’s how @botmesh/ai loads its provider SDKs.

Plugin packages

Besides slashCommandsPlugin, these packages ship ready-made plugins:
  • AI — @botmesh/ai: LLM replies (aiPlugin), with tools, memory and RAG and streaming.
  • Voice — @botmesh/voice (voicePlugin): speech-to-text for inbound voice notes and text-to-speech replies.
  • Integrations — @botmesh/chatwoot, @botmesh/tickets, @botmesh/moderation, @botmesh/dialogflow and @botmesh/nlu (local intent matching).
  • Tracing — @botmesh/otel (otelMetricsPlugin): bot.metrics() and the bot’s spans in OpenTelemetry.
All of them are on npm. @botmesh/rag (retrieval for aiPlugin) is described with memory and RAG.

Next steps