<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: sharvin shetty</title>
    <description>The latest articles on DEV Community by sharvin shetty (@sharvin_shetty_d86cdf5387).</description>
    <link>https://dev.to/sharvin_shetty_d86cdf5387</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4078435%2F8a1e448b-8fcf-4dfc-8114-1905dfd8cf4b.png</url>
      <title>DEV Community: sharvin shetty</title>
      <link>https://dev.to/sharvin_shetty_d86cdf5387</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sharvin_shetty_d86cdf5387"/>
    <language>en</language>
    <item>
      <title>Saathi (साथी) A Bilingual Multi-Agent Voice AI Tutor for Indian Students</title>
      <dc:creator>sharvin shetty</dc:creator>
      <pubDate>Sat, 15 Aug 2026 11:27:59 +0000</pubDate>
      <link>https://dev.to/sharvin_shetty_d86cdf5387/saathi-saathiia-bilingual-multi-agent-voice-ai-tutor-for-indian-students-47pl</link>
      <guid>https://dev.to/sharvin_shetty_d86cdf5387/saathi-saathiia-bilingual-multi-agent-voice-ai-tutor-for-indian-students-47pl</guid>
      <description>&lt;p&gt;Over the last 10 days, I participated in the 10 Days of AI Voice Agents (Voice for Bharat Edition) challenge by Murf AI. My goal was to build a real-world voice application that solves an actual accessibility problem in India.&lt;/p&gt;

&lt;p&gt;I chose the Learning &amp;amp; Literacy Track and built Saathi (साथी) — an AI-powered voice companion designed to help school students and first-generation learners practice concepts, play quizzes, and learn math in Hinglish.&lt;/p&gt;

&lt;p&gt;Here is a breakdown of what I built, the architecture behind it, the hardest bugs I ran into, and how you can run the project yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Real-World Problem: The Indian Spoken English Paradox
&lt;/h2&gt;

&lt;p&gt;In rural or under-resourced Indian households, many children are first-generation schoolgoers. While they study passive school material, they lack supportive, bilingual study partners at home to help clarify doubts, explain math equations, or review vocabulary.&lt;br&gt;
Voice calls are intuitive for young students who find reading long textbook texts or typing queries on tiny screens difficult. A 30-second conversational call in Hinglish is much more effective than navigating websites.&lt;br&gt;
I designed Saathi to act like a personal phone call tutor:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; It greets students in natural bilingual Hinglish, recognizing returning     profiles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; It offers interactive general knowledge trivia quizzes and English word definitions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; It protects student privacy by requiring verbal consent before storing names and study progress in SQLite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; If the student struggles or asks for a teacher, it creates an escalation ticket and sends alerts to supervisors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.&lt;/strong&gt; If the student wants to practice math, it transfers them mid-session to a Specialist Math Tutor (Samar), who speaks in a dedicated male voice.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. System Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6hvksvs6xsfajxpw6ckm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6hvksvs6xsfajxpw6ckm.png" alt=" " width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is how real-time audio and data flow through the application:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm47xzjyyzzo5d368g67j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm47xzjyyzzo5d368g67j.png" alt=" " width="733" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now the end-to-end pipeline view, showing the same system as a sequence of turn-by-turn stages:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz5pfbwpfba435lduwcx7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz5pfbwpfba435lduwcx7.png" alt=" " width="800" height="770"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. The Tech Stack
&lt;/h2&gt;

&lt;p&gt;• &lt;code&gt;Voice Synthesis (TTS)&lt;/code&gt;: Murf Falcon Streaming TTS (latency &amp;lt;100ms)&lt;br&gt;
• &lt;code&gt;Real-Time Transport&lt;/code&gt;: LiveKit Agents SDK &amp;amp; WebRTC Rooms&lt;br&gt;
• &lt;code&gt;Speech Recognition (STT)&lt;/code&gt;: Deepgram Nova-3 Multilingual&lt;br&gt;
• &lt;code&gt;Language Model (LLM)&lt;/code&gt;: Google Gemini 3.5 Flash-lite&lt;br&gt;
• &lt;code&gt;Database&lt;/code&gt;: SQLite (saathi_memory.db)&lt;br&gt;
• &lt;code&gt;Frontend&lt;/code&gt;: Next.js 15, React, Tailwind CSS&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-Time Transport:&lt;/strong&gt; LiveKit Cloud manages bidirectional WebRTC audio tracks with adaptive jitter buffers and low-latency packet recovery.&lt;br&gt;
Speech Recognition (STT): Deepgram Nova-3 (multilingual) transcribes audio, handling code-mixed Hinglish phrases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent Core &amp;amp; LLM Orchestration:&lt;/strong&gt; Configured with Google Gemini 3.5 Flash-lite to provide fast bilingual token generation with sub-400ms time-to-first-token latency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Speech Synthesis (TTS):&lt;/strong&gt; Murf Falcon streams synthesized speech frames over WebSockets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saathi (Main Agent):&lt;/strong&gt; Configured with Murf Falcon voice "Anisha" (conversational Hinglish female voice).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Math Specialist (Specialist Agent):&lt;/strong&gt; Configured with Murf Falcon voice "Samar" (patient male Indian math tutor voice).&lt;br&gt;
Data Layer &amp;amp; Observability: Local SQLite database (memory.db) tracks 3 tables: users, escalations, and calls.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Visual Evidence from the Build
&lt;/h2&gt;

&lt;p&gt;Here is how the system looks and behaves across core interaction touchpoints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. Landing &amp;amp; Practice Goals&lt;/strong&gt;&lt;br&gt;
The main interface allows learners to choose practice focus areas and configure daily practice schedules.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqhiz4g3h59bhb0f5fjc7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqhiz4g3h59bhb0f5fjc7.png" alt=" " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Active Voice Conversation &amp;amp; State Feedback&lt;/strong&gt;&lt;br&gt;
During an active session, the animated Voice Orb visualizer renders real-time state feedback (listening, thinking, speaking) alongside an active agent and voice indicator badge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxc3nddjy1600yjhyseuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxc3nddjy1600yjhyseuh.png" alt=" " width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. Human Support Escalation Drawer &amp;amp; Discord Alerts&lt;/strong&gt;&lt;br&gt;
When a learner requests human assistance or expresses distress, Saathi opens a support ticket (ESC-XXXX), displays it in the Human Help drawer, and dispatches a sanitized alert to academic counselors via Discord Webhooks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3d4lqksuembh2tfjc8a2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3d4lqksuembh2tfjc8a2.png" alt=" " width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D. Production Call Analytics Dashboard&lt;/strong&gt;&lt;br&gt;
The built-in analytics dashboard reads directly from the SQLite call_analytics table, presenting real session counts, success rates, failure breakdowns, and duration logs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fahgvi5iyap1di3uflk23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fahgvi5iyap1di3uflk23.png" alt=" " width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Key Features Built Over the 10 Days
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A. Natural Hinglish Voice with Accent Scripting&lt;/strong&gt;&lt;br&gt;
Using Murf Falcon (Anisha voice), the coordinator responds almost instantly. To prevent a robotic English-accented voice, Saathi's system prompt strictly requires Devanagari script output (नमस्ते) for all Hindi phrases, prompting native cadence and natural rhythm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Caller Profile Memory &amp;amp; Consent Guardrails&lt;/strong&gt;&lt;br&gt;
Instead of asking for information repeatedly, Saathi remembers students across calls. When a student calls back, the agent loads their saved profile from SQLite. To protect user privacy, Saathi is programmatically blocked from saving name or topic progress unless the student gives explicit verbal consent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. Structured Study Tools&lt;/strong&gt;&lt;br&gt;
I integrated tools that retrieve live trivia quiz questions from the Open Trivia Database, and define English words in Hinglish using dictionary APIs. Students can study vocabulary and test general knowledge mid-session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D. Teacher Escalation &amp;amp; Analytics Dashboard&lt;/strong&gt;&lt;br&gt;
If a student repeatedly struggles, Saathi creates an escalation ticket, displays it on a Next.js /escalations page, and dispatches a sanitized warning embed notification directly to a Discord Webhook. Metrics including total calls, success rates, and duration logs are shown on a glassmorphism /dashboard page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E. Multi-Agent Specialist Handoff&lt;/strong&gt;&lt;br&gt;
When a student asks to learn math, the main agent (Anisha) announces a handoff. The active chat context is copied and sent to a specialized MathSpecialist agent (Samar), who takes over the session in a distinct male voice (Samar) to solve equations step-by-step.&lt;/p&gt;
&lt;h2&gt;
  
  
  6. Verified Code Highlights (Evidence from our codebase)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Context-Preserving Multi-Agent Handoff Tool&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;_Location: backend/src/agent.py_&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@function_tool
async def transfer_to_maths(self, context: RunContext) -&amp;gt; tuple[Agent, str]:
    """Transfer the student to the Maths Specialist when they want to study math."""
    logger.info(f"Handoff triggered: transfer_to_maths for user_id: {self.user_id}")
    math_agent = MathSpecialist(
        user_id=self.user_id,
        chat_ctx=self.chat_ctx.copy(exclude_instructions=True)
    )
    return math_agent, "Main aapko hamare Maths specialist se connect karti hoon. Ek second rukiye."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 2: Decoupled Multi-Threaded Python REST Server&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;_Location: backend/src/agent.py_&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class EscalationsHandler(BaseHTTPRequestHandler):
    def do_OPTIONS(self):
        self.send_response(200)
        self.send_header("Access-Control-Allow-Origin", "*")
        self.send_header("Access-Control-Allow-Methods", "GET, OPTIONS")
        self.send_header("Access-Control-Allow-Headers", "Content-Type")
        self.end_headers()

    def do_GET(self):
        if self.path == "/stats":
            from database import get_call_stats
            try:
                stats = get_call_stats()
                self.send_response(200)
                self.send_header("Content-Type", "application/json")
                self.send_header("Access-Control-Allow-Origin", "*")
                self.end_headers()
                self.wfile.write(json.dumps(stats).encode("utf-8"))
            except Exception as e:
                self.send_response(500)
                self.wfile.write(str(e).encode("utf-8"))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 3: SQLite Call Metrics Outcome Updates&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;_Location: backend/src/database.py_&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def update_call_outcome(call_id: str, duration_seconds: int, name: str, outcome: str, failure_reason: str = None):
    conn = get_db_connection()
    cursor = conn.cursor()
    cursor.execute(
        """
        UPDATE calls
        SET duration_seconds = ?, name = ?, outcome = ?, failure_reason = ?
        WHERE call_id = ?
        """,
        (duration_seconds, name, outcome, failure_reason, call_id)
    )
    conn.commit()
    conn.close()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 4: Windows Safe Unicode Terminal Logging Filter&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;_Location: backend/src/agent.py_&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SafeLoggingFilter(logging.Filter):
    def filter(self, record):
        try:
            if isinstance(record.msg, str):
                record.msg = record.msg.encode("ascii", errors="replace").decode("ascii")
            if record.args:
                new_args = [
                    arg.encode("ascii", errors="replace").decode("ascii")
                    if isinstance(arg, str) else arg for arg in record.args
                ]
                record.args = tuple(new_args)
        except Exception:
            pass
        return True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Real Engineering Challenges &amp;amp; How I Solved Them
&lt;/h2&gt;

&lt;p&gt;Here are the primary technical issues encountered during development and how they were resolved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The LiveKit &lt;code&gt;NOT_GIVEN&lt;/code&gt; Sentinel Issue&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;/em&gt; Subclassing &lt;code&gt;Agent&lt;/code&gt; with &lt;code&gt;tts=None&lt;/code&gt; in &lt;code&gt;Assistant&lt;/code&gt; caused LiveKit to raise &lt;code&gt;RuntimeError: 'tts_node' called but no TTS node is available&lt;/code&gt; during speech output.&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Cause:&lt;/strong&gt;&lt;/em&gt; In LiveKit Agents SDK, &lt;code&gt;Agent&lt;/code&gt; uses &lt;code&gt;NOT_GIVEN&lt;/code&gt; as the default sentinel to inherit the session-level TTS. Passing &lt;code&gt;None&lt;/code&gt; explicitly disabled the TTS node.&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/em&gt; Updated constructors to pass &lt;code&gt;tts if tts is not None else NOT_GIVEN.&lt;/code&gt;&lt;br&gt;
Lesson: Inspect framework-level sentinel objects &lt;code&gt;(NOT_GIVEN)&lt;/code&gt; when subclassing agent classes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Next.js 15 React Server Component (RSC) Boundary Crash&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;/em&gt; Adding a custom &lt;code&gt;useActiveAgent&lt;/code&gt; hook resulted in Error: Could not find the module ... in the React Client Manifest and &lt;code&gt;TypeError: __webpack_modules__[moduleId] is not a function.&lt;/code&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Cause:&lt;/strong&gt;&lt;/em&gt; The hook file omitted the &lt;code&gt;'use client'&lt;/code&gt;; directive. In Next.js 15 App Router, hooks utilizing &lt;code&gt;useState&lt;/code&gt; or &lt;code&gt;useEffect&lt;/code&gt; must explicitly declare client boundaries.&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/em&gt; Added &lt;code&gt;'use client'&lt;/code&gt;; at the top of &lt;code&gt;frontend/hooks/useActiveAgent.ts&lt;/code&gt; and rebuilt with &lt;code&gt;pnpm build&lt;/code&gt;.&lt;br&gt;
&lt;em&gt;Lesson:&lt;/em&gt; Every custom hook that uses React lifecycle state in Next.js App Router must include the &lt;code&gt;'use client'&lt;/code&gt;; directive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Latency in Multi-Turn Specialist Handoffs&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;/em&gt; Transferring between agents previously took multiple conversational turns (Ask permission → User confirmation → Transfer), making the transition feel delayed.&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Cause:&lt;/strong&gt;&lt;/em&gt; Prompt instructions required confirmation for all mentions of the specialist topic, even when the user explicitly asked for immediate practice.&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/em&gt; Updated prompt rules so that when a user explicitly requests specialist practice, the agent triggers the handoff tool in the same turn.&lt;br&gt;
&lt;em&gt;Lesson:&lt;/em&gt; Reserve multi-step verbal confirmation for destructive operations (e.g. data deletion); routing to specialized skills should happen promptly upon explicit intent.&lt;/p&gt;
&lt;h2&gt;
  
  
  8. Practical Step-by-Step Build Guide
&lt;/h2&gt;

&lt;p&gt;To set up and run the Saathi repository locally:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Python 3.10+&lt;/strong&gt; with &lt;code&gt;uv&lt;/code&gt; package manager&lt;br&gt;
&lt;strong&gt;Node.js 18+&lt;/strong&gt; with &lt;code&gt;pnpm&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;LiveKit Cloud Project&lt;/strong&gt; (URL, API Key, API Secret from cloud.livekit.io)&lt;br&gt;
&lt;strong&gt;Murf AI API Key&lt;/strong&gt; (murf.ai/api)&lt;br&gt;
&lt;strong&gt;Deepgram API Key&lt;/strong&gt; (console.deepgram.com)&lt;br&gt;
&lt;strong&gt;Google Gemini API Key&lt;/strong&gt; or &lt;strong&gt;Groq API Key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Clone and Configure Environment&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/sharvinshetty10-hub/murf-livekit-starter.git
cd murf-livekit-starter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Backend Configuration &lt;code&gt;(backend/.env.local)&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LIVEKIT_URL=wss://your-project.livekit.cloud
LIVEKIT_API_KEY=your_livekit_api_key
LIVEKIT_API_SECRET=your_livekit_api_secret

MURF_API_KEY=your_murf_api_key
DEEPGRAM_API_KEY=your_deepgram_api_key
GOOGLE_API_KEY=your_gemini_api_key
GROQ_API_KEY=your_groq_api_key

DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/your_webhook_url
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Frontend Configuration &lt;code&gt;(frontend/.env.local)&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LIVEKIT_URL=wss://your-project.livekit.cloud
LIVEKIT_API_KEY=your_livekit_api_key
LIVEKIT_API_SECRET=your_livekit_api_secret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Security Note: Never commit &lt;code&gt;.env.local&lt;/code&gt; files, webhook URLs, or private database files to version control.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Start the System&lt;/strong&gt;&lt;br&gt;
Using the Startup Scripts:&lt;/p&gt;

&lt;p&gt;Windows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.\start_app.ps1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;macOS / Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./start_app.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manual Startup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Terminal 1: Backend
cd backend
uv sync
uv run python src/agent.py dev

# Terminal 2: Frontend
cd frontend
pnpm install
pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; to call Saathi, and visit &lt;a href="http://localhost:3000/dashboard" rel="noopener noreferrer"&gt;http://localhost:3000/dashboard&lt;/a&gt; to view the metrics panel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Run the Test Suite&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Backend unit &amp;amp; integration tests
cd backend
uv run pytest tests/test_analytics.py tests/test_escalation.py tests/test_memory_db.py tests/test_handoff.py -k test_specialist_murf_voice_configuration -v

# Frontend lint &amp;amp; build check
cd ../frontend
pnpm lint
pnpm build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Practical Troubleshooting
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Issue 1: Audio Playback Fails on Initial Page Load&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Cause:&lt;/em&gt; Modern browsers block autoplay audio until a user interaction event occurs.&lt;br&gt;
&lt;em&gt;Fix:&lt;/em&gt; The frontend uses an explicit Start Audio button &lt;code&gt;(StartAudioButton)&lt;/code&gt;to ensure an audio context is initialized before streaming starts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Issue 2: Discord Webhook Times Out&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Cause:&lt;/em&gt; Network egress latency or invalid webhook URL.&lt;br&gt;
&lt;em&gt;Fix:&lt;/em&gt; &lt;code&gt;escalationtools.py&lt;/code&gt; wraps webhook requests in a non-blocking background task with a 5-second timeout, ensuring the voice dialogue continues even if the webhook call fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Conclusion &amp;amp; Links
&lt;/h2&gt;

&lt;p&gt;Building Saathi demonstrates how voice, fast streaming TTS, and multi-agent setups can build accessible educational tools in India. Thanks to Murf AI for hosting the #VoiceForBharat challenge!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GitHub Repository: https://github.com/sharvinshetty10-hub/murf-livekit-starter&lt;br&gt;
LiveKit Voice AI Docs: https://docs.livekit.io/agents&lt;br&gt;
Murf Falcon TTS Docs: https://murf.ai/api/docs&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  11. References
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1.Pratham Education Foundation (2023).&lt;/strong&gt; Annual Status of Education Report (Rural) 2023: Beyond Basics. New Delhi: ASER Centre. Available at: &lt;a href="https://www.asercentre.org" rel="noopener noreferrer"&gt;https://www.asercentre.org&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;2.Horwitz, E. K., Horwitz, M. B., &amp;amp; Cope, J. (1986).&lt;/strong&gt; Foreign language classroom anxiety. The Modern Language Journal, 70(2), 125-132.&lt;br&gt;
&lt;strong&gt;3.National Council of Educational Research and Training (NCERT) (2020).&lt;/strong&gt; Position Paper on the Teaching of English. National Curriculum Framework, Ministry of Education, Government of India.&lt;br&gt;
&lt;strong&gt;4.LiveKit Agents Framework Documentation (2026).&lt;/strong&gt; Real-Time Multimodal Voice Agent Framework. &lt;a href="https://docs.livekit.io/agents" rel="noopener noreferrer"&gt;https://docs.livekit.io/agents&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;5.Murf AI Falcon Streaming API (2026).&lt;/strong&gt; Ultra Low-Latency Text-to-Speech Engine for Conversational AI. &lt;a href="https://murf.ai/api/docs" rel="noopener noreferrer"&gt;https://murf.ai/api/docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>voiceai</category>
    </item>
  </channel>
</rss>
