Skip to main content

Plugin Categories & Capabilities

Every plugin in the Ever Works platform declares a category and one or more capabilities. The category determines how the platform classifies and displays the plugin, while capabilities define the interfaces the plugin implements and the operations it can perform.

Plugin Categories​

Categories are defined as a single source of truth in @ever-works/plugin via the PLUGIN_CATEGORIES constant, in packages/plugin/src/contracts/plugin-manifest.types.ts. It started at twelve entries and now carries twenty-seven — the last three joined with their owning epics: app-dependency (APW-07), build (APW-05) and identity (APW-12).

const PLUGIN_CATEGORIES = [
// The original twelve
'git-provider',
'deployment',
'screenshot',
'search',
'content-extractor',
'data-source',
'ai-provider',
'pipeline',
'form',
'integration',
'utility',
'theme',
// Infrastructure and communication sockets added since
'storage', // object storage: local disk, S3, MinIO, GitHub blobs
'database', // relational backend for a deployed Work
'email-provider', // outbound + inbound email transport
'notification-channel', // outbound-only chat delivery
'connector', // bidirectional channel plugins (send AND receive)
'vector-store', // embedding storage for the Knowledge Base
'dns', // DNS record management for deployed sites
'secret-store-resolver', // credential-pointer resolvers
'job-runtime', // background execution engines
'memory', // org-wide memory frameworks (contract only)
'rag', // composed retrieval pipelines (contract only)
'metrics', // read-only metric collectors for Goals
// Added with their owning App Works epics (2026)
'app-dependency', // dependency providers the app environment needs (APW-07)
'build', // build providers that turn a source repository into a deployable image (APW-05)
'identity' // identity providers for Ever ID browser sign-in (APW-12)
] as const;

type PluginCategory = (typeof PLUGIN_CATEGORIES)[number];

Each plugin declares exactly one category. The category is set on the plugin class and included in the plugin manifest.

Twenty-one of the twenty-seven carry at least one shipped plugin. The counts below come from the 105 plugin packages under packages/plugins/ (every directory there declares an everworks.plugin.category) — read from each package's everworks.plugin.category field. The remaining six (form, integration, theme, memory, rag and app-dependency) are contracts with nothing registered under them yet; app-dependency joined that list with APW-07, whose providers declare the deployment category and the app-dependency capability.

Category Overview​

Ordered the way the dashboard orders them at /plugins.

CategoryDescriptionExample Plugins
pipelineDefines the generation workflowStandard Pipeline (15 steps), Agent Pipeline (5 steps), Claude Code, Claude Managed Agent, Codex, Gemini CLI, OpenCode, Hermes Agent, Go-to-Market, Make.com, SIM AI, Zapier, Composio, Activepieces (14)
ai-providerProvides AI model access for content generationOpenAI, Anthropic, Google, Grok, Groq, Mistral, Ollama, LM Studio, vLLM, OpenRouter, Vercel AI Gateway (11)
searchWeb search for discovering work itemsTavily, Exa, SerpAPI, Brave, Perplexity, Bright Data, Firecrawl, Valyu, Linkup (9)
content-extractorExtracts structured content from URLsLocal Content Extractor, Jina, Notion Extractor, PDF Extractor, OfficeCLI Extractor, Scrapfly (6)
screenshotCaptures website screenshotsScreenshotOne, Urlbox (2). Scrapfly also serves this capability from the content-extractor category
git-providerGit hosting API operations and local gitGitHub (1)
deploymentDeploys generated works to hosting platformsVercel, Kubernetes (2)
data-sourceImports items from external data APIsApify (1)
storageObject-storage backends for every uploaded byteLocal Filesystem, AWS S3, MinIO, GitHub Storage (4)
databaseRelational backend for a deployed WorkPostgreSQL DB (1)
vector-storeEmbedding storage and similarity search for the Knowledge Basepgvector, Qdrant (2)
dnsCreates, probes and removes DNS records for deployed sitesCloudflare DNS (1)
email-providerOutbound and inbound email transportResend, SendGrid, Postmark, Mailgun, Mailchimp Transactional (5)
notification-channelOutbound-only delivery of a notification to a chat targetSlack, Discord, Telegram, WhatsApp, Novu (5)
job-runtimeBackground execution engine behind every queued jobTrigger.dev, Temporal, BullMQ, pg-boss, Inngest, Fleet Node (6)
secret-store-resolverTurns an opaque credential pointer into a credential bagHashiCorp Vault, Kubernetes, AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, Doppler, Infisical (7)
formProvides custom form fields for the generator UINone — pipeline plugins contribute fields through the form-schema-provider capability instead
integrationThird-party service integrationsNone registered today — outside systems arrive through connector and notification-channel
utilityGeneral-purpose utilitiesComparison Generator, Agent Memory, Memory Pipeline Modifier, Browser Automation, Ever Works Skills, Ever Works Task Tracker, Langfuse, Local Workspace, Sandbox Workspace, Local PTY host (10)
themeVisual theme customizationNone registered today
connectorBidirectional channel plugins — send outbound and accept inboundSlack, Discord, Linear, Notion, Jira, Zoom, Google Workspace, HubSpot, Pipedrive, Bluesky, Mastodon (11)
metricsRead-only metric collectors that Goals are evaluated againstStripe, PostHog, Google Analytics, Custom HTTP (4)
memoryOrg-wide memory frameworks — storage, retrieval and synthesisNone — contract only (IMemoryPlugin)
ragComposed retrieval pipelines orchestrating extractor, embedder and storeNone — contract only (IRagPlugin)

The five categories with no plugin yet​

They are all valid manifest values — isPluginCategory('theme') returns true — so a community plugin can fill any of them without a platform change. Nothing in the product depends on them today.

CategoryWhy it is empty
formCustom generator-form fields are contributed by the form-schema-provider capability, which every pipeline plugin declares. No plugin needs form as its category.
integrationSuperseded in practice: bidirectional systems register as connector, outbound-only ones as notification-channel.
themeOpen socket. The look of a generated site currently comes from its template, not from a plugin.
memoryContract only (capabilities/memory.interface.ts). The org-wide Memory surface and the per-Work Knowledge Base do not route through it.
ragContract only (capabilities/rag.interface.ts). Knowledge Base retrieval composes a content extractor, an AI provider and a vector store directly rather than behind one IRagPlugin contract.

Where each category is documented​

Every category that ships a plugin has a user-facing page describing what it does in the product, not just in the manifest.

CategoryRead next
ai-providerAI Provider Plugins · Bring your own AI provider
searchSearch Plugins
content-extractorContent Extraction Plugins
screenshotScreenshotOne · Urlbox
git-providerGitHub Plugin · Git Operations
deploymentDeployment Plugins · Kubernetes Deployment
data-sourceData Source Plugins
pipelinePipeline Plugins
storageStorage Backends
databaseManaged Hosting
vector-storeKnowledge Base
dnsCustom Domains · Managed Hosting
email-providerAgent Email & Inboxes · Notifications
notification-channelNotifications
connectorConnectors · Integrations
job-runtimeJob Runtimes · Workers
secret-store-resolverSecret Stores
metricsGoals
utilityBuilt-in Plugins
Everything elsePlugins — the dashboard view of all twenty-seven

Dashboard grouping and display order​

/plugins groups cards under category headings and offers one chip per category, using the label and icon maps in apps/web/src/lib/utils/plugin-category-icons.ts. The ids above are not what a reader sees — CATEGORY_LABELS renames several of them:

Category idDashboard label
content-extractorContent Processors
data-sourceData Sources
secret-store-resolverSecret Stores
job-runtimeJob Runtimes
notification-channelNotification Channels
email-providerEmail Providers
vector-storeVector Stores
databaseDatabases
dnsDNS Providers
memoryMemory Frameworks
ragRAG Pipelines

CATEGORY_DISPLAY_ORDER in the same file pins twenty of the twenty-seven into a fixed sequence. connector, metrics, memory, rag, app-dependency, build and identity are absent from that array, so compareCategoryOrder() sorts them to the end, after Themes. A chip only appears for a category that has at least one registered plugin on the install, which is why Memory Frameworks and RAG Pipelines never show up.

Plugin Capabilities​

Capabilities are the functional interfaces a plugin implements. A plugin can declare multiple capabilities. For example, the Exa plugin declares both search and content-extractor capabilities.

Capability Constants​

const PLUGIN_CAPABILITIES = {
AI_PROVIDER: 'ai-provider',
SEARCH: 'search',
SCREENSHOT: 'screenshot',
CONTENT_EXTRACTOR: 'content-extractor',
DATA_SOURCE: 'data-source',
PIPELINE: 'pipeline',
PIPELINE_MODIFIER: 'pipeline-modifier',
FORM_SCHEMA_PROVIDER: 'form-schema-provider',
DEPLOYMENT: 'deployment',
GIT_PROVIDER: 'git-provider',
OAUTH: 'oauth'
} as const;

That excerpt is the original set. The constant in packages/plugin/src/contracts/facade-capabilities.ts now holds 45 entries, validated by isValidPluginCapability() against ALL_PLUGIN_CAPABILITIES.

Capability Interfaces​

Each capability maps to a TypeScript interface that the plugin must implement:

CapabilityInterfaceRequired Methods
ai-providerIAiProviderPlugincreateChatCompletion(), listModels(), getModel(), isAvailable(), getCapabilities()
searchISearchPluginsearch(), isAvailable()
content-extractorIContentExtractorPluginextract(), isAvailable()
screenshotIScreenshotPlugincapture(), isAvailable()
data-sourceIDataSourcePluginquery(), isAvailable()
pipelineIPipelinePlugingetStepDefinitions(), execute()
pipeline-modifierIPipelineModifierPluginexecute(), targetPipelines
git-providerIGitProviderPlugingetAuth(), getCloneUrl(), createRepository(), getRepository(), createPullRequest(), mergePullRequest() + IGitOperations
deploymentIDeploymentPlugindeploy(), getDeploymentStatus()
oauthIOAuthPlugingetOAuthConfig(), exchangeCode(), getUser()
form-schema-providerIFormSchemaProvidergetFormFields(), getFormGroups()

Capability interfaces added since​

One *.interface.ts file per contract under packages/plugin/src/contracts/capabilities/ — 33 files in total.

CapabilityInterfaceRequired Methods
storageIStoragePluginputObject(), getObject(), deleteObject(), isAvailable(); presignPut() optional
datastoreIDatastorePluginisAvailable(), testDatabaseConnection()
vector-storeIVectorStorePluginupsertChunks(), queryChunks(), deleteByDocument(), deleteByWork(), isAvailable()
email-outboundIEmailOutboundPluginsendEmail(), verifyAddress()
email-inboundIEmailInboundPluginparseInboundWebhook(), verifyWebhookSignature()
notification-channelINotificationChannelPluginverifyTarget(), send()
connectorIConnectorPluginverifyConnection(), send(); parseInbound(), poll(), reply() optional
event-sourceIEventSourcePluginpullEvents(); backfill() optional
metrics-providerIMetricsProviderPluginlistMetrics(), getMetricValue()
secret-store-resolveISecretStoreProviderresolveSecret()
job-runtime-*IJobRuntimeProviderregisterSchedules(), cancel(), getRunStatus(), isEnabled()
dns-*IDnsProviderensureRecord(), removeRecord(), recordExists(), rootDomain()
skills-providerISkillsProviderPluginlistEntries(), getEntry()
task-trackerITaskTrackerPluginlistTasks(), getTask(), createTask(), updateTask(), deleteTask()
workspaceIWorkspacePluginprovision(), finalize(), simulateMerge(), teardown()
terminal-streamITerminalStreamPluginsession write() / resize() / kill(); relay publish() / inbound() / close()
agent-memoryIAgentMemoryPluginopenSession(), closeSession(), saveMemory(), searchMemory(), buildContext()
browser-automationIBrowserAutomationPluginopen(), navigate(), extract()
code-editICodeEditPluginexecuteCodeEdit()
prompt-providerIPromptProviderPlugingetPrompt(), isAvailable()
memoryIMemoryPluginindex(), search() — contract only, no plugin ships under it
ragIRagPluginingest(), retrieve(), getSupportedDocTypes() — contract only

Umbrella and verb capabilities​

Newer contracts split one job across several capability strings, so a manifest can advertise exactly what a plugin does:

PatternExample manifestWhy
Umbrella + one per providerSlack Connector: connector, connector-slack, event-sourceThe umbrella drives discovery and UI grouping; the provider-specific id lets the platform find that connector without hardcoding a plugin id.
Umbrella + optional extrasAWS S3: storage, put-object, get-object, presigned-putput-object and get-object are the floor. presigned-put is opt-in for backends that can hand the browser a direct-upload URL.
One per verb, no umbrellaCloudflare DNS: dns-ensure-record, dns-remove-record, dns-record-exists, dns-root-domainisDnsProvider() requires all four before the platform will route a record through the plugin.
One per verb, with an optional extraFleet Node: job-runtime-enqueue, -cancel, -status, -schedule, -worker-hostThe first four are required of every runtime; job-runtime-worker-host marks the pull-model runtimes that host their own workers.
A single verbHashiCorp Vault: secret-store-resolveA resolver does one thing.

Capability ids come from two places, and both are valid. The facade-routed set is enumerated in PLUGIN_CAPABILITIES. The newer contracts — vector-store, memory, rag, datastore, the DNS verbs, the job-runtime verbs, secret-store-resolve — declare their strings in their own interface file and are detected with a per-contract type guard rather than by looking them up in the constant.

Type Guards​

The plugin system provides type guard functions for each capability:

import {
isAiProviderPlugin,
isSearchPlugin,
isContentExtractorPlugin,
isScreenshotPlugin,
isDataSourcePlugin,
isPipelinePlugin,
isPipelineModifierPlugin,
isGitProviderPlugin,
isDeploymentPlugin
} from '@ever-works/plugin';

// Usage in facade or platform code
if (isSearchPlugin(plugin)) {
const results = await plugin.search({ query: 'example' });
}

The newer contracts follow the same naming: isStoragePlugin, isVectorStorePlugin, isConnectorPlugin, isNotificationChannelPlugin, isEmailOutboundPlugin, isEmailInboundPlugin, isEventSourcePlugin, isMetricsProviderPlugin, isSkillsProviderPlugin, isTaskTrackerPlugin, isWorkspacePlugin, isTerminalStreamPlugin, isAgentMemoryPlugin, isBrowserAutomationPlugin, isCodeEditPlugin, isPromptProviderPlugin, isMemoryPlugin and isRagPlugin — plus isDnsProvider, isFormSchemaProvider and isDeviceAuthProvider, which are named after the interface rather than suffixed Plugin.

Selectable Provider Categories​

Certain capabilities are selectable in the generator form UI. These are defined by SELECTABLE_PROVIDER_CATEGORIES:

const SELECTABLE_PROVIDER_CATEGORIES = {
search: { capability: 'search', uiKey: 'search', selectableInForm: true },
screenshot: { capability: 'screenshot', uiKey: 'screenshot', selectableInForm: true },
ai: { capability: 'ai-provider', uiKey: 'ai', selectableInForm: true },
contentExtractor: { capability: 'content-extractor', uiKey: 'contentExtractor', selectableInForm: true },
pipeline: { capability: 'pipeline', uiKey: 'pipeline', selectableInForm: true }
} as const;

When a user creates a work, they can select which plugin to use for each selectable category. Plugins that declare defaultForCapabilities in their manifest are pre-selected.

These five are still the whole list. None of the categories added since is chosen per Work in the generator form. Storage, job runtime and vector store are resolved from operator or tenant configuration — STORAGE_BACKEND, EVER_WORKS_JOB_RUNTIME (with the tenant overlay at /settings/job-runtime), KB_VECTOR_STORE_PROVIDER_ID — a secret store is picked by the scheme prefix of the credential pointer it is asked to resolve, and connectors, notification channels, email providers and metrics providers are chosen where they are used: a channel target, an Agent mailbox, a Goal.

Plugin Visibility​

Each plugin can set a visibility level in its manifest:

VisibilityBehavior
publicShown to all users in all plugin lists (default)
hiddenNever shown in the plugin UI; used for internal infrastructure plugins
user-onlyShown in user plugin settings but not in work plugin lists
note
operator is not a fourth level

The six job-runtime and seven secret-store-resolver packages declare visibility: 'operator' in their manifests. PluginVisibility has only the three values above, and the filters in packages/agent/src/plugins/services/plugin-operations.service.ts test for exactly 'hidden' and 'user-only' — so anything else, operator included, behaves as public, and those plugins do appear in the plugin lists. The word records intent; it does not hide anything.

Supplementary Plugins​

Plugins with supplementary: true in their manifest are excluded from manual provider selection dropdowns. They still declare their capability and auto-activate through URL-based routing in the facade layer. This is used for narrow-scope extractors like the Notion Extractor (activates only for notion.so URLs) and the PDF Extractor (activates only for .pdf URLs).

Multi-Capability Plugins​

A single plugin can implement multiple capabilities. This is common for search and content extraction:

PluginCapabilities
Exasearch, content-extractor
Tavilysearch, content-extractor
Firecrawlsearch, content-extractor
Bright Datasearch, content-extractor
Scrapflyscreenshot, content-extractor
GitHubgit-provider, oauth
Standard Pipelinepipeline, form-schema-provider
Agent Pipelinepipeline, form-schema-provider

The same pattern runs through the categories added since:

PluginCategoryCapabilities
Jinacontent-extractorsearch, content-extractor
Linkup, Valyusearchsearch, content-extractor
Verceldeploymentdeployment, oauth
Apifydata-sourcedata-source, form-schema-provider
Claude Codepipelinepipeline, form-schema-provider, code-edit
Codexpipelinepipeline, form-schema-provider, device-auth, code-edit
Composiopipelinepipeline, form-schema-provider, skills-provider
AWS S3, MinIOstoragestorage, put-object, get-object, presigned-put
GitHub Storagestoragestorage, put-object, get-object, lfs
PostgreSQL DBdatabasedatabase, datastore
Postmark, Mailgunemail-provideremail-outbound, email-inbound
Slack Connectorconnectorconnector, connector-slack, event-source
Cloudflare DNSdnsdns, dns-ensure-record, dns-remove-record, dns-record-exists, dns-root-domain
Fleet Nodejob-runtimejob-runtime-enqueue, job-runtime-cancel, job-runtime-status, job-runtime-schedule, job-runtime-worker-host

When a plugin provides multiple capabilities, the manifest's defaultForCapabilities array specifies which capabilities it should be the default provider for:

// A plugin with multiple capabilities, default for only one
{
capabilities: ['search', 'content-extractor'],
defaultForCapabilities: ['search']
}

Configuration Modes​

Every plugin declares a configurationMode that determines how its settings are managed:

ModeDescription
admin-onlyOnly platform admins can configure the plugin
user-requiredEach user must provide their own credentials (e.g., API keys)
hybridAdmins set global defaults; users can override with their own values

Most AI provider plugins use user-required since users provide their own API keys. Infrastructure plugins like GitHub use hybrid with admin-level OAuth app credentials and user-level tokens.

How to browse plugins by category​

In the dashboard​

  1. Open Plugins in the sidebar (/plugins).
  2. Pick a category chip — All, plus one chip per category that has at least one plugin registered on this install. Picking a chip flattens the grouped list into a single grid.
  3. Or type into the search box: it matches the plugin name, description, category and capabilities, so connector and secret-store-resolve both work as queries.
  4. To walk one category's settings, open /settings/plugins/<category> using the id from the table above — for example /settings/plugins/ai-provider or /settings/plugins/secret-store-resolver. The route validates the segment with isPluginCategory(), so a mistyped id returns a 404 — and so does a valid category with nothing enabled in it (every category except pipeline).

From the CLI​

# Every plugin, or just one category
ever-works plugins
ever-works plugins --category connector
ever-works plugins -c job-runtime

# What is installable on a dynamic-distribution install
ever-works plugins catalog

Over the API​

# All plugins, with your installation status
curl -H "Authorization: Bearer $TOKEN" http://localhost:3100/api/plugins

# One category
curl -H "Authorization: Bearer $TOKEN" "http://localhost:3100/api/plugins?category=notification-channel"

# The category-grouped settings navigation
curl -H "Authorization: Bearer $TOKEN" http://localhost:3100/api/plugins/settings-menu