Brainarr API Reference
June 1, 2026 · View on GitHub
Core Interfaces
IAIProvider
The primary interface that all AI providers must implement to integrate with Brainarr.
public interface IAIProvider
{
Task<List<Recommendation>> GetRecommendationsAsync(string prompt);
Task<bool> TestConnectionAsync();
string ProviderName { get; }
void UpdateModel(string modelName);
string? GetLastUserMessage();
string? GetLearnMoreUrl();
}
Methods
GetRecommendationsAsync
Gets music recommendations based on the provided prompt.
Parameters:
prompt(string): The prompt containing user's music library and preferences
Returns:
Task<List<Recommendation>>: A list of recommended albums with metadata
Example:
var provider = new OllamaProvider(baseUrl, model, httpClient, logger);
var recommendations = await provider.GetRecommendationsAsync(
"Based on my library of Pink Floyd, Led Zeppelin, recommend similar albums"
);
TestConnectionAsync
Tests the connection to the AI provider.
Parameters:
- None
Returns:
Task<bool>: True if the connection is successful; otherwise, false
Example:
if (await provider.TestConnectionAsync())
{
logger.Info("Provider is available");
}
Properties
ProviderName
Gets the display name of the provider.
Type: string
Access: Read-only
UpdateModel
Updates the model used by the provider dynamically.
Parameters:
modelName(string): The new model name to use
Returns:
void
Example:
// Switch from default model to a more powerful one
provider.UpdateModel("llama3.1:70b");
Notes:
- Not all providers support dynamic model updates
- Model name must be valid for the provider
- Throws
InvalidOperationExceptionif model is not available
IAIService
Main orchestrator service for AI providers. Manages provider chains, failover, and health monitoring.
public interface IAIService
{
Task<List<Recommendation>> GetRecommendationsAsync(string prompt);
Task<Dictionary<string, bool>> TestAllProvidersAsync();
Task<Dictionary<string, ProviderHealthInfo>> GetProviderHealthAsync();
void RegisterProvider(IAIProvider provider, int priority = 100);
void UpdateConfiguration(BrainarrSettings settings);
AIServiceMetrics GetMetrics();
}
Methods
GetRecommendationsAsync
Gets recommendations using the configured provider chain with automatic failover.
Parameters:
prompt(string): The prompt to send to AI providers
Returns:
Task<List<Recommendation>>: List of recommendations from the first successful provider
Behavior:
- Attempts providers in priority order
- Automatically falls back to secondary providers on failure
- Caches successful responses based on configuration
TestAllProvidersAsync
Tests connectivity to all configured providers.
Returns:
Task<Dictionary<string, bool>>: Dictionary of provider names and their connection status
GetProviderHealthAsync
Gets the health status of all providers.
Returns:
Task<Dictionary<string, ProviderHealthInfo>>: Dictionary of provider names and their health information
RegisterProvider
Registers a new provider with the service.
Parameters:
provider(IAIProvider): Provider to registerpriority(int): Priority in the failover chain (lower = higher priority, default: 100)
UpdateConfiguration
Updates the configuration for all providers.
Parameters:
settings(BrainarrSettings): Updated settings
GetMetrics
Gets metrics for all provider usage.
Returns:
AIServiceMetrics: Provider usage metrics including request counts, response times, and error rates
ILibraryAnalyzer
Analyzes the user's music library to generate context for AI recommendations.
public interface ILibraryAnalyzer
{
LibraryProfile AnalyzeLibrary();
string BuildPrompt(LibraryProfile profile, int maxRecommendations, DiscoveryMode discoveryMode);
List<ImportListItemInfo> FilterDuplicates(List<ImportListItemInfo> recommendations);
}
Methods
AnalyzeLibrary
Analyzes the music library to create a profile.
Parameters:
- None - retrieves data directly from Lidarr services
Returns:
LibraryProfile: Analyzed library profile with genre distribution, era preferences, etc.
BuildPrompt
Builds a prompt for AI recommendations based on the library profile.
Parameters:
profile(LibraryProfile): The analyzed library profilemaxRecommendations(int): Maximum number of recommendations to requestdiscoveryMode(DiscoveryMode): Discovery mode (Similar, Adjacent, or Exploratory)
Returns:
string: Formatted prompt string for AI providers
FilterExistingRecommendations
Normalizes artist and album metadata (HTML decoding, article trimming, whitespace collapsing) and removes any recommendations already present in Lidarr before enrichment. Artist mode enforces unique artists; album mode considers both the artist and album title.
Parameters:
recommendations(List): Raw AI recommendations artistMode(bool): Whentrue, treat the request as artist-only
Returns:
List<Recommendation>: Filtered recommendations to continue through enrichment
FilterDuplicates
Filters the post-enrichment import items, removing duplicate artist/album combinations and recording the normalized keys for historical tracking. Album mode allows multiple entries from the same artist provided the album titles differ.
Parameters:
recommendations(List): Import items ready for Lidarr
Returns:
List<ImportListItemInfo>: Filtered list without duplicates
Data Models
Recommendation
Represents a music recommendation with metadata.
public record Recommendation
{
public string Artist { get; init; }
public string Album { get; init; }
public string? Genre { get; init; }
public double Confidence { get; init; }
public bool ConfidenceProvided { get; init; }
public string? Reason { get; init; }
public int? Year { get; init; } // Preferred: Release year of the album
public int? ReleaseYear { get; init; } // Alternative property name for Year
public string? Source { get; init; } // Source provider identifier
public string? Provider { get; init; } // Provider that made the recommendation
public string? MusicBrainzId { get; init; } // MusicBrainz ID for the recommendation
public string? ArtistMusicBrainzId { get; init; } // Artist MusicBrainz ID
public string? AlbumMusicBrainzId { get; init; } // Album MusicBrainz ID
public string? SpotifyId { get; init; } // Spotify ID for the album
}
Properties
- Artist (string): The artist name
- Album (string): The album title
- Genre (string): The music genre (optional)
- Confidence (double): Confidence score from 0.0 to 1.0
- Reason (string): Explanation for why this album was recommended (optional)
- Year (int?): Release year of the album (preferred property)
- ReleaseYear (int?): Alternative property name for Year (optional)
- Source (string): Source provider identifier (optional)
- Provider (string): Provider that made this recommendation (optional)
- MusicBrainzId (string): MusicBrainz ID for the recommendation (optional)
- ArtistMusicBrainzId (string): Artist MusicBrainz ID (optional)
- AlbumMusicBrainzId (string): Album MusicBrainz ID (optional)
- SpotifyId (string): Spotify ID for the album (optional)
ProviderHealthInfo
Health information for a provider.
public class ProviderHealthInfo
{
public string ProviderName { get; set; }
public HealthStatus Status { get; set; }
public double SuccessRate { get; set; }
public double AverageResponseTime { get; set; }
public int TotalRequests { get; set; }
public int FailedRequests { get; set; }
public string LastError { get; set; }
public bool IsAvailable { get; set; }
}
Properties
- ProviderName (string): Name of the provider
- Status (HealthStatus): Current health status (Healthy, Degraded, Unhealthy)
- SuccessRate (double): Success rate as a percentage (0-100)
- AverageResponseTime (double): Average response time in milliseconds
- TotalRequests (int): Total number of requests made
- FailedRequests (int): Number of failed requests
- LastError (string): Description of the last error encountered
- IsAvailable (bool): Whether the provider is currently available
AIServiceMetrics
Metrics for provider usage.
public class AIServiceMetrics
{
public Dictionary<string, int> RequestCounts { get; set; }
public Dictionary<string, double> AverageResponseTimes { get; set; }
public Dictionary<string, int> ErrorCounts { get; set; }
public Dictionary<string, long> TotalTokensUsed { get; set; }
public int TotalRequests { get; set; }
public int SuccessfulRequests { get; set; }
public int FailedRequests { get; set; }
}
Properties
- RequestCounts: Number of requests per provider
- AverageResponseTimes: Average response time per provider (ms)
- ErrorCounts: Number of errors per provider
- TotalTokensUsed: Total tokens consumed per provider
- TotalRequests: Total requests across all providers
- SuccessfulRequests: Total successful requests
- FailedRequests: Total failed requests
Provider Implementations
Local Providers
OllamaProvider
Local AI provider using Ollama for privacy-focused recommendations.
Constructor:
public OllamaProvider(
string baseUrl, // Default: http://localhost:11434
string model, // Default: qwen2.5:latest
IHttpClient httpClient,
Logger logger
)
Features:
- 100% local processing
- No data leaves your network
- Supports multiple open-source models
- Automatic model detection
LMStudioProvider
Dedicated local AI provider implementation with GUI interface for easy model management. This is a separate implementation from OllamaProvider, specifically designed for LM Studio's OpenAI-compatible API.
Constructor:
public LMStudioProvider(
string baseUrl, // Default: http://localhost:1234
string model, // Default: local-model (or any loaded model)
IHttpClient httpClient,
Logger logger
)
Features:
- User-friendly desktop application
- Uses OpenAI-compatible endpoint (
/v1/chat/completions) - Automatic model downloading from Hugging Face
- GUI for configuration
- Wide model compatibility
Implementation Note:
LMStudioProvider is a dedicated class in LocalAIProvider.cs that uses the OpenAI-compatible API format, while OllamaProvider uses Ollama's native API format.
Cloud Providers
OpenAIProvider
OpenAI provider for GPT model recommendations.
Constructor:
public OpenAIProvider(
IHttpClient httpClient,
Logger logger,
string apiKey, // Required
string model // Default: gpt-4o-mini
)
Supported Models:
- gpt-4o
- gpt-4o-mini
- gpt-4-turbo
- gpt-3.5-turbo
AnthropicProvider
Anthropic provider for Claude model recommendations.
Constructor:
public AnthropicProvider(
IHttpClient httpClient,
Logger logger,
string apiKey, // Required
string model // Default: claude-3-5-haiku-latest
)
Supported Models:
- claude-3-5-sonnet-latest
- claude-3-5-haiku-latest
- claude-3-opus-latest
GeminiProvider
Google Gemini provider with free tier support.
Constructor:
public GeminiProvider(
IHttpClient httpClient,
Logger logger,
string apiKey, // Required (free at aistudio.google.com)
string model // Default: gemini-2.5-flash
)
Supported Models:
- gemini-2.5-flash (free tier)
- gemini-2.5-pro
- gemini-2.0-flash
Additional Providers
- DeepSeekProvider: Budget-friendly with 10-20x lower costs
- GroqProvider: Ultra-fast inference speeds
- OpenRouterProvider: Gateway to 200+ models
- PerplexityProvider: Web-enhanced responses
Configuration
BrainarrSettings
Main configuration class for the plugin.
public class BrainarrSettings
{
// Provider Configuration
public AIProvider Provider { get; set; }
public string ApiKey { get; set; }
public string ModelName { get; set; }
// Discovery Settings
public DiscoveryMode DiscoveryMode { get; set; }
public int MaxRecommendations { get; set; }
public double MinimumConfidence { get; set; }
// Performance Settings
public int CacheDurationMinutes { get; set; }
public bool EnableAutoDetection { get; set; }
public int RequestTimeoutSeconds { get; set; }
// Advanced Settings
public List<string> ProviderChain { get; set; }
public bool EnableHealthMonitoring { get; set; }
public bool LogProviderRequests { get; set; }
}
Enumerations
AIProvider
public enum AIProvider
{
Ollama = 0,
LMStudio = 1,
Perplexity = 2,
OpenAI = 3,
Anthropic = 4,
OpenRouter = 5,
DeepSeek = 6,
Gemini = 7,
Groq = 8,
ClaudeCodeSubscription = 9,
OpenAICodexSubscription = 10,
ClaudeCodeCli = 11,
ZaiGlm = 12,
ZaiCoding = 13
}
DiscoveryMode
public enum DiscoveryMode
{
Similar, // Very similar to existing library
Adjacent, // Related genres and styles
Exploratory // New genres and territories
}
HealthStatus
public enum HealthStatus
{
Healthy,
Degraded,
Unhealthy,
Unknown
}
Error Handling
Common Exceptions
ProviderNotFoundException
Thrown when a specified provider cannot be found or initialized.
ProviderUnavailableException
Thrown when all providers in the chain are unavailable.
InvalidApiKeyException
Thrown when an API key is invalid or missing for cloud providers.
RateLimitExceededException
Thrown when provider rate limits are exceeded.
Error Codes
BR001: Provider initialization failed - The AI provider could not be initialized. Check provider configuration and dependencies.BR002: API key validation failed - The provided API key is invalid or expired. Verify your API key in settings.BR003: Connection timeout - Request to provider timed out. Check network connectivity and increase timeout if needed.BR004: Rate limit exceeded - Provider's rate limit has been reached. Wait before retrying or upgrade your plan.BR005: Invalid response format - Provider returned unexpected response format. Check provider version compatibility.BR006: Model not found - Specified model is not available for this provider. Use GetAvailableModelsAsync() to list valid models.BR007: Insufficient quota - API quota exhausted. Check your provider account balance or usage limits.BR008: Provider health check failed - Provider is unhealthy or unavailable. Check provider status and logs.
Usage Examples
Basic Usage
// Initialize a provider
var provider = new OllamaProvider(
"http://localhost:11434",
"qwen2.5:latest",
httpClient,
logger
);
// Test connection
if (await provider.TestConnectionAsync())
{
// Get recommendations
var prompt = "I love Pink Floyd and Led Zeppelin";
var recommendations = await provider.GetRecommendationsAsync(prompt);
foreach (var rec in recommendations)
{
Console.WriteLine($"{rec.Artist} - {rec.Album} ({rec.Confidence:P})");
}
}
Using AIService with Failover
// Create service with multiple providers
var aiService = new AIService(httpClient, logger, settings);
// Register providers with priorities
aiService.RegisterProvider(ollamaProvider, priority: 1);
aiService.RegisterProvider(openAIProvider, priority: 2);
aiService.RegisterProvider(anthropicProvider, priority: 3);
// Get recommendations with automatic failover
var recommendations = await aiService.GetRecommendationsAsync(prompt);
// Check provider health
var health = await aiService.GetProviderHealthAsync();
foreach (var (provider, info) in health)
{
Console.WriteLine($"{provider}: {info.Status} ({info.SuccessRate:P})");
}
Library Analysis
var styleCatalog = new StyleCatalogService(logger, httpClient: null);
var analyzer = new LibraryAnalyzer(artistService, albumService, styleCatalog, logger);
// Analyze library
var profile = analyzer.AnalyzeLibrary();
// Generate context for different discovery modes
var similarContext = analyzer.BuildPrompt(profile, 20, DiscoveryMode.Similar);
var exploratoryContext = analyzer.BuildPrompt(profile, 20, DiscoveryMode.Exploratory);
// Use with provider
var recommendations = await provider.GetRecommendationsAsync(similarContext);
// Filter out duplicates
var filtered = analyzer.FilterDuplicates(recommendations);
Best Practices
Provider Selection
- Privacy-First: Use Ollama or LM Studio for complete data privacy
- Cost-Effective: Use DeepSeek or Gemini free tier for budget constraints
- Quality-First: Use OpenAI GPT-4 or Anthropic Claude for best results
- Speed-First: Use Groq for fastest response times
Performance Optimization
- Enable Caching: Set appropriate cache duration (30-60 minutes recommended)
- Use Provider Chains: Configure fallback providers for reliability
- Monitor Health: Enable health monitoring to track provider performance
- Optimize Prompts: Use concise, focused prompts to reduce token usage
Error Handling
- Implement Retries: Use exponential backoff for transient failures
- Log Errors: Enable diagnostic logging for troubleshooting
- Handle Rate Limits: Implement rate limiting per provider
- Validate Responses: Check response format before processing
Security
- Protect API Keys: Never commit keys to source control
- Use Environment Variables: Store keys in environment variables
- Rotate Keys: Regularly rotate API keys for cloud providers
- Monitor Usage: Track API usage to detect anomalies
Troubleshooting
Provider Not Detected
// Enable auto-detection
settings.EnableAutoDetection = true;
// Or manually specify provider
settings.Provider = AIProvider.Ollama;
settings.ModelName = "qwen2.5:latest";
Connection Issues
// Increase timeout
settings.RequestTimeoutSeconds = 120;
// Enable detailed logging
settings.LogProviderRequests = true;
// Test specific provider
var isAvailable = await provider.TestConnectionAsync();
Poor Recommendations
// Adjust discovery mode
settings.DiscoveryMode = DiscoveryMode.Similar;
// Increase minimum confidence
settings.MinimumConfidence = 0.7;
// Use better model
settings.ModelName = "gpt-4o"; // or "claude-3-5-sonnet-latest"
Version History
v1.0.0
- Initial release with 8 AI providers
- Multi-provider support with failover
- Health monitoring and metrics
- Comprehensive caching system
- Library analysis and profiling
Additional Resources
- Architecture Documentation
- Provider Setup Guide
- User Setup Guide
- Contributing Guide
- Development Guide
Provider UI Actions
Certain UI operations are handled via provider actions without changing existing contracts. These actions are invoked by the UI layer and routed to /api/v1/brainarr/provider/action.
-
getModelOptions:
- Returns:
{ options: [{ value: string, name: string }] }
- Returns:
-
testconnection/details:
- Returns:
{ success: boolean, provider: string, hint?: string, message: string, docs?: string } - Purpose: provide structured connection test details alongside a user-facing hint when available (e.g., Google Gemini SERVICE_DISABLED activation URL).
- Notes:
hintis provider-specific and may be null.docslinks to the relevant wiki/GitHub docs section when available.
- Returns:
-
sanitycheck/commands:
- Returns:
{ provider: string, commands: string[] } - Purpose: provide copy-paste curl commands to sanity-check connectivity outside Brainarr (never includes real keys; uses placeholders like
YOUR_*_API_KEY). - Examples: Gemini model list, OpenAI/Anthropic/OpenRouter model list, local Ollama/LM Studio endpoints.
- Returns:
Dev UI example
- A simple HTML page demonstrating both actions lives at
examples/ui/testconnection_details.html. - See
docs/PROVIDER_GUIDE.mdfor usage notes.
Example: Test With Learn More Link (frontend)
async function testConnectionDetails(settings: any) {
const res = await fetch('/api/v1/brainarr/provider/action', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'testconnection/details', ...settings })
});
const data = await res.json(); // { success, provider, hint, message, docs }
if (!data.success) {
console.error(data.message, data.hint, data.docs);
}
return data;
}
Render hint + Learn more when present (docs URL points to GitHub docs):
{result && !result.success && (
<div>
<div>{result.message || `Cannot connect to ${result.provider}`}</div>
{result.hint && <div>{result.hint}</div>}
{result.docs && (
<div>
<a href={result.docs} target="_blank" rel="noreferrer">Learn more</a>
</div>
)}
</div>
)}