> ## Documentation Index
> Fetch the complete documentation index at: https://comis-fix-skill-import-vetting-gate.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugins

> Source-integrated lifecycle hooks for customizing Comis behavior

Comis plugins are trusted, source-integrated components that register typed
lifecycle hooks. The public `PluginRegistryApi` deliberately exposes one
registration method: `registerHook`.

<Warning>
  Comis does not currently ship a stable third-party code-plugin loader. The
  plugin registry does not discover packages or register agent tools, HTTP
  routes, or configuration schemas. Those extensions use their own ports and
  must be wired in the composition root.
</Warning>

## Plugin Contract

A plugin implements `PluginPort`. Its synchronous `register()` method receives
a registry facade scoped to that plugin ID.

```typescript theme={}
import type { PluginPort, PluginRegistryApi } from "@comis/core";
import type { Result } from "@comis/shared";

export interface PluginPort {
  readonly id: string;
  readonly name: string;
  readonly version?: string;
  register(registry: PluginRegistryApi): Result<void, Error>;
  activate?(): Promise<Result<void, Error>>;
  deactivate?(): Promise<Result<void, Error>>;
}
```

The public registration surface is intentionally narrow:

```typescript theme={}
export interface PluginRegistryApi {
  registerHook<K extends HookName>(
    hookName: K,
    handler: HookHandlerMap[K],
    options?: { priority?: number },
  ): void;
}
```

`priority` defaults to `0` and may range from `-100` to `100`. Higher values
run first.

## Supported Hooks

Comis exposes nine hooks across five lifecycle domains.

| Hook                 | Kind          | When it runs                        | Supported result                             |
| -------------------- | ------------- | ----------------------------------- | -------------------------------------------- |
| `before_agent_start` | Modifying     | Before an agent processes a message | `systemPrompt`, `prependContext`             |
| `before_compaction`  | Modifying     | Before session compaction           | `cancel`, `cancelReason`                     |
| `before_delivery`    | Modifying     | Before channel delivery             | `text`, `cancel`, `cancelReason`, `metadata` |
| `after_compaction`   | Observational | After session compaction            | None                                         |
| `after_delivery`     | Observational | After channel delivery              | None                                         |
| `session_start`      | Observational | When a session starts               | None                                         |
| `session_end`        | Observational | When a session ends                 | None                                         |
| `gateway_start`      | Observational | When the gateway starts             | None                                         |
| `gateway_stop`       | Observational | When the gateway stops              | None                                         |

### Modifying hooks

The three modifying hooks run sequentially. Their return values are validated
against strict schemas and merged field by field. A higher priority handler
runs earlier, but a later handler can replace the same field. Avoid assigning
the same field from multiple plugins when ordering alone would determine the
result.

### Observational hooks

The six observational hooks run in parallel and return no result. They are
appropriate for lifecycle notifications and metrics that do not alter the
operation.

By default, the hook runner contains individual handler errors so one hook
does not stop the remaining lifecycle work. Invalid modifying results are
ignored.

## Example

This source-integrated plugin adds context before an agent starts and appends a
footer before a response is delivered.

```typescript theme={}
import type { PluginPort, PluginRegistryApi } from "@comis/core";
import { ok, type Result } from "@comis/shared";

export const operatorContextPlugin: PluginPort = {
  id: "operator-context",
  name: "Operator Context",

  register(registry: PluginRegistryApi): Result<void, Error> {
    registry.registerHook(
      "before_agent_start",
      (_event, ctx) => {
        if (!ctx.isFirstMessageInSession) return;
        return { prependContext: "Follow the operator runbook for this session." };
      },
      { priority: 20 },
    );

    registry.registerHook("before_delivery", (event) => ({
      text: `${event.text}\n\nSent through Comis`,
    }));

    return ok(undefined);
  },
};
```

Register the plugin from source-level bootstrap or composition wiring and
handle the returned `Result`:

```typescript theme={}
const result = pluginRegistry.register(operatorContextPlugin);
if (!result.ok) return result;
```

There is no package discovery step. Adding a plugin means importing it and
wiring it into the application source.

## Registry Lifecycle

The generic `PluginRegistry` exposes these operations:

* `register(plugin)` adds the plugin and calls `plugin.register(api)`.
* `unregister(id)` removes the plugin and its registered hooks.
* `getHooksByName(name)` returns handlers sorted by descending priority.
* `deactivateAll()` calls each registered plugin's optional `deactivate()`.
* `count()` reports the number of registered plugins.

`PluginPort` includes an optional `activate()` method, but the generic registry
does not invoke it. A source integration that needs activation must own that
lifecycle explicitly.

## Security Boundary

Plugin code runs in the Comis process and is not sandboxed. Treat it as trusted
application code, review it like any other dependency, and give external data
the same validation and prompt-wrapping treatment used elsewhere in Comis.

<CardGroup cols={2}>
  <Card title="Custom Adapters" icon="plug" href="/developer-guide/custom-adapters">
    Add a channel through its port and daemon wiring
  </Card>

  <Card title="Event Bus" icon="tower-broadcast" href="/developer-guide/event-bus">
    Publish and subscribe to typed system events
  </Card>

  <Card title="Custom Skills" icon="wand-magic-sparkles" href="/developer-guide/custom-skills">
    Extend agents with prompt skills and MCP
  </Card>

  <Card title="Architecture" icon="hexagon" href="/developer-guide/architecture">
    Understand ports, adapters, and composition
  </Card>
</CardGroup>
