Provider Abstraction
All 11 providers in VoiceGateway implement the same abstract base class, giving the core layer a uniform interface regardless of whether the underlying service is a cloud API or a local model.BaseProvider ABC
File:src/voicegateway/providers/base.py
Method Contracts
| Method | Returns | Unsupported Behavior |
|---|---|---|
create_stt(model, **kwargs) | LiveKit-compatible STT instance | Call self._unsupported("stt") |
create_llm(model, **kwargs) | LiveKit-compatible LLM instance | Call self._unsupported("llm") |
create_tts(model, voice, **kwargs) | LiveKit-compatible TTS instance | Call self._unsupported("tts") |
health_check() | True if reachable, False otherwise | Must always be implemented |
voice-prices (see the wrapper modules src/voicegateway/inference/pricing/{llm,stt,tts}.py, which call voice_prices.calc_price). Use voicegateway.inference.pricing.catalog.calculate_cost(modality, model, ...) from anywhere that needs a per-request cost.
Argument order trap.voicegateway.pricing.catalog.calculate_cost(modality, model, ...)takesmodalityfirst; the legacyCostTracker.calculate_cost(model_id, modality, ...)onvoicegateway.middleware.cost_trackertakesmodel_idfirst. The two helpers serve different layers (catalog is the pricing facade; CostTracker bridges to the storage record), but the reversed positional order is easy to transpose. When in doubt, use keyword arguments or call the catalog directly.
Provider Registry
All 11 providers are registered insrc/voicegateway/core/registry.py as (module_path, class_name) tuples. The Registry uses importlib.import_module() for lazy loading — a provider’s SDK is only imported when that provider is first used.
Modality Support Matrix
| Provider | STT | LLM | TTS | Install Extra |
|---|---|---|---|---|
| OpenAI | Yes | Yes | Yes | openai |
| Deepgram | Yes | — | — | deepgram |
| Cartesia | — | — | Yes | cartesia |
| Anthropic | — | Yes | — | anthropic |
| Groq | Yes | Yes | — | groq |
| ElevenLabs | — | — | Yes | elevenlabs |
| AssemblyAI | Yes | — | — | assemblyai |
| Ollama | — | Yes | — | ollama |
| Whisper | Yes | — | — | whisper |
| Kokoro | — | — | Yes | kokoro |
| Piper | — | — | Yes | piper |
create_* method calls self._unsupported(), which raises NotImplementedError. This propagates cleanly through the Router and Gateway layers.
Implementation Pattern
Every provider follows the same structure:Key patterns:
-
API key resolution:
config.get("api_key")first (from YAML or managed providers), then fall back to the standard environment variable (DEEPGRAM_API_KEY,OPENAI_API_KEY, etc.). -
LiveKit plugin wrapping: each
create_*method returns a LiveKit Agents plugin instance (livekit.plugins.deepgram.STT,livekit.plugins.openai.LLM, etc.), making VoiceGateway a drop-in replacement for direct LiveKit plugin usage. -
Lazy SDK import: the
from livekit.plugins.deepgram import STThappens inside the method, not at module level. This allows installing only the providers you need.
Modular Installation
Each provider is an optional dependency:ImportError:
Adding a New Provider
- Create
src/voicegateway/providers/myprovider_provider.pyextendingBaseProvider - Implement the five abstract methods (use
_unsupported()for unsupported modalities) - Register it in
src/voicegateway/core/registry.py: - Add pricing data to
src/voicegateway/pricing/catalog.py - Add the optional dependency to
pyproject.toml