Documentation Index
Fetch the complete documentation index at: https://www.getmaxim.ai/docs/llms.txt
Use this file to discover all available pages before exploring further.
Plugin Overview
Plugins provide middleware functionality in Bifrost:
- PreHook: Intercept and modify requests before they reach providers
- PostHook: Modify responses after providers return
- Cross-cutting concerns: Rate limiting, caching, logging, monitoring
- Custom logic: Add functionality without modifying core Bifrost code
type Plugin interface {
GetName() string
PreHook(ctx *context.Context, req *BifrostRequest) (*BifrostRequest, *PluginShortCircuit, error)
PostHook(ctx *context.Context, result *BifrostResponse, err *BifrostError) (*BifrostResponse, *BifrostError, error)
Cleanup() error
}
Basic Plugin Examples
Simple Logging Plugin
type LoggingPlugin struct {
logger *log.Logger
}
func (p *LoggingPlugin) GetName() string {
return "logging"
}
func (p *LoggingPlugin) PreHook(ctx *context.Context, req *schemas.BifrostRequest) (*schemas.BifrostRequest, *schemas.PluginShortCircuit, error) {
p.logger.Printf("Request: Provider=%s, Model=%s", req.Provider, req.Model)
return req, nil, nil
}
func (p *LoggingPlugin) PostHook(ctx *context.Context, result *schemas.BifrostResponse, err *schemas.BifrostError) (*schemas.BifrostResponse, *schemas.BifrostError, error) {
if err != nil {
p.logger.Printf("Error: %s", err.Error.Message)
} else {
p.logger.Printf("Success: Provider=%s", result.ExtraFields.Provider)
}
return result, err, nil
}
func (p *LoggingPlugin) Cleanup() error {
return nil
}
Rate Limiting Plugin
type RateLimitPlugin struct {
requests map[string]int
mu sync.Mutex
limit int
}
func (p *RateLimitPlugin) PreHook(ctx *context.Context, req *schemas.BifrostRequest) (*schemas.BifrostRequest, *schemas.PluginShortCircuit, error) {
userID := p.extractUserID(*ctx)
p.mu.Lock()
count := p.requests[userID]
if count >= p.limit {
p.mu.Unlock()
// Rate limit exceeded - short circuit
return req, &schemas.PluginShortCircuit{
Error: &schemas.BifrostError{
StatusCode: &[]int{429}[0],
Error: schemas.ErrorField{
Message: "Rate limit exceeded",
},
},
}, nil
}
p.requests[userID] = count + 1
p.mu.Unlock()
return req, nil, nil
}
Response Caching Plugin
type CachePlugin struct {
cache map[string]*schemas.BifrostResponse
mu sync.RWMutex
}
func (p *CachePlugin) PreHook(ctx *context.Context, req *schemas.BifrostRequest) (*schemas.BifrostRequest, *schemas.PluginShortCircuit, error) {
cacheKey := p.generateCacheKey(req)
p.mu.RLock()
cached, exists := p.cache[cacheKey]
p.mu.RUnlock()
if exists {
// Return cached response - short circuit
return req, &schemas.PluginShortCircuit{
Response: cached,
}, nil
}
return req, nil, nil
}
func (p *CachePlugin) PostHook(ctx *context.Context, result *schemas.BifrostResponse, err *schemas.BifrostError) (*schemas.BifrostResponse, *schemas.BifrostError, error) {
if result != nil {
cacheKey := p.generateCacheKeyFromResponse(result)
p.mu.Lock()
p.cache[cacheKey] = result
p.mu.Unlock()
}
return result, err, nil
}
Learn More
For advanced plugin development and complete examples:
Using Plugins
// Add plugins to your Bifrost client
client, initErr := bifrost.Init(schemas.BifrostConfig{
Account: &MyAccount{},
Plugins: []schemas.Plugin{
NewLoggingPlugin(),
NewRateLimitPlugin(100), // 100 requests per user
NewCachePlugin(time.Hour), // 1 hour cache
},
})
defer client.Cleanup() // Calls Cleanup() on all plugins
Plugin Order: Plugins execute in the order they’re added. PreHooks run forward, PostHooks run in reverse order.