Add voice to a text-only agent
Run a voice call with an agent whose model has no native audio streaming, such as Claude. The runtime transcribes the caller’s speech, sends the text to the model, and speaks the reply.
Prerequisites
Section titled “Prerequisites”- An AgentRuntime whose default provider is a text model.
- A Provider with
role: stt, such as OpenAIwhisper-1. - A Provider with
role: tts, such as OpenAItts-1, Cartesia or ElevenLabs. - The credentials for both providers, in the same form as any other provider. See Provider.
-
Create the speech providers.
spec.sttandspec.ttsset what the call uses:apiVersion: omnia.altairalabs.ai/v1alpha1kind: Providermetadata:name: openai-sttspec:type: openairole: sttmodel: whisper-1credential:secretRef:name: openai-credentialsstt:language: ensampleRate: 16000---apiVersion: omnia.altairalabs.ai/v1alpha1kind: Providermetadata:name: openai-ttsspec:type: openairole: ttsmodel: tts-1credential:secretRef:name: openai-credentialstts:voice: novaField Effect on the call stt.languageTranscription language. Unset means enstt.sampleRateSample rate the console captures at, unless spec.duplex.audio.recommendedSampleRatesets onetts.voiceVoice of the agent’s replies. Unset means alloyThe runtime speaks replies as 16-bit PCM at 24 kHz. It logs
tts output format not applied in cascaded voicewhentts.sampleRateortts.formatis set. -
Bind both providers to the agent and turn on duplex:
apiVersion: omnia.altairalabs.ai/v1alpha1kind: AgentRuntimemetadata:name: support-agentspec:providers:- name: defaultproviderRef:name: claude-sonnet- name: speech-inrole: sttproviderRef:name: openai-stt- name: speech-outrole: ttsproviderRef:name: openai-ttsduplex:enabled: truemode: cascadedWith
modeunset, the runtime chooses cascaded voice when the default provider’s type cannot stream audio and both speech providers are usable. Claude, Ollama and vLLM qualify. An OpenAI or Gemini provider streams audio by type whatever its model, so an agent on a text model from either vendor setsmode: cascaded. -
Apply both manifests:
Terminal window kubectl --context <context> apply -f speech-providers.yaml -f support-agent.yaml
Verify
Section titled “Verify”-
Open the agent’s console in the dashboard and start a call. Once the call connects, the console header shows Cascaded voice (STT → LLM → TTS). Its tooltip says that each turn adds latency. An agent on a realtime model shows Realtime voice instead. The label reflects the mode the runtime chose, including the automatic choice when
modeis unset. A runtime that predates the label shows none. -
Speak, then pause. The agent replies after about 800 ms of silence.
-
Check the runtime log for the session’s mode:
Terminal window kubectl --context <context> -n <namespace> logs deploy/support-agent -c runtime | grep "duplex mode selected"The line carries
mode=cascaded.
Troubleshooting
Section titled “Troubleshooting”- The call fails at open with
spec.duplex.mode is cascaded but the agent has no usable stt and tts providers. One of the providers is missing fromspec.providers, or the runtime skipped it. Search the runtime log forskipping extra provider, which names the provider and the missing credential. - The agent answers slowly. Each turn waits for transcription, the full model reply and synthesis. A realtime model, such as Gemini Live, answers sooner.