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:
| Interface | Status | What it does |
|---|---|---|
ChannelAdapter | ✔ Wired end-to-end | Adds 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-end | Adds 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. |
ModelProvider | Accepted — coming | The 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. |
EmbeddingProvider | Accepted — coming | Same story — accepted, runs, not yet wired into embedding generation. |
VaultBackend | Accepted — coming | Deferred: 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. |
Tool | Refused | Intentional. 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-extractorThe 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:
<dataDir>/plugins/— locally developed or hand-installed plugins (scanned first)<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 GatewayMarketplace plugin installs land in skills/installed/ through the same pipeline as skills — see Publishing to the Marketplace.
Lifecycle
- Spawn — the Gateway launches
dotnet <plugin>.dll --port {port}on a free port. - Initialize — once the plugin's gRPC server accepts connections, the Gateway calls
Initializeand, on success, registers the plugin with its binder (channel manager, extractor registry, …). The plugin is nowRunning. - Healthcheck — the Gateway calls
HealthCheckevery 30 seconds. An unhealthy response is logged; restarts are driven by the process actually exiting, not by failed healthchecks. - 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
Erroruntil 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 distributionDevStudio gives you an IDE environment for authoring and testing alongside your skills and agents.
Where to go next
- Plugin Manifest Reference — the full
manifest.jsonschema - Publishing to the Marketplace — distribute your plugin
- Skills — sandboxed agent tools, the right home for custom tools
- Channels Overview — the built-in channels plugin adapters sit alongside