Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.praison.ai/llms.txt

Use this file to discover all available pages before exploring further.

Custom Provider Registry

The Custom Provider Registry allows you to register custom LLM providers that extend PraisonAI’s capabilities beyond the built-in providers (OpenAI, Anthropic, Google via LiteLLM).
Important: This registry is for custom provider extensions only. Built-in providers (OpenAI, Anthropic, Google, etc.) are handled automatically by LiteLLM in praisonaiagents. You only need this registry when integrating providers not supported by LiteLLM.

What Problem Does It Solve?

  • Integrate proprietary or internal LLM APIs
  • Add support for new providers before LiteLLM supports them
  • Create mock providers for testing
  • Build custom routing or caching layers

Quick Start

from praisonai.llm import register_llm_provider, create_llm_provider

# Define a custom provider
class MyCustomProvider:
    provider_id = "my-custom"
    
    def __init__(self, model_id, config=None):
        self.model_id = model_id
        self.config = config or {}
    
    def generate(self, prompt):
        # Your implementation here
        return f"Response from {self.model_id}"

# Register the provider
register_llm_provider("my-custom", MyCustomProvider)

# Use it
provider = create_llm_provider("my-custom/my-model")

Thread Safety

Enhanced in PR #1597: LLMProviderRegistry is now thread-safe with singleton access and RLock protection for all operations.
All registry methods (register, unregister, resolve, alias lookup, and listing) are safe to call concurrently from threads. Built-in providers are registered automatically on first instantiation. Singleton access pattern (preferred for app code):
from praisonai.llm.registry import LLMProviderRegistry

registry = LLMProviderRegistry.get_instance()  # double-checked-locked singleton
The existing helpers register_llm_provider / create_llm_provider continue to work unchanged (backwards compatible).

How Provider Resolution Works

The registry resolves providers in this order:

1. Explicit Provider Format: provider/model

# Explicitly specify provider
provider = create_llm_provider("cloudflare/workers-ai-model")
# Resolves to: provider_id="cloudflare", model_id="workers-ai-model"

2. Model Prefix Inference

When no provider is specified, the model name prefix determines the provider:
Model PrefixInferred Provider
gpt-*, o1*, o3*openai
claude-*anthropic
gemini-*google
Otheropenai (default)
# These are equivalent:
create_llm_provider("gpt-4o-mini")
create_llm_provider("openai/gpt-4o-mini")

# These are equivalent:
create_llm_provider("claude-3-5-sonnet")
create_llm_provider("anthropic/claude-3-5-sonnet")

3. Custom Provider with Explicit Name

# After registering "cloudflare"
create_llm_provider("cloudflare/workers-ai")
# Resolves to your registered CloudflareProvider

Registering Custom Providers Safely

Unique Name Rules

Provider names must be unique. Attempting to register a duplicate name raises an error:
register_llm_provider("my-provider", MyProvider)
register_llm_provider("my-provider", AnotherProvider)  # Raises ValueError!
Error message:
ValueError: Provider 'my-provider' is already registered. Use override=True to replace it.

Alias Rules

Aliases provide alternative names for a provider:
register_llm_provider("cloudflare", CloudflareProvider, aliases=["cf", "workers-ai"])

# All of these now work:
create_llm_provider("cloudflare/model")
create_llm_provider("cf/model")
create_llm_provider("workers-ai/model")
Alias collision detection:
register_llm_provider("provider-a", ProviderA, aliases=["shared"])
register_llm_provider("provider-b", ProviderB, aliases=["shared"])  # Raises ValueError!
Error message:
ValueError: Alias 'shared' is already registered (points to 'provider-a'). Use override=True to replace it.

Override Flag

Use override=True only when you intentionally want to replace an existing registration:
# Replace existing provider
register_llm_provider("my-provider", NewProvider, override=True)
Avoid using override=True carelessly - it can break other code that depends on the original provider.

Avoiding Collisions

Use a namespace prefix to avoid collisions:
# Good: namespaced provider names
register_llm_provider("mycompany-internal-llm", InternalProvider)
register_llm_provider("myproject-mock", MockProvider)

# Avoid: generic names that might conflict
register_llm_provider("custom", CustomProvider)  # Too generic
register_llm_provider("llm", LLMProvider)  # Too generic

Reserved Names

These provider names are reserved for model prefix inference and should not be used for custom providers:
  • openai - Used for gpt-, o1, o3* models
  • anthropic - Used for claude-* models
  • google - Used for gemini-* models
You can register these names, but it will override the default inference behavior. Only do this if you’re intentionally replacing the built-in provider resolution.

Multi-Agent Guidance

Global Registry (Default)

The default global registry is shared across all code:
from praisonai.llm import register_llm_provider

# This affects all code using the default registry
register_llm_provider("shared-provider", SharedProvider)

Isolated Registry (Per Agent/Run)

For multi-agent scenarios where you need isolation:
from praisonai.llm import LLMProviderRegistry, create_llm_provider

# Create isolated registries
agent1_registry = LLMProviderRegistry()
agent2_registry = LLMProviderRegistry()

# Register different providers to each
agent1_registry.register("custom", Agent1Provider)
agent2_registry.register("custom", Agent2Provider)

# Use with create_llm_provider
provider1 = create_llm_provider("custom/model", registry=agent1_registry)
provider2 = create_llm_provider("custom/model", registry=agent2_registry)

# provider1 and provider2 are different instances from different classes
Benefits of isolated registries:
  • No global state mutation
  • Safe for concurrent/parallel agent runs
  • Each agent can have its own provider configuration
  • Testing isolation

API Reference

register_llm_provider

register_llm_provider(
    name: str,
    provider: ProviderClass | ProviderFactory,
    *,
    override: bool = False,
    aliases: list[str] | None = None
) -> None

create_llm_provider

create_llm_provider(
    input_value: str | dict | ProviderInstance,
    *,
    registry: LLMProviderRegistry | None = None,
    config: dict | None = None
) -> ProviderInstance

LLMProviderRegistry

class LLMProviderRegistry:
    def register(name, provider, *, override=False, aliases=None) -> None
    def unregister(name) -> bool
    def has(name) -> bool
    def list() -> list[str]
    def list_all() -> list[str]  # Includes aliases
    def resolve(name, model_id, config=None) -> ProviderInstance
    def get(name) -> ProviderClass | None

Utility Functions

from praisonai.llm import (
    get_default_llm_registry,  # Get global registry
    has_llm_provider,          # Check if provider exists
    list_llm_providers,        # List registered providers
    unregister_llm_provider,   # Remove a provider
    parse_model_string,        # Parse "provider/model" strings
)

Minimal Example

from praisonai.llm import register_llm_provider, create_llm_provider

class EchoProvider:
    """Simple provider that echoes input."""
    provider_id = "echo"
    
    def __init__(self, model_id, config=None):
        self.model_id = model_id
        self.config = config or {}
    
    def generate(self, prompt):
        return f"[{self.model_id}] Echo: {prompt}"

# Register
register_llm_provider("echo", EchoProvider)

# Use
provider = create_llm_provider("echo/v1")
print(provider.generate("Hello!"))
# Output: [v1] Echo: Hello!

Troubleshooting

Common Errors

“Provider ‘X’ is already registered”
# Problem: Duplicate registration
register_llm_provider("my-provider", ProviderA)
register_llm_provider("my-provider", ProviderB)  # Error!

# Solution 1: Use a different name
register_llm_provider("my-provider-v2", ProviderB)

# Solution 2: Override intentionally
register_llm_provider("my-provider", ProviderB, override=True)
“Unknown provider: ‘X’”
# Problem: Provider not registered
provider = create_llm_provider("unregistered/model")  # Error!

# Solution: Register first
register_llm_provider("unregistered", MyProvider)
provider = create_llm_provider("unregistered/model")
“Alias ‘X’ conflicts with existing provider”
# Problem: Alias matches an existing provider name
register_llm_provider("provider-a", ProviderA)
register_llm_provider("provider-b", ProviderB, aliases=["provider-a"])  # Error!

# Solution: Use a unique alias
register_llm_provider("provider-b", ProviderB, aliases=["alias-b"])

Performance Notes

  • Lazy imports: The registry module only imports typing - no heavy dependencies
  • Import time: ~800μs for praisonai.llm.registry
  • O(1) operations: has(), resolve(), and register() are all O(1)
  • No LiteLLM coupling: The registry is completely independent of LiteLLM

See Also