Documentation Index
Fetch the complete documentation index at: https://docs.ensemble.ai/llms.txt
Use this file to discover all available pages before exploring further.
Plugin System Overview
Conductor’s plugin system enables you to extend the framework with custom operations, third-party integrations, and specialized functionality without modifying the core codebase.
What Are Plugins?
Plugins are packages that extend Conductor’s capabilities by:
- Adding custom operations (e.g.,
plasmic:render, unkey:validate)
- Integrating external services (Resend, Twilio, Plasmic, Payload CMS)
- Providing specialized functionality (authentication, data fetching, rendering)
- Working universally across all contexts (ensembles, pages, forms, APIs, webhooks)
Plugin Ecosystem
Core Package
@ensemble-edge/conductor - The core framework (native functionality)
- All AI providers (Anthropic, OpenAI, Cloudflare AI)
- All agent patterns (Think, Email, SMS, PDF, HTML, Data, API)
- Core authentication (Bearer, API Key, Cookie)
- Built-in operations (
http, transform, convert, code)
Plugin Packages
@conductor/* - Optional plugin packages for specific integrations
Planned Plugins:
@conductor/unkey - Unkey authentication and API key management
@conductor/resend - Resend email service
@conductor/twilio - Twilio SMS service
@conductor/plasmic - Plasmic visual builder integration
@conductor/payload - Payload CMS integration
@conductor/stripe - Stripe payments
Two Plugin Patterns
Conductor supports two plugin patterns to balance simplicity and power:
1. Functional Plugins (Simple)
For lightweight plugins that only need to transform configuration:
import { buildPlugin } from '@ensemble-edge/conductor'
export const simplePlugin = buildPlugin((options) => (config) => {
// Transform config, register operations, etc.
return {
...config,
operations: [
...config.operations,
{
name: 'simple:operation',
handler: simpleHandler,
metadata: {
name: 'simple:operation',
description: 'A simple operation',
contexts: ['all'],
}
}
]
}
})
Use Cases:
- Adding operations to the registry
- Modifying configuration
- Simple hooks without async setup
- Lightweight integrations
2. Lifecycle Plugins (Complex)
For plugins that need async initialization, external connections, or complex setup:
import type { LifecyclePlugin, PluginContext } from '@ensemble-edge/conductor'
export const complexPlugin: LifecyclePlugin = {
name: 'complex',
version: '1.0.0',
description: 'A complex plugin with lifecycle',
async initialize(context: PluginContext): Promise<void> {
// Async initialization
await connectToExternalService()
// Register operations
const operations = this.operations()
for (const op of operations) {
context.operationRegistry.register(op.name, op.handler, op.metadata)
}
context.logger.info('Complex plugin initialized')
},
operations() {
return [
{
name: 'complex:operation',
handler: complexHandler,
metadata: {
name: 'complex:operation',
description: 'A complex operation',
contexts: ['all'],
}
}
]
},
async shutdown(): Promise<void> {
// Cleanup resources
await disconnectFromExternalService()
}
}
Use Cases:
- Database connections
- External API initialization
- Complex state management
- Plugins with cleanup requirements
Global Plugin Registry
All plugins register their operations with the global PluginRegistry:
import { getPluginRegistry } from '@ensemble-edge/conductor'
const registry = getPluginRegistry()
// Register a custom operation
registry.register('custom:op', handler, {
name: 'custom:op',
description: 'Custom operation',
version: '1.0.0',
author: '@conductor/custom',
contexts: ['form', 'api'],
tags: ['custom', 'example']
})
// Operations work everywhere
await registry.execute({
operation: 'custom:op',
config: { foo: 'bar' }
}, context)
Universal Operations
Once registered, operations work in all contexts:
# In ensembles
agents:
- name: custom
operation: custom:op
config:
foo: bar
# In ensembles (via flow)
name: my-ensemble
trigger:
- type: http
path: /my-page
methods: [GET]
public: true
flow:
- name: custom-data
operation: custom:op
config:
foo: bar
# In forms, APIs, webhooks - everywhere!
Plugin Context
Plugins receive a PluginContext during initialization:
interface PluginContext {
operationRegistry: PluginRegistry // Register operations
env: ConductorEnv // Environment bindings
ctx: ExecutionContext // Cloudflare Workers context
config: Record<string, any> // Plugin configuration
logger: PluginLogger // Plugin-specific logger
}
Operation Discovery
Operations can be discovered and filtered:
// List all operations
const all = registry.list()
// List operations by context
const formOps = registry.listByContext('form')
// List operations by tag
const uiOps = registry.listByTag('ui')
// Get operation metadata
const meta = registry.getMetadata('plasmic:render')
console.log(meta.description, meta.version, meta.contexts)
Example: Plasmic Plugin
Here’s how a Plasmic plugin might work:
// @conductor/plasmic package
import type { LifecyclePlugin } from '@ensemble-edge/conductor'
export const plasmicPlugin: LifecyclePlugin = {
name: 'plasmic',
version: '1.0.0',
description: 'Render Plasmic components',
async initialize(context) {
// Initialize Plasmic connection
await initializePlasmicClient(context.config.apiKey)
// Register operations
context.operationRegistry.register('plasmic:render', {
async execute(operation, opContext) {
const { componentId, props } = operation.config
return await renderPlasmicComponent(componentId, props)
}
}, {
name: 'plasmic:render',
description: 'Render Plasmic component',
version: '1.0.0',
author: '@conductor/plasmic',
contexts: ['form', 'api'],
tags: ['ui', 'visual', 'render']
})
context.logger.info('Plasmic plugin initialized')
}
}
Usage in Ensembles:
# ensembles/home.yaml
name: home
description: Home page with Plasmic hero section
trigger:
- type: http
path: /
methods: [GET]
public: true
flow:
- name: render-hero
operation: plasmic:render
config:
componentId: hero-section
props:
title: ${input.title}
subtitle: ${input.subtitle}
- name: render-page
operation: html
config:
template: |
<div>{{ render-hero.output }}</div>
output:
_raw: ${render-page.output}
Creating Your Own Plugin
See the following guides:
Official Plugins
Browse the official plugin ecosystem:
Benefits
Universal Operations: Register once, use everywhere (ensembles, pages, forms, APIs, webhooks)
Type Safe: Full TypeScript support with type guards and helpers
Discoverable: Operations include metadata for documentation and discovery
Two Patterns: Simple functional plugins or complex lifecycle plugins
Edge Native: Plugins work on Cloudflare Workers edge network
Independent Versioning: Each plugin has its own version and release cycle
Next Steps