Building

Plugin SDK

What a plugin is, what it can change, and how the pieces fit.

A plugin is one package that changes what your agents can do. It can give them a new tool, rewrite a message before the model sees it, install a whole crew of specialist agents, connect them to a chat app, replace the web-search engine, give them a voice, or put a 3D face on them. You write TypeScript or JavaScript against a typed SDK, upload the package, and anyone who installs it gets exactly what the code does — nothing more.

This page is the mental model. The Quickstart gets a plugin running in about ten minutes.

One package, many capabilities

A single package can carry any mix of these. Each is a capability: something the platform discovers in your package at publish time and switches on when someone installs it.

Capability What it does for the user How you declare it Guide
Tool A function the model can call, next to the built-in tools tools.<name> = { description, parameters, handler } Tools
Middleware Rewrites or vetoes a message, prompt, todo, timer, SSH command or scheduled run as it happens — 14 hooks middleware.<hook> = (context, tools) => … Middleware
Lifecycle event Runs when your plugin is installed, updated or removed, or a chat starts, is cleared or deleted — 6 events events.<event> = (context) => … Lifecycle events
Agent crew Creates and heals a team of real agents your plugin owns host.agents.* + manifest.agents Agent crews
Command A slash command such as /research <question> commands/<name>.md Commands and skills
Skill Instructions (and files) an agent loads only when it needs them skills/<key>/skill.md Commands and skills
Channel A two-way chat app: people message the agent there, it answers there channel.{receive, send, typing, fetchAttachment} Channels
Live connection A socket AgentParley holds open for you for days (Discord, IRC-style protocols) connection.{open, receive, timer} Live connections
Chat model provider Your vendor's models become selectable agent brains modelProvider.complete Model providers
Decision model provider Fast typed yes/no, choose and score answers modelProvider.{noul, choose, score} Model providers
Voice provider Text-to-speech voices for companions modelProvider.{speak, voices} Voice and speech-to-text
Speech-to-text provider Turns what the user says to a companion into text modelProvider.transcribe Voice and speech-to-text
Web search / web fetch provider Replaces the engine behind the built-in web_search / web_fetch tools web.search, web.fetch Web providers
Compaction provider Replaces how long conversations are summarized compaction.summarize Compaction
Companion motion set How a 3D companion moves — idle, talk, listen, think, gestures companion-motions/<key>/motions.json Companion packs
Companion model A 3D avatar (VRM or GLB) companion-models/<key>/model.json Companion packs
Companion character A ready-made face: look + motions + suggested personality and voice companion-characters/<key>/character.json Companion packs

Companion packs, commands and skills are data: no code runs for them. Everything else is code you write.

Code declares itself

There is no capability list to maintain. The platform gives your code a set of empty objects — middleware, events, tools, compaction, web, modelProvider, channel, connection — and you assign handlers to them. At publish time the platform runs your bundle once, reads back what you assigned, and turns each assignment into a capability.

// plugins/caveman/index.ts — the whole plugin
const GUIDANCE =
  "\n\n## Caveman mode (output-brevity skill)\n" +
  "Rewrite your responses to be dramatically shorter while keeping technical accuracy.\n" +
  // …
  "Say the least that fully answers. Example: 'New ref each render. Wrap in useMemo.' not a paragraph.";

globalThis.middleware.systemPrompt = async (context) => {
  return context.systemPrompt + GUIDANCE;
};

That one assignment is a complete, publishable plugin: one middleware capability, zero permissions.

Two rules follow from "the platform reads what you assigned":

  • Register at the top level. An assignment made inside a handler, or computed from a host.* call, is invisible at publish time and is never switched on. See Package format.
  • Everything else goes in globalThis.manifest — the hosts you call, the settings form users fill in, the agents you will create, the provider you register as. See the Manifest reference.

Your code talks to the world through host

Plugin code runs in a sandbox with no network, no filesystem and no process access. Everything goes through one object, host: host.fetch for HTTP (only to hosts you declared), host.settings for the installer's settings and secrets, host.session to read and act on the current chat, host.agents to manage your crew, host.llm to call a model, host.crypto to check webhook signatures, and so on. The Host API reference lists every member.

A member is only there if you were granted it. You don't write a permission list. At publish time the platform reads your code, finds every host.x.y(...) call, and derives the permissions from them. The installer sees that list before installing. At run time, a member you weren't granted is simply absent. See Permissions.

Lifecycle of a plugin

  1. Write — in the console's plugin editor (one script) or locally (any number of .ts/.js files).
  2. Publish — upload a zip or press Publish. The platform bundles your code, discovers the capabilities, derives the permissions, and stores an immutable version. A version is private to your account until you choose List in Browse.
  3. Install — the user sees what your plugin can reach and what it adds (for example "Adds 7 agents"), then installs. Installing switches on every capability in the version.
  4. Configure — the user fills in your settings form; secrets are write-only and encrypted.
  5. Use — middleware and lifecycle hooks run for the whole account; tools, commands and skills appear on every agent (each agent's Access tab can narrow them); providers are picked under AI Providers → Add provider or Settings → Engines; channels under Channels → Connect; companion characters in the Companions gallery.
  6. Update — publish a new version. Installs on the Latest policy move to it automatically — unless it asks for more access (a new permission, a new host, a new agent). Then it waits for the user to accept it.

What makes this different

  • A real sandbox, per call. Every invocation runs in a fresh V8 isolate with a memory cap and a wall-clock limit, and is thrown away afterwards. Secrets and the platform's API token never enter it. See Sandbox model.
  • Permissions you can't under-declare. They come from your code. A call the scanner can't see doesn't get secret access — it fails, because the member was never bound.
  • Updates can't sneak in new access. A version that asks for more waits for the owner's OK.
  • Breadth. Tools, 14 middleware hooks (including SSH command rewriting and output redaction, and vetoing scheduled missions), lifecycle events, crews, commands, skills, channels, held sockets, chat / decision / voice / speech-to-text providers, web search, web fetch, compaction and 3D companion assets — all in one package format.
  • Plugins can ship a team. A crew plugin creates real agents — each with its own model, persona and instructions — keeps them healthy, and shapes how they work together. See Agent crews.
  • Official plugins use the same SDK. Discord, Brave Search and Wiki Web are ordinary plugins built on exactly what this documentation describes.

Next