A plugin is an object with a name and a setup function.
setup returns the parts the plugin adds.
Each key in that return value is one part, and a key the contract does not have stops the start and names the closest one.
This page lists the parts in four groups, so you can find the one you need and follow its link.
Example files live in examples/.
Every example has a test next to it that runs without Discord, and the guide embeds each one.
All links in the tables point to the section of the full plugin guide.
| Piece |
What it is for |
Example |
Guide |
| The plugin object |
Holds the name (lowercase words joined by dashes, unique across plugins) and setup. Optional fields sit on the plugin itself, not in what setup returns: migrations, providers, provides, replaces, requires and preflight. A plugin must add something, or the start stops. |
tools.ts |
The plugin object |
| The context |
What setup receives: a logger that tags every line with your plugin name, the host environment (locale, time zone), the database, the services, and more. Some fields work only after every plugin is set up. |
shared-services.ts |
The context |
| Part |
Reach for it when |
Example |
Guide |
tools |
You want agents to be able to call something. Each tool names the lowest tier of speaker whose turns may call it. |
tools.ts |
tools |
holdRules and a tool’s hold |
A call should wait until the owner approves it in Discord. |
holds.ts |
holdRules |
prompt |
You want text added after the core’s prompt in every agent turn. |
prompt.ts |
prompt |
seeds |
You want agents created on the first start. An agent that is already stored is never overwritten. |
seeds.ts |
seeds |
agentSelection |
Every agent should carry some tools besides its own. |
selection.ts |
agentSelection |
piPackages |
Every session should load the Pi extensions of an npm package you installed. |
packages.ts |
piPackages |
sessionTools |
tools cannot express what you need, for example a tool set that changes while the process runs. This is the raw Pi extension form. |
session-tools.ts |
sessionTools |
toolTiers |
You use sessionTools and need to say which tier may use each raw tool. |
none |
toolTiers |
| Part |
Reach for it when |
Example |
Guide |
events |
You want to hear what the core does: a service finished starting, a turn started or ended, the team changed, shutdown began. |
events.ts |
events |
services |
You need something with a lifetime, such as a timer, a queue, or a connection. Services start after setup and stop in reverse order. |
services.ts |
services |
migrations |
Your plugin needs tables of its own. They run before any setup. |
migrations.ts |
migrations |
preflight |
A bad setting should stop the start before Discord connects. |
preflight.ts |
preflight |
backgroundTargets |
A schedule or a delegated task should come back as a turn of a kind you define, with its own limits. |
support-desk.ts |
backgroundTargets |
channels |
Your plugin should own the conversations in some channels, instead of the agent server. Most plugins never need this. |
channels.ts |
channels |
personas and context.turns |
You own a kind of conversation, give it a system prompt, and run its turns without writing the typing, stop and reply pipeline. |
study-room.ts |
personas |
| Part |
Reach for it when |
Example |
Guide |
Slash commands (commands.add) |
You want a subcommand under the root command (/roundtable by default). You add it from setup through the DISCORD service. |
interactions.ts |
Slash commands |
http |
You want a route on the bot’s listener, such as a health check. Anything on it is reachable from the internet, so check a secret in the handler. |
http.ts |
http |
dashboard |
You want extra lines on the dashboard message that the agent server keeps pinned in Discord. |
dashboard.ts |
dashboard |
surfaces |
You want to connect a chat network other than Discord. A surface reports what people write and posts what conversations answer. |
fake-surface.ts |
surfaces |
See Services and addons for provides, requires and replaces, and Examples for every example file.