Skip to main content
Comis plugins are trusted, source-integrated components that register typed lifecycle hooks. The public PluginRegistryApi deliberately exposes one registration method: registerHook.
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.

Plugin Contract

A plugin implements PluginPort. Its synchronous register() method receives a registry facade scoped to that plugin ID.
The public registration surface is intentionally narrow:
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.

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.
Register the plugin from source-level bootstrap or composition wiring and handle the returned 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.

Custom Adapters

Add a channel through its port and daemon wiring

Event Bus

Publish and subscribe to typed system events

Custom Skills

Extend agents with prompt skills and MCP

Architecture

Understand ports, adapters, and composition