> For clean Markdown of any page, append `.md` to the page URL.
> For a complete documentation index, see https://docs.sarvam.ai/llms.txt.
> For full documentation content in one file, see https://docs.sarvam.ai/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.sarvam.ai/_mcp/server.

# IVR & Contact Center Voice Agents

> Architecture, model configuration, and latency targets for building telephony-based IVR and contact-center voice agents with Sarvam AI.

Indian contact centers run at huge call volumes on infrastructure that's still largely PSTN and IVR-menu based: outbound collections, order status, appointment reminders, first-line support. A Sarvam-powered voice agent can sit behind that IVR (or replace the menu entirely) and hold a real conversation in the caller's language, instead of routing them through "press 1 for Hindi."

This guide covers the architecture pattern common to IVR/contact-center bots, then walks through the [Collection Agent](/api-reference-docs/cookbook/Examples/Collection_Agent_LiveKit) example (a payment-reminder bot) as the concrete implementation. The same pattern (professional tone, structured account lookup, clean escalation to a human) applies whether you're doing collections, order-status calls, or appointment reminders.

**In short:** stream everything (STT and TTS), keep the LLM turn short and on `sarvam-30b` by default, and build the human-escalation path before you build anything else.

## Architecture

```
PSTN / SIP trunk → Telephony transport → STT (streaming) → LLM → TTS (streaming) → Telephony transport → Caller
```

* **DTMF / intent detection** → escalate to human queue
* **Call recording** (with consent) → batch STT for QA/analytics

Calls typically arrive over a SIP trunk. Both [LiveKit](https://docs.livekit.io/sip/) and [Pipecat](https://docs.pipecat.ai/server/services/transport/introduction) support SIP/telephony transports that bridge PSTN audio into the same `Agent`/`Pipeline` you'd use for a WebRTC call. There's no separate code path for phone vs. app.

Use the WebSocket transport (or the LiveKit/Pipecat Sarvam plugins, which use it internally) so the agent starts processing speech before the caller finishes talking. Telephony audio is 8kHz, which Saaras v3 supports natively without upsampling.

The LLM generates a response. Keep it short: contact-center callers are on hold, not reading an essay. Stream the reply into TTS rather than waiting for the full completion.

Detect explicit requests ("talk to a person," repeated failed intents, DTMF `0`) and transfer to a human queue rather than looping the caller through the bot. Every example agent in this series is written to acknowledge and offer transfer instead of stonewalling.

If you record calls for compliance or quality review, run them through Sarvam's [Batch STT with diarization](/api-reference-docs/speech-to-text/apis/batch) afterward. See the [Call Analytics Pipeline](/api-reference-docs/cookbook/Starter_Notebook/Call_Analytics) cookbook for a full diarized-transcript-to-insights pipeline.

## Recommended models & params

| Layer          | Setting                                                                  | Why                                                                                                                                                                                              |
| -------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| STT            | `saaras:v3`, `mode="transcribe"`, `language="unknown"`                   | Auto-detect handles callers who code-mix Hindi/English mid-sentence, common in contact-center audio                                                                                              |
| LLM            | `sarvam-30b`, `reasoning_effort=None`, short `max_tokens` (e.g. 200–400) | Contact-center turns are short Q\&A/confirmation exchanges. You don't need `sarvam-105b`'s depth, and you don't want its latency                                                                 |
| TTS            | `bulbul:v3`, WebSocket streaming, `pace=1.1`, `temperature=0.4`          | Matches the "IVR / Telephony" preset in [TTS Best Practices](/api-reference-docs/text-to-speech/best-practices#11-use-case-quick-reference): a slightly brisk, professional, consistent delivery |
| TTS format     | `mulaw` at 8kHz for PSTN legs, `linear16` at 16kHz for WebRTC/app legs   | Matches the telephony codec so there's no resampling step in the media path                                                                                                                      |
| Turn detection | `turn_detection="stt"`, `min_endpointing_delay=0.07` (LiveKit)           | See [Build a Voice Agent with LiveKit](/api-reference-docs/integration/build-voice-agent-with-live-kit#4-configure-min-endpointing-delay)                                                        |

## Latency targets

| What                    | Target                            | How to get there                                                                                                                                                                                                                                                                                                                                                 |
| ----------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| STT processing          | \~70ms                            | Set `min_endpointing_delay=0.07` (matches the Sarvam LiveKit plugin's documented processing latency) so the agent doesn't wait longer than necessary before handing off to the LLM                                                                                                                                                                               |
| LLM time-to-first-token | As low as the conversation allows | Default to `sarvam-30b`, the lower-latency option for voice-agent pipelines. Reserve `sarvam-105b` for calls that need multi-step reasoning (e.g. explaining a complex billing dispute), not routine confirmations                                                                                                                                               |
| TTS time-to-first-audio | Near-instant                      | Always use WebSocket streaming on the live call leg ("audio starting within milliseconds of the first chunk" per [TTS Best Practices](/api-reference-docs/text-to-speech/best-practices#8-choosing-the-right-api-mode)). REST waits for full synthesis and is fine only for pre-generated static prompts ("Thank you for calling...") that don't change per call |

There's no official Sarvam round-trip SLA to quote here, so budget your own. Streaming STT plus `sarvam-30b` plus streaming TTS keeps each leg in the tens-to-low-hundreds of milliseconds, which is what makes barge-in and natural turn-taking possible over a phone line.

## Pitfalls

Contact-center callers switch between Hindi, English, and their regional language within one sentence. `language="unknown"` on STT handles this. Hardcoding a single language code degrades transcription the moment a caller code-mixes.

A bot that can't recognize "I want to speak to a person" and hand off cleanly will frustrate callers and generate complaints. Build the transfer/escalation branch first, not as an afterthought.

Account numbers, product codes, and abbreviations (e.g. "EMI," "NAIC") don't always get read the way you'd expect. Use a [pronunciation dictionary](/api-reference-docs/text-to-speech/pronunciation-dictionary) scoped per language rather than fighting it in the prompt.

REST returns the full audio only after synthesis completes, which reads as dead air to a caller on a phone line. Reserve REST for pre-generated, static prompts; use WebSocket streaming for anything generated per turn.

If you're recording for QA, capture consent in the call flow itself, and pipe recordings through diarized batch STT so per-speaker talk-time and sentiment are queryable. Don't just archive raw audio.

## Full example

The [Collection Agent](/api-reference-docs/cookbook/Examples/Collection_Agent_LiveKit) guide has the complete, runnable code (LiveKit-based). The core of it:

```python
class CollectionAgent(Agent):
    def __init__(self) -> None:
        super().__init__(
            instructions="""
                You are a professional and empathetic collection agent working for ABC Bank.
                ...
                If customer requests to speak to a human, acknowledge and offer to transfer.
            """,
            stt=sarvam.STT(language="unknown", model="saaras:v3", mode="transcribe"),
            llm=sarvam.LLM(model="sarvam-105b"),
            tts=sarvam.TTS(target_language_code="en-IN", model="bulbul:v3", speaker="aditya"),
        )
```

The example above uses `sarvam-105b` for a richer collections conversation with payment-plan negotiation. For simpler, high-volume flows (order status, appointment reminders, balance inquiries), swap in `sarvam-30b` per the [recommended params](#recommended-models-params) to shave latency off every turn.

**See also:** [BFSI Voice Bots](/api-reference-docs/api-guides-tutorials/speech-to-text/use-cases/bfsi-voice-bots) for collections-specific compliance guardrails, and the [Call Analytics Pipeline](/api-reference-docs/cookbook/Starter_Notebook/Call_Analytics) cookbook for post-call QA.