AI SDK
Plugins
Dynamic plugin system for extending SDK functionality
Plugin System
Dynamically load and execute plugins to extend SDK functionality.
Basic Plugin
type MyPlugin struct{}
func (p *MyPlugin) Name() string {
return "my-plugin"
}
func (p *MyPlugin) Version() string {
return "1.0.0"
}
func (p *MyPlugin) Execute(ctx context.Context, input interface{}) (interface{}, error) {
// Plugin logic here
return fmt.Sprintf("Processed: %v", input), nil
}
// Register
pluginSystem := sdk.NewPluginSystem(logger, metrics)
pluginSystem.RegisterPlugin(&MyPlugin{})
// Execute
result, err := pluginSystem.ExecutePlugin(ctx, "my-plugin", "input data")Plugin Interface
type Plugin interface {
// Plugin metadata
Name() string
Version() string
Description() string
// Lifecycle
Init(ctx context.Context, config map[string]interface{}) error
Execute(ctx context.Context, input interface{}) (interface{}, error)
Cleanup(ctx context.Context) error
// Health check
HealthCheck(ctx context.Context) error
}Complete Plugin Example
type TranslationPlugin struct {
apiKey string
logger forge.Logger
}
func (p *TranslationPlugin) Name() string {
return "translator"
}
func (p *TranslationPlugin) Version() string {
return "1.0.0"
}
func (p *TranslationPlugin) Description() string {
return "Translates text between languages"
}
func (p *TranslationPlugin) Init(ctx context.Context, config map[string]interface{}) error {
apiKey, ok := config["api_key"].(string)
if !ok {
return fmt.Errorf("api_key required")
}
p.apiKey = apiKey
p.logger = config["logger"].(forge.Logger)
return nil
}
func (p *TranslationPlugin) Execute(ctx context.Context, input interface{}) (interface{}, error) {
req := input.(map[string]interface{})
text := req["text"].(string)
targetLang := req["target_lang"].(string)
// Translation logic
translated, err := p.translate(ctx, text, targetLang)
if err != nil {
return nil, err
}
return map[string]interface{}{
"original": text,
"translated": translated,
"language": targetLang,
}, nil
}
func (p *TranslationPlugin) Cleanup(ctx context.Context) error {
// Cleanup resources
return nil
}
func (p *TranslationPlugin) HealthCheck(ctx context.Context) error {
// Check if service is available
return nil
}Plugin Registration
Manual Registration
plugin := &TranslationPlugin{}
pluginSystem.RegisterPlugin(plugin)With Configuration
err := pluginSystem.RegisterPlugin(&TranslationPlugin{}, map[string]interface{}{
"api_key": os.Getenv("TRANSLATION_API_KEY"),
"logger": logger,
})Dynamic Loading
// Load plugin from file (Go plugin system)
pluginSystem.LoadPlugin("./plugins/translator.so")
// Or from URL
pluginSystem.LoadPluginFromURL("https://plugins.example.com/translator.so")Plugin Execution
Simple Execution
result, err := pluginSystem.ExecutePlugin(ctx, "translator", map[string]interface{}{
"text": "Hello, world!",
"target_lang": "es",
})
translation := result.(map[string]interface{})
fmt.Println(translation["translated"]) // "¡Hola, mundo!"With Timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
result, err := pluginSystem.ExecutePlugin(ctx, "translator", input)Concurrent Execution
var wg sync.WaitGroup
results := make([]interface{}, len(inputs))
for i, input := range inputs {
wg.Add(1)
go func(i int, input interface{}) {
defer wg.Done()
result, _ := pluginSystem.ExecutePlugin(ctx, "plugin-name", input)
results[i] = result
}(i, input)
}
wg.Wait()Plugin Discovery
// List all plugins
plugins := pluginSystem.ListPlugins()
for _, plugin := range plugins {
fmt.Printf("%s v%s: %s\n",
plugin.Name(), plugin.Version(), plugin.Description())
}
// Get specific plugin
plugin, err := pluginSystem.GetPlugin("translator")
// Check if plugin exists
if pluginSystem.HasPlugin("translator") {
// Use plugin
}Plugin Lifecycle
// Initialize plugin
err := pluginSystem.InitPlugin(ctx, "translator", config)
// Execute plugin
result, err := pluginSystem.ExecutePlugin(ctx, "translator", input)
// Health check
err = pluginSystem.HealthCheckPlugin(ctx, "translator")
// Unload plugin
err = pluginSystem.UnregisterPlugin("translator")Real-World Examples
Content Moderation Plugin
type ModerationPlugin struct {
threshold float64
}
func (p *ModerationPlugin) Name() string {
return "content-moderator"
}
func (p *ModerationPlugin) Execute(ctx context.Context, input interface{}) (interface{}, error) {
text := input.(string)
// Check for inappropriate content
score := p.moderateContent(text)
return map[string]interface{}{
"safe": score < p.threshold,
"score": score,
"flagged": score >= p.threshold,
}, nil
}Data Enrichment Plugin
type EnrichmentPlugin struct {
database Database
}
func (p *EnrichmentPlugin) Execute(ctx context.Context, input interface{}) (interface{}, error) {
userID := input.(string)
// Fetch additional data
profile, _ := p.database.GetUserProfile(ctx, userID)
preferences, _ := p.database.GetPreferences(ctx, userID)
history, _ := p.database.GetHistory(ctx, userID)
return map[string]interface{}{
"profile": profile,
"preferences": preferences,
"history": history,
}, nil
}Custom Formatter Plugin
type FormatterPlugin struct{}
func (p *FormatterPlugin) Execute(ctx context.Context, input interface{}) (interface{}, error) {
data := input.(map[string]interface{})
format := data["format"].(string)
content := data["content"].(string)
switch format {
case "markdown":
return p.toMarkdown(content), nil
case "html":
return p.toHTML(content), nil
case "json":
return p.toJSON(content), nil
default:
return content, nil
}
}Plugin Chains
Execute multiple plugins in sequence:
chain := pluginSystem.CreateChain(
"moderator",
"enricher",
"formatter",
)
result, err := chain.Execute(ctx, input)Plugin Versioning
// Register multiple versions
pluginSystem.RegisterPlugin(&TranslatorV1{})
pluginSystem.RegisterPlugin(&TranslatorV2{})
// Execute specific version
result, _ := pluginSystem.ExecutePlugin(ctx, "translator@1.0.0", input)
// Execute latest
result, _ := pluginSystem.ExecutePlugin(ctx, "translator", input)Plugin Marketplace
marketplace := sdk.NewPluginMarketplace(
"https://plugins.example.com",
logger,
metrics,
)
// Browse plugins
plugins, _ := marketplace.ListAvailable()
// Install plugin
err := marketplace.Install("translator", "1.0.0")
// Update plugin
err = marketplace.Update("translator", "2.0.0")
// Uninstall plugin
err = marketplace.Uninstall("translator")Plugin Security
Sandboxing
pluginSystem := sdk.NewPluginSystem(logger, metrics, sdk.PluginConfig{
EnableSandbox: true,
MaxMemory: 100 * 1024 * 1024, // 100MB
MaxCPU: 0.5, // 50% of one core
Timeout: 30 * time.Second,
NetworkAccess: false, // No network
})Permission System
plugin := &MyPlugin{}
pluginSystem.RegisterPlugin(plugin, sdk.PluginPermissions{
FileAccess: sdk.ReadOnly,
NetworkAccess: sdk.AllowHTTPS,
DatabaseAccess: sdk.NoAccess,
})Monitoring
// Plugin metrics
stats := pluginSystem.GetStats("translator")
fmt.Printf("Executions: %d\n", stats.TotalExecutions)
fmt.Printf("Failures: %d\n", stats.Failures)
fmt.Printf("Avg duration: %v\n", stats.AvgDuration)
// Health monitoring
go func() {
ticker := time.NewTicker(1 * time.Minute)
for range ticker.C {
for _, name := range pluginSystem.ListPluginNames() {
if err := pluginSystem.HealthCheckPlugin(ctx, name); err != nil {
logger.Error("plugin unhealthy", "plugin", name, "error", err)
}
}
}
}()Best Practices
Error Handling
func (p *MyPlugin) Execute(ctx context.Context, input interface{}) (interface{}, error) {
// Validate input
if input == nil {
return nil, fmt.Errorf("input cannot be nil")
}
// Type assertion with check
data, ok := input.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("input must be map[string]interface{}")
}
// Execute with error handling
result, err := p.process(data)
if err != nil {
return nil, fmt.Errorf("processing failed: %w", err)
}
return result, nil
}Resource Cleanup
func (p *MyPlugin) Cleanup(ctx context.Context) error {
// Close connections
if p.conn != nil {
p.conn.Close()
}
// Release resources
if p.cache != nil {
p.cache.Clear()
}
return nil
}Graceful Degradation
func (p *MyPlugin) Execute(ctx context.Context, input interface{}) (interface{}, error) {
result, err := p.tryExecute(ctx, input)
if err != nil {
// Log error but return partial result
p.logger.Error("plugin failed, returning partial result", "error", err)
return p.getPartialResult(input), nil
}
return result, nil
}Next Steps
- Tools & Workflows - Use plugins in workflows
- Examples - Plugin examples
How is this guide?
Last updated on