Providers
All bundled providers share the credential shape from @ottervoice/provider-utils:
| Field | Use |
|---|---|
apiKey |
Long-lived key (server only — never ship to clients) |
tokenBrokerUrl |
Direct-client token mint only when credentials are short-lived and least-privilege |
tokenBrokerHeaders / tokenBrokerSessionId |
Application auth and ownership binding for broker calls |
fetch |
Injectable |
Capability map
Section titled “Capability map”| Capability | Package | Transport |
|---|---|---|
| Streaming ASR | @ottervoice/provider-deepgram |
WebSocket |
| Streaming ASR | @ottervoice/provider-elevenlabs |
WebSocket |
| LLM / SSE | @ottervoice/provider-openrouter |
HTTP SSE |
| TTS / STT / Audio LLM | @ottervoice/provider-openrouter |
HTTP (demo-optional) |
| TTS | @ottervoice/provider-azure-speech |
REST + SSML |
Custom ASR must declare capabilities.streaming correctly — core uses it to choose live chunks vs full-turn audio.
For OpenRouter in browsers/apps, use server-managed factories. Their client options contain no model, prompt, voice, or generation controls:
import { createOpenRouterGatewayASR, createOpenRouterGatewayAudioLLM, createOpenRouterGatewayVoiceTurn,} from '@ottervoice/provider-openrouter';
// Server-composed ASR → LLM → TTS; input transcript and reply share one SSE request.const cascadedVoice = createOpenRouterGatewayVoiceTurn({ baseUrl: '/api/voice/asr-llm-tts', prepareAudio,});
// A native Audio LLM may need a separate caption ASR.const asr = createOpenRouterGatewayASR({ baseUrl: '/api/voice/asr', format: 'webm',});const audioLlm = createOpenRouterGatewayAudioLLM({ baseUrl: '/api/voice/audio-llm', prepareAudio,});Configure createOpenRouterGateway() on the server with locked policy and
its mandatory authorize hook. The composite asr_llm_tts profile is enabled
only when policy.asr, policy.llm, and policy.tts all exist; standalone
audio_llm is the native speech-model route and standalone asr is only for
optional captions. There are no client LLM/TTS profiles. Direct factories such
as createOpenRouterLLM and createOpenRouterTTS are trusted-backend building
blocks for a composite AudioLLMProvider.
Direct WebSocket services such as Deepgram may still use a broker when the issued credential is short-lived and tightly scoped:
import { createDeepgramASR } from '@ottervoice/provider-deepgram';
const asr = createDeepgramASR({ tokenBrokerUrl: '/api/voice/token', tokenBrokerHeaders: { authorization: `Bearer ${applicationSessionToken}` }, tokenBrokerSessionId: voiceSessionId,});Short-lived is not sufficient by itself. If a token can still select arbitrary models/routes or spend the account budget, keep it behind a policy gateway.
Credential details: provider-utils. Factory option tables: API reference and each package’s JSDoc.