# What Capabilities Can Plugins Expose to Paperclip Agents: A Complete Guide

> Explore the seven core capability categories plugins expose to Paperclip agents: tools, authentication, UI, events, jobs, state, and hooks. Unlock the full potential of your agents.

- Repository: [Paperclip/paperclip](https://github.com/paperclipai/paperclip)
- Tags: how-to-guide
- Published: 2026-08-14

---

**Plugins expose seven core capability categories to Paperclip agents: tools, authentication providers, UI contributions, events, scheduled jobs, state persistence, and runtime hooks—all gated by a typed capability system.**

Paperclip's plugin architecture is built around the `@paperclipai/plugin-sdk` package, which provides a `definePlugin()` factory for declaring extensions. The design separates host-controlled surfaces from plugin-owned logic, ensuring safe extension while preserving core invariants. This article breaks down every capability surface agents can consume, with implementation details from the Paperclip source code.

## Agent-Usable Tools

Plugins register **namespaced tools** via `ctx.tools.register()`, making them available to agents alongside built-in tools.

According to [[`doc/plugins/ideas-from-opencode.md`](https://github.com/paperclipai/paperclip/blob/main/doc/plugins/ideas-from-opencode.md)](https://github.com/paperclipai/paperclip/blob/master/doc/plugins/ideas-from-opencode.md#L517-L525), tool registration requires the `agent.tools.register` capability. Tools are namespaced to prevent collision—`pluginId:toolName` rather than flat global names.

```typescript
// From packages/plugins/examples/plugin-hello-world-example/src/worker.ts pattern
ctx.tools.register("example:say-hello", {
  description: "Returns a friendly greeting",
  input: ctx.z.object({
    name: ctx.z.string().optional(),
  }),
  async run({ input }) {
    const who = input.name ?? "world";
    return `👋 Hello, ${who}!`;
  },
});

```

The tool appears in the same registry as native Paperclip tools. Agents invoke it by name, with the host handling marshalling between the agent runtime and your plugin worker.

## Custom Auth Providers

Beyond tools, plugins extend **authentication flows** through `ctx.auth.registerProvider()`.

This capability lets plugins contribute custom request loaders and evolve provider behavior post-authentication ([L79-L211](https://github.com/paperclipai/paperclip/blob/master/doc/plugins/ideas-from-opencode.md#L79)). The provider metadata includes description, token refresh logic, and header injection.

```typescript
ctx.auth.registerProvider("example:api-key", {
  description: "API-key auth for Example.com",
  async getHeaders() {
    // Secrets retrieved from host-managed secure storage
    return { Authorization: "Bearer EXAMPLE_KEY" };
  },
});

```

## UI Contributions via Extension Slots

Plugins ship **React bundles** that export components for host-controlled slots: dashboard widgets, settings pages, and company panels.

The host loads these via a **typed bridge** forwarding `getData`, `performAction`, and error objects ([L452-L465](https://github.com/paperclipai/paperclip/blob/master/doc/plugins/ideas-from-opencode.md#L452)). The UI field in `definePlugin()` exports components; the host decides placement.

```typescript
ui: {
  DashboardWidget: async () => {
    const { usePluginData } = await import("@paperclipai/plugin-sdk/ui");
    const data = await usePluginData("example:status", {});
    return <div>Example status: {data?.status ?? "unknown"}</div>;
  },
},

```

**Key constraint:** The plugin owns the component; the host owns the slot. Communication crosses the worker/UI boundary through the bridge implemented in [[`packages/plugins/sdk/src/worker-rpc-host.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/plugins/sdk/src/worker-rpc-host.ts)](https://github.com/paperclipai/paperclip/blob/master/packages/plugins/sdk/src/worker-rpc-host.ts).

## Event Bus and Plugin-to-Plugin Communication

The **typed event bus** enables reactive, decoupled architectures.

- **Core events:** Subscribe with `ctx.events.on("issue.created", handler)`
- **Plugin events:** Emit with `ctx.events.emit("plugin.<pluginId>.eventName", payload)`
- **Cross-plugin consumption:** Other plugins subscribe to `plugin.<yourId>.*` patterns

This design lets plugins react to domain changes without shared state or direct imports ([L530-L536](https://github.com/paperclipai/paperclip/blob/master/doc/plugins/ideas-from-opencode.md#L530)).

```typescript
// React to core domain events
ctx.events.on("issue.created", async (evt) => {
  await ctx.events.emit(
    "plugin.example.issue-notified",
    { issueId: evt.id, title: evt.title }
  );
});

```

## Scheduled Jobs and Automation

Plugins register **cron-style background work** via `ctx.jobs.schedule()`.

Jobs run in out-of-process workers, making them suitable for sync operations, webhook processors, and periodic maintenance ([L408-L409](https://github.com/paperclipai/paperclip/blob/master/doc/plugins/ideas-from-opencode.md#L408)).

```typescript
ctx.jobs.schedule(
  "example:sync",
  { cron: "0 * * * *" }, // every hour
  async () => {
    await ctx.logger.info("Example sync job ran");
  }
);

```

Job definitions persist to `plugin_jobs` table with execution history and retry semantics controlled by the host.

## State Persistence and Lifecycle

Each plugin receives isolated storage:

| Table | Purpose |
|-------|---------|
| `plugin_state` | Key-value and structured state |
| `plugin_entities` | Relational data for plugin-owned models |
| `plugin_jobs` | Job definitions and execution records |

On uninstall, data is retained for a default 30-day grace period to support safe reinstalls ([L561-L564](https://github.com/paperclipai/paperclip/blob/master/doc/plugins/ideas-from-opencode.md#L561)). The plugin accesses storage through typed APIs on `ctx`, not raw SQL.

## Runtime Hooks and Execution Pipeline

Plugins augment the **agent execution pipeline** through fine-grained hooks:

- Tool execution pre/post processors
- Auth header mutation
- Permission answer overrides
- Error transformation

This extensibility point ([L102-L108](https://github.com/paperclipai/paperclip/blob/master/doc/plugins/ideas-from-opencode.md#L102)) enables cross-cutting concerns like logging, caching, or policy enforcement without modifying core tool implementations.

## Health and Observability

Plugins participate in host health systems through:

- **Event emission:** `plugin.health.degraded`, `plugin.worker.crashed`
- **Health check hook:** Optional `health.check` async function
- **Dashboard rendering:** UI slot for custom health visualization ([L569-L573](https://github.com/paperclipai/paperclip/blob/master/doc/plugins/ideas-from-opencode.md#L569))

```typescript
health: {
  async check() {
    // Return false to trigger host recovery procedures
    return await verifyExternalService();
  },
},

```

## Capability Gating and Security

All capabilities require explicit grants. The `definePlugin()` factory validates requested capabilities against the host's permission manifest at load time. Unavailable capabilities throw at registration, not at runtime.

This model ensures plugins operate within declared boundaries—no ambient authority, no surprise network access, no implicit tool registration.

## Summary

- **Tools:** Namespaced agent-callable functions via `ctx.tools.register()`
- **Auth:** Custom providers and flows via `ctx.auth.registerProvider()`
- **UI:** React components for host extension slots via the `ui` field
- **Events:** Typed publish/subscribe with core and plugin-scoped namespaces
- **Jobs:** Cron-scheduled background work via `ctx.jobs.schedule()`
- **State:** Isolated tables with grace-period retention on uninstall
- **Hooks:** Pre/post execution interceptors throughout the agent pipeline
- **Health:** Event-based status reporting and explicit check functions

These surfaces combine to let plugins extend Paperclip agents safely, with the host maintaining control over security boundaries, UI placement, and resource scheduling.

## Frequently Asked Questions

### What permission do I need to register a tool for Paperclip agents?

The `agent.tools.register` capability. Without this grant, `ctx.tools.register()` throws at plugin initialization. This is enforced in the SDK's type system and runtime validation.

### Can plugins modify built-in Paperclip tools?

No direct modification. Plugins can hook tool execution (before/after) through runtime hooks, but cannot override or replace core tool implementations. This preserves the integrity of the built-in agent toolset.

### How do plugins communicate with their own UI components?

Through the typed bridge API. UI components use `usePluginData()` and `performAction()` from `@paperclipai/plugin-sdk/ui`, which serialize calls across the worker boundary. The host's RPC layer in [`worker-rpc-host.ts`](https://github.com/paperclipai/paperclip/blob/main/worker-rpc-host.ts) handles message routing.

### What happens to plugin data after uninstall?

Data in `plugin_state`, `plugin_entities`, and `plugin_jobs` is retained for 30 days by default. This supports clean reinstalls without data loss. The grace period is host-configurable per [L561-L564](https://github.com/paperclipai/paperclip/blob/master/doc/plugins/ideas-from-opencode.md#L561).

### Can scheduled jobs access the same context as interactive tools?

Yes, with differences. Jobs receive a `ctx` object with tools, storage, events, and logger, but lack agent conversation context. The job's `ctx` is isolated per execution, with its own tracing and retry state.