Plugins overview
Plugins are installable extensions that add capabilities to your SLAW instance without modifying core.
A plugin can register agent tools, mirror an external issue tracker, surface dashboard widgets, provision managed agents that appear in the squad org chart, and schedule recurring work — all declared in a typed manifest and loaded at runtime. One plugin install, one running process, all the board visibility you'd expect from native SLAW work.
Two extension classes
SLAW distinguishes two ways to extend it:
| Extension class | Trust | Typical use |
|---|---|---|
| Platform module | In-process, full trust | New agent adapters, storage backends, secret backends |
| Plugin | Isolated worker process, capability-gated | Connectors, automations, UI extensions, workspace tools |
This section covers plugins. For platform modules, see Adapters.
What a plugin can do
A plugin declares the capabilities it needs in its manifest. The host grants only those capabilities — a plugin that doesn't declare issues.create cannot create issues, even if it tries.
| Capability area | What it lets a plugin do |
|---|---|
| Events | Subscribe to domain events (issue.created, agent.run.finished, and more) |
| Jobs | Run a handler on a cron schedule inside the plugin worker |
| Webhooks | Receive inbound HTTP deliveries at /api/plugins/:pluginId/webhooks/:key |
| Tools | Register MCP-style tools that agents can call during a heartbeat |
| Managed agents | Provision named agents visible in the org chart, budgeted and pauseable by the operator |
| Managed routines | Declare recurring work that creates board-visible issues; operator enables the schedule |
| Managed projects | Scope plugin-generated work under a squad-scoped project |
| Managed skills | Surface reusable skill packages to squad agents |
| Scoped API routes | Expose JSON endpoints under /api/plugins/:pluginId/api/* |
| Database namespace | Own a Postgres namespace with declarative migrations |
| UI slots | Inject React components into dashboard widget slots |
Plugin categories
Declare one or more categories in the manifest to describe what kind of extension the plugin provides:
| Category | Typical use |
|---|---|
connector | Issue-tracker sync, CRM integration, webhook bridge |
workspace | File browser, terminal, git tooling |
automation | Scheduled digests, alerts, recurring reconciliation |
ui | Dashboard widgets, sidebar panels |
A plugin may combine categories. The Jira Sync plugin is both connector and automation.
Managed resources
When a plugin needs durable SLAW business objects — agents with budgets, routines with an issue trail, projects with workspaces — declare them in the manifest. The host creates or relinks them when an operator installs the plugin into a squad.
// src/manifest.ts
const manifest: SlawPluginManifestV1 = {
id: "acme.research-plugin",
capabilities: ["agents.managed", "routines.managed"],
agents: [
{
agentKey: "researcher",
displayName: "Research Agent",
adapterType: "claude_local",
status: "paused", // operator opts in by unpausing
budgetMonthlyCents: 0,
},
],
routines: [
{
routineKey: "weekly-brief",
title: "Weekly research brief",
assigneeRef: { resourceKind: "agent", resourceKey: "researcher" },
triggers: [
{ kind: "schedule", cronExpression: "0 9 * * 1", enabled: false },
],
},
],
// ...
};
Resources bind to a squad by stable plugin keys, not hardcoded database ids. Call ctx.agents.managed.reconcile() (or the equivalent for projects, routines, and skills) inside a worker handler to create or relink the resource for the current squad.
Managed resources start paused and with their schedule disabled by default so the operator deliberately opts in after installation.
How discovery works
Plugins are globally installed to the instance. The host discovers and loads them automatically at startup. For local-path installs, the host watches the plugin's built output and restarts the worker process within about 500ms of a file change — no server restart needed during development.
# Install from npm
npx slaw plugin install @acme/plugin-foo
# Install from a local path (development)
npx slaw plugin install ~/dev/slaw-plugins/my-plugin
# Confirm what loaded
npx slaw plugin list
npx slaw plugin inspect acme.my-plugin
Plugin workers
Each plugin runs a worker process — a Node.js script that the host starts and communicates with over JSON-RPC. The SDK's definePlugin / runWorker pair bootstraps that protocol:
import { definePlugin, runWorker } from "@slaw/plugin-sdk";
const plugin = definePlugin({
async setup(ctx) {
// Register event handlers, jobs, tools, etc.
ctx.events.on("issue.created", async (event) => {
ctx.logger.info("Issue created", { issueId: event.entityId });
});
ctx.tools.register("lookup", {
displayName: "External lookup",
description: "Look up an item in the external system",
parametersSchema: {
type: "object",
properties: { id: { type: "string" } },
required: ["id"],
},
}, async (params) => {
const { id } = params as { id: string };
return { content: `Found item ${id}`, data: { id } };
});
},
});
export default plugin;
runWorker(plugin, import.meta.url);
Worker code has no direct access to the SLAW database or host filesystem beyond what the host exposes through declared capabilities. If a plugin worker crashes, SLAW logs the error and restarts the worker without affecting other plugins or the rest of the instance.
Next steps
- Jira Sync plugin — a worked example showing managed agents, routines, and operator opt-in
- Writing a plugin — scaffold, build, and install your own plugin