Skip to content

Your First Plugin

In this tutorial, we’ll build a simple “Echo” plugin that responds to any user message by repeating it back.

If you have not defined a custom agent yet, start with Your First Agent.

When wiring HTTP/SSE yourself, pass channelId and threadId together (Your First Channel — both are required for conversations).

  • Node.js installed on your machine.
  • A basic understanding of TypeScript.
  • OpenBot installed (npm i -g openbot).

Create a new directory for your plugin and initialize it:

Terminal window
mkdir openbot-echo-plugin
cd openbot-echo-plugin
npm init -y
npm install @meetopenbot/plugin-sdk

Create a file named index.ts and add the following code:

import { definePlugin, shouldHandleInvoke, agentOutput } from '@meetopenbot/plugin-sdk';
export default definePlugin({
id: 'echo-plugin',
name: 'Echo Plugin',
description: 'Repeats user input back to them.',
factory: (context) => (builder) => {
builder.on('agent:invoke', async function* (event) {
// Check if this event should be handled by our agent
if (shouldHandleInvoke(event, context.agentId)) {
const userContent = event.data?.content || '';
// Emit an agent:output event
yield agentOutput({
agentId: context.agentId,
content: `You said: ${userContent}`,
threadId: event.meta?.threadId,
});
}
});
},
});

Compile your TypeScript code to JavaScript. You can use tsc or any other bundler.

To test your plugin, you must create a directory for it in the OpenBot plugins folder:

Terminal window
mkdir -p ~/.openbot/plugins/echo-plugin

Then, place your compiled index.js file into that directory: ~/.openbot/plugins/echo-plugin/index.js.

Finally, reference it in an agent’s AGENT.md:

plugins:
- id: echo-plugin
  • definePlugin: Provides the structure and types for your plugin.
  • builder.on('agent:invoke', ...): Subscribes to the event triggered when a user sends a message.
  • shouldHandleInvoke: A helper to ensure your plugin only responds when the specific agent it’s attached to is invoked.
  • yield agentOutput(...): Sends a message back to the user via the event bus.

Try extending your plugin to use the storage interface or render a uiWidget!