# Plugin SDK

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](plugin-quickstart.md) 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](plugin-tools.md) |
| Middleware | Rewrites or vetoes a message, prompt, todo, timer, SSH command or scheduled run as it happens — 17 hooks | `middleware.<hook> = (context, tools) => …` | [Middleware](plugin-middleware.md) |
| 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](plugin-lifecycle-events.md) |
| Agent crew | Creates and heals a team of real agents your plugin owns | `host.agents.*` + `manifest.agents` | [Agent crews](plugin-agent-crews.md) |
| Command | A slash command such as `/research <question>` | `commands/<name>.md` | [Commands and skills](plugin-commands-and-skills.md) |
| Skill | Instructions (and files) an agent loads only when it needs them | `skills/<key>/skill.md` | [Commands and skills](plugin-commands-and-skills.md) |
| Channel | A two-way chat app: people message the agent there, it answers there | `channel.{receive, send, typing, fetchAttachment}` | [Channels](plugin-channels.md) |
| Live connection | A socket AgentParley holds open for you for days (Discord, IRC-style protocols) | `connection.{open, receive, timer}` | [Live connections](plugin-live-connections.md) |
| Chat model provider | Your vendor's models become selectable agent brains | `modelProvider.complete` | [Model providers](plugin-model-providers.md) |
| Decision model provider | Fast typed yes/no, choose and score answers | `modelProvider.{noul, choose, score}` | [Model providers](plugin-model-providers.md) |
| Voice provider | Text-to-speech voices for companions | `modelProvider.{speak, voices}` | [Voice and speech-to-text](plugin-voice-and-speech.md) |
| Speech-to-text provider | Turns what the user says to a companion into text | `modelProvider.transcribe` (plus optional `modelProvider.startLiveTranscription` for live words) | [Voice and speech-to-text](plugin-voice-and-speech.md) |
| Web search / web fetch provider | Replaces the engine behind the built-in `web_search` / `web_fetch` tools | `web.search`, `web.fetch` | [Web providers](plugin-web-providers.md) |
| Compaction provider | Replaces how long conversations are summarized | `compaction.summarize` | [Compaction](plugin-compaction.md) |
| Companion model | A look: a 3D avatar (VRM or GLB) or a Live2D model (`.zip`) with its own motions — idle, talk, listen, think, gestures | `companion-models/<key>/model.json` | [Companion packs](plugin-companion-packs.md) |
| Companion character | A ready-made face: one look + suggested personality and voice | `companion-characters/<key>/character.json` | [Companion packs](plugin-companion-packs.md) |

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.

```ts
// 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](plugin-package-format.md#register-at-the-top-level).
- **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](plugin-manifest.md).

## 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.cronJobs` to
own schedules, `host.oauth` for customer sign-ins, `host.llm` to call a model, `host.crypto` to check webhook
signatures, and so on. The [Host API reference](plugin-host-api.md) lists every
member.

**You only get what you called.** 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, `host.workspace`, `host.media`, `host.ssh` and `host.connection` are absent unless
granted, and a call to `host.session`, `host.agents`, `host.models` or `host.cronJobs` that wasn't derived is
rejected with a 403. See [Permissions](plugin-permissions.md).

## 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, a new schedule, a new `failClosed` hook, or the
   `anyone` sender policy). 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](sandbox-model.md).
- **Permissions you can't under-declare.** They come from your code. A call the scanner can't see is not granted —
  it fails at run time.
- **Updates can't sneak in new access.** A version that asks for more waits for the owner's OK.
- **Breadth.** Tools, 17 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](plugin-agent-crews.md).
- **Official plugins use the same SDK.** Discord, Brave Search and Wiki Web are ordinary plugins built on exactly
  what this documentation describes.

## Next

- [Quickstart](plugin-quickstart.md)
- [Package format](plugin-package-format.md) · [Manifest](plugin-manifest.md) · [Permissions](plugin-permissions.md) · [Sandbox model](sandbox-model.md)
- [Host API reference](plugin-host-api.md)
