Skip to content

Run a browser voice call

This continues from the generated my-voicebot directory in Install and generate.

1. Add runtime credentials

Copy the example once and edit .env:

cd my-voicebot
cp .env.example .env

The generated starter profile needs:

LIVEKIT_URL=wss://your-project.livekit.cloud
LIVEKIT_API_KEY=...
LIVEKIT_API_SECRET=...
LIVEKIT_AGENT_NAME=my-voicebot
DEEPGRAM_API_KEY=...
GOOGLE_AI_STUDIO_API_KEY=...
SMALLEST_API_KEY=...

These credentials run calls. They are separate from the Google identity used to download private packages. The bundled locked production deployment also requires SARVAM_API_KEY, VERTEX_SERVICE_ACCOUNT_JSON, and CARTESIA_API_KEY for its fallbacks. Keep .env out of version control and use a secret manager in production.

2. Know what each command does

./scripts/setup
./scripts/check
./scripts/dev
Command What it does
setup installs the locked private vaani==1.0.0rc43 artifact, verifies its version, location, and approved wheel digest, then installs frontend packages
check loads the chosen environment, validates the Assistant, required credential variables, installed extras, and locks; it does not call LiveKit or a provider
dev selects development, starts one VAANI worker, then starts the token API and Next.js frontend

check proves local consistency, not a conversation. Leave dev running, open http://localhost:3000, allow microphone access, choose any available STT, LLM, TTS, voice, and language combination, and connect. Speak normally and confirm that you hear the greeting and see both sides of the transcript. Participant interim updates and assistant update granularity depend on the selected providers; the provider guide documents the SmallestAI behavior used by the current release.

A new project has no business-specific call-context form. It asks only for the language and backend-approved development voice stack. If a test call needs a caller ID, account ID, or another safe value, define it in backend/src/<package>/call_context.py; do not add employee or workflow fields unless that bot actually owns them.

The generated END button first asks VAANI to complete the call. When the remote agent leaves—or after a 1.5-second safety bound—the browser disconnects locally and returns to the start screen. A worker log ending with primary_participant_end_requested and vaani_outcome: COMPLETED is the expected graceful path.

3. Make one visible change

Edit backend/src/<package>/prompts.py:

from vaani import Call


def prompt_for(call: Call) -> str:
    return """You are Simran, a concise loyalty assistant.
Ask one question at a time. Do not use markdown.
Never claim a business action succeeded unless its tool result says so."""

Edit the greeting in backend/src/<package>/assistant.py:

assistant = Assistant(
    name="Simran",
    prompt=prompt_for,
    greeting="Namaste. Main Simran hoon. How can I help?",
    environment=environment,
)

Restart ./scripts/dev and place another browser call. VAANI owns microphone audio through LiveKit, STT, streaming model output, streaming TTS, turn taking, interruptions, transcripts, and cleanup. Your code owns the words and business actions.

4. Check production configuration

VAANI_ENVIRONMENT=production ./scripts/check

Production uses its locked Production Deployment Profile. It has no route selector and rejects browser provider/model/voice selection. This check still does not place a call.

Next: use the project map, then add caller data and tools.