Sophon 1.15 is here
Sophon Docs
Features

PluginsNEW

Extend Sophon with out-of-process plugins — new messaging channels and document formats running as local processes alongside the Gateway.

A plugin is an out-of-process .NET program that extends one of Sophon's core interfaces over gRPC — without forking Sophon. The Gateway spawns each plugin as a long-lived, full-trust local dotnet process and talks to it over localhost. Plugins are a different mechanism from skills (sandboxed, short-lived agent tools) and MCP (external tool servers you connect to): skills and MCP give the agent new tools, while plugins give Sophon itself new capabilities — a messaging channel the core doesn't ship, or a file format the document pipeline can't read.

What plugins can extend

Each plugin implements exactly one interface, declared as pluginInterface in its manifest. Check the status column before building anything — not every interface is consumed by the runtime yet:

InterfaceStatusWhat it does
ChannelAdapter✔ Wired end-to-endAdds a new messaging channel — a proprietary in-house chat system, an internal ticketing bridge, a niche protocol. Registered channel types appear in the Dashboard add-channel wizard (via GET /api/channels/types) with full session, routing, and approval integration.
DocumentExtractor✔ Wired end-to-endAdds new file formats (EPUB, RTF, CAD, …) to the document pipeline via a dynamic extractor registry. Built-in formats always win ties — a plugin can never shadow a format Sophon already handles.
ModelProviderAccepted — comingThe manifest is accepted and the process runs, but the runtime doesn't route model calls to it yet. For an OpenAI-compatible endpoint, use the built-in custom provider today.
EmbeddingProviderAccepted — comingSame story — accepted, runs, not yet wired into embedding generation.
VaultBackendAccepted — comingDeferred: the vault must exist before plugins are even scanned (plugin settings are vault-hydrated), so this needs extra bootstrap work. Use the built-in vault backends today.
ToolRefusedIntentional. Custom agent tools belong in skills (sandboxed) or MCP servers — never in a full-trust process. A Tool manifest is refused at parse time and the plugin never starts.

For the three not-yet-consumed interfaces, the plugin process still starts and passes healthchecks — the Gateway logs a one-time warning so you don't mistake a running-but-inert plugin for a bug.

Enabling plugins

Plugins are off by default. An admin has to opt in — from the Dashboard at Settings → Plugins (a confirm dialog guards the enable switch), or via config:

{
  "Sophon": {
    "Plugins": {
      "Enabled": true,
      "Allow": ["acme-chat-adapter"]   // optional allowlist of plugin names (case-insensitive);
                                        // empty = every discovered plugin may load
    }
  }
}

Environment-variable form:

SOPHON__Plugins__Enabled=true
SOPHON__Plugins__Allow__0=acme-chat-adapter
SOPHON__Plugins__Allow__1=epub-extractor

The Dashboard toggle applies live — plugins hot-start or hot-stop with no Gateway restart. The env-var form requires a restart to take effect. Note that Allow filters by the name a manifest claims; it doesn't verify authorship or file integrity (see the security model below).

Installing and discovery

The Gateway scans two directories for manifest.json files, on startup and on demand:

  1. <dataDir>/plugins/ — locally developed or hand-installed plugins (scanned first)
  2. <dataDir>/skills/installed/ — Marketplace-installed plugins

If the same plugin name appears in both, the first-scanned copy wins and the duplicate is skipped with a warning. There is no filesystem watcher — trigger a rescan explicitly:

curl -X POST http://localhost:8080/api/plugins/scan   # admin-only

(or use the Scan button at Settings → Plugins).

For local development, the CLI does the packaging and staging:

sophon dev build      # packages the project into a .sophon-plugin archive
sophon dev install    # copies the project into ~/.sophon/plugins/<name>/ for a live Gateway

Marketplace plugin installs land in skills/installed/ through the same pipeline as skills — see Publishing to the Marketplace.

Lifecycle

  1. Spawn — the Gateway launches dotnet <plugin>.dll --port {port} on a free port.
  2. Initialize — once the plugin's gRPC server accepts connections, the Gateway calls Initialize and, on success, registers the plugin with its binder (channel manager, extractor registry, …). The plugin is now Running.
  3. Healthcheck — the Gateway calls HealthCheck every 30 seconds. An unhealthy response is logged; restarts are driven by the process actually exiting, not by failed healthchecks.
  4. Auto-restart — if the process exits unexpectedly, the Gateway restarts it with exponential backoff (1s, 2s, 4s, … capped at 60s). After 10 failed attempts it gives up and leaves the plugin in Error until an admin restarts it.

A crashing plugin cannot take down the Gateway — it's a separate process, and its channel configs surface an explicit error status (never a silent failure) until the plugin is healthy again.

Managing plugins

Settings → Plugins on the Dashboard (admin-only) lists every discovered plugin with its state, restart count, and any registration errors. From there you can:

  • Enable or disable the plugin system and edit the allowlist
  • Start and stop individual plugins — hot, with no Gateway restart
  • Trigger a rescan of the plugin directories

Everything is also available over REST: GET /api/plugins, GET /api/plugins/{id}, and POST /api/plugins/scan.

The manifest at a glance

Every plugin ships a manifest.json declaring what it is and what it needs:

{
  "name": "acme-chat-adapter",
  "version": "1.0.0",
  "description": "Channel adapter for the Acme in-house chat system",
  "author": "Your Name",
  "type": "plugin",
  "pluginInterface": "ChannelAdapter",
  "entrypoint": "AcmeChatAdapter.dll",
  "channelType": "acme-chat",
  "recipientMetadataKey": "channel",
  "settings": [
    { "name": "serverUrl", "displayName": "Server URL", "type": "string", "required": true },
    { "name": "apiToken", "displayName": "API Token", "type": "secret", "required": true }
  ]
}

pluginInterface picks the interface; channelType (for channel adapters) or supportedExtensions (for document extractors) declares what the plugin claims. The settings array drives the setup form in the Dashboard — entries with "type": "secret" are stored in the credential vault and masked in the UI, never persisted in plaintext config. Never put a real secret in a default: defaults are visible to any authenticated user via the listing endpoints.

See the Plugin Manifest Reference for the full schema and field-by-field rules.

Security model

Plugins are full-trust local code. Unlike skills, there is no sandbox: no container, no code signing, no resource limits, and unrestricted network access. A plugin runs with the same filesystem, network, and process privileges as the Gateway's own OS user. Process separation is a stability property — a crashing plugin can't take down the Gateway — not a security boundary. Keep the plugin system disabled unless you need it, use the Sophon:Plugins:Allow allowlist, and only install plugins from the Marketplace or sources you trust. If you want custom agent tools with real isolation, write a skill — skills run in the Docker + gVisor sandbox with resource limits and explicit network rules.

Building your own

Plugins are C# (.NET 10) projects that subclass PluginBase from the Sophon Plugin SDK and override the methods for their interface — OnConnectChannelAsync / OnSendChannelMessageAsync for a channel adapter, OnExtractDocumentAsync for a document extractor. The Gateway handles process management, gRPC wiring, and health monitoring; you write the integration logic.

The local development loop:

dotnet publish -c Release -o publish
sophon dev validate    # checks the manifest
sophon dev install     # stages the project for your local Gateway
# ... enable plugins, then POST /api/plugins/scan ...
sophon dev build       # packages a .sophon-plugin archive for distribution

DevStudio gives you an IDE environment for authoring and testing alongside your skills and agents.

Where to go next