<?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: Biprajit Biswas</title>
    <description>The latest articles on DEV Community by Biprajit Biswas (@biprajit_biswas_4915ce12b).</description>
    <link>https://dev.to/biprajit_biswas_4915ce12b</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%2F4078642%2F87bfa7b3-396d-4bd6-a01d-abd1f8875f7e.png</url>
      <title>DEV Community: Biprajit Biswas</title>
      <link>https://dev.to/biprajit_biswas_4915ce12b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/biprajit_biswas_4915ce12b"/>
    <language>en</language>
    <item>
      <title>Jana Sakhyam: Building a Voice That Speaks for the People</title>
      <dc:creator>Biprajit Biswas</dc:creator>
      <pubDate>Sat, 15 Aug 2026 08:49:59 +0000</pubDate>
      <link>https://dev.to/biprajit_biswas_4915ce12b/jana-sakhyam-building-a-voice-that-speaks-for-the-people-1lh6</link>
      <guid>https://dev.to/biprajit_biswas_4915ce12b/jana-sakhyam-building-a-voice-that-speaks-for-the-people-1lh6</guid>
      <description>&lt;p&gt;10 Days of Voice Agents — VoiceForBharat Edition using &lt;a href="https://murf.ai/" rel="noopener noreferrer"&gt;Murf AI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;1. The Problem and the Users&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ramesh has farmed a small two-acre plot in Uttar Pradesh for over twenty years. He uses a basic feature phone, speaks local Hindi, and left school after 6th grade. When his daughter came home from college and asked if he was receiving his ₹6,000 yearly PM-KISAN stipend, he had no idea. He didn't know if he qualified, what documents he needed, or where to go. Navigating a complex, English-heavy government portal wasn't an option, and losing a day’s farm wages just to stand in line at the block office with no guaranteed answer was too big a risk.&lt;/p&gt;

&lt;p&gt;This is the real gap in India—not a lack of government schemes, but a massive barrier to access. Millions like Ramesh miss out on entitlements simply because information isn't available in a format they can actually use. Worse, this same gap makes them prime targets for phone scams asking for OTPs under the guise of "releasing" their funds.&lt;/p&gt;

&lt;p&gt;Voice changes everything. By letting callers simply speak and listen in their native language, we strip away the literacy and technology barriers holding them back.&lt;/p&gt;

&lt;p&gt;To turn this into reality, I built Jana Sakhyam using the Murf Falcon TTS API—the fastest in the market—so farmers like Ramesh can have instant, natural, zero-latency conversations to check scheme eligibility, get document checklists, and protect themselves from fraud, all with a simple phone call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;2. What the Voice Agent Does&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Jana Sakhyam is a phone-based (and browser-based) voice agent, built around three pillars a caller can navigate with a single tap or spoken request:&lt;/p&gt;

&lt;p&gt;Government Schemes — eligibility checks, required documents, deadlines, for 5 major schemes (PM-KISAN, PM MUDRA, Atal Pension Yojana, Sukanya Samriddhi, Ayushman Bharat)&lt;br&gt;
Bank Scam Safety — recognising fraud patterns, reporting incidents&lt;br&gt;
Savings &amp;amp; Insurance — general banking literacy&lt;/p&gt;

&lt;p&gt;The main persona, Anjali Arora, handles the conversation. If a caller's question goes deep into scheme-specific eligibility or into fraud territory, Anjali hands the conversation to a specialist — Smita for schemes, Kriti for cyber fraud — without the caller repeating themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;3. How the System Works&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A real-time voice agent rests on four core components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. Speech-to-Text (STT) — converts the caller's spoken audio into text&lt;/li&gt;
&lt;li&gt;2. LLM — reasons about intent and decides what to say or which tool to call.&lt;/li&gt;
&lt;li&gt;3. Text-to-Speech (TTS) — converts the response back into natural audio — powered here by Murf Falcon, the fastest TTS API I tested, which mattered for keeping the conversation feeling real-time instead of laggy.&lt;/li&gt;
&lt;li&gt;4. Real-time transport — LiveKit handles audio streaming; SIP trunking (via Linphone) enables real inbound and outbound phone calls, not just browser conversations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;How audio moves through the system:&lt;/em&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%2Fzopw6nvg5a5mbri270tz.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%2Fzopw6nvg5a5mbri270tz.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Every response passes through a system prompt with hard safety rules: never ask for PINs or OTPs, never guarantee loan approval, always escalate anything outside the agent's scope to a human.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;_4. The Most Important Features&lt;br&gt;
_&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A named, consistent persona. &lt;em&gt;Anjali Arora&lt;/em&gt; isn't an unnamed bot — she has a defined role and personality, which made conversations feel noticeably more natural than a generic assistant would.&lt;/li&gt;
&lt;li&gt;Memory for returning callers. SQLite-backed memory lets the agent recognize returning users and greet them by name — only after explicit consent, and only after sensitive data (bank numbers, PINs, OTPs) is automatically stripped before anything is stored.&lt;/li&gt;
&lt;li&gt;A real eligibility engine, not a static FAQ. Structured eligibility rules and document checklists for all 5 schemes, with data-freshness metadata so the agent is transparent about when information was last verified — important for someone like Ramesh, who needs to trust the answer, not just hear one.&lt;/li&gt;
&lt;li&gt;Outbound calling. The agent doesn't just wait for calls — it can proactively reach out to remind eligible users about upcoming deadlines. If Ramesh had signed up, Jana Sakhyam could have called him, instead of waiting for Priya to bring it up.&lt;/li&gt;
&lt;li&gt;Human escalation. When something is too sensitive or out of scope, the agent raises a ticket — PII automatically scrubbed, duplicate-check protection — routed to a real dashboard, with the ability to call the user back once resolved.&lt;/li&gt;
&lt;li&gt;A call analytics dashboard. Tracks call topics and outcomes, so I can actually measure whether the agent is helping rather than assume it.&lt;/li&gt;
&lt;li&gt;Handoffs to specialist agents. The main agent recognizes when a question needs deeper expertise and hands off cleanly
:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@function_tool&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handoff_to_scheme_specialist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RunContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;query_reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;caller_question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Hand off the current caller and conversation to the Government Scheme Specialist agent.

        MUST CALL THIS TOOL WHEN:
        1. The user asks questions about Indian government financial schemes (PM-KISAN, PM MUDRA, Atal Pension Yojana, Sukanya Samriddhi, Ayushman Bharat).
        2. The user wants to check eligibility, required documents, or application procedures for any government financial scheme.

        DO NOT CALL THIS TOOL FOR:
        - General cyber safety, UPI PIN advice, online fraud helpline (1930) queries, or banking fraud reports.

        Args:
            query_reason: Summary of why the caller is being transferred to the specialist (e.g. &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Caller asked about PM-Kisan eligibility&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;).
            caller_question: The specific query or question asked by the caller (optional).
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;specialist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GovernmentSchemeSpecialist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;# Retain session context and switch active agent
&lt;/span&gt;            &lt;span class="n"&gt;call_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;userdata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;call_state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;call_state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;call_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transferred_to_specialist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
                &lt;span class="n"&gt;call_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;specialist_reason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query_reason&lt;/span&gt;
                &lt;span class="n"&gt;call_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;caller_question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;caller_question&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;

            &lt;span class="c1"&gt;# Update session's current active agent to GovernmentSchemeSpecialist
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;update_agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;specialist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isawaitable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;

            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🔀 Handoff initiated to GovernmentSchemeSpecialist (Smita) | reason=%s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query_reason&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;announcement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;मैं आपको हमारे सरकारी योजना विशेषज्ञ (Government Scheme Specialist) से कनेक्ट कर रही हूँ। कृपया एक पल रुकिए।&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;handoff_success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;spoken_announcement&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;announcement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;instruction&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Speak ONLY the spoken_announcement above to the user. Do NOT greet as Smita yourself. The specialist agent will introduce herself in her own voice on the next turn.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error executing handoff to specialist: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;spoken_failure_message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;माफ़ कीजिए, विशेषज्ञ एजेंट से कनेक्ट करने में कुछ समस्या आई है।&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;&lt;em&gt;5. Challenges and How I Overcame Them&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Voice mismatches across multiple agents&lt;br&gt;
. Once I introduced specialist agents, different agents sometimes defaulted to different TTS voices mid-conversation, breaking the illusion of a coherent handoff. I standardized on a single base voice across all agents, using persona differences (Anjali, Smita, Kriti) instead of different actual audio voices — simpler and far more reliable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A framework migration mid-build&lt;br&gt;
. Partway through, I had to rewrite tool registration — moving from an older &lt;a class="mentioned-user" href="https://dev.to/llm"&gt;@llm&lt;/a&gt;.ai_callable / FunctionContext pattern to the newer @function_tool decorator in livekit-agents 1.4+. This meant dropping type annotations and switching to plain docstrings. It cost an afternoon of debugging silent tool-call failures before I found the real cause: a version mismatch between what I'd written against and what was actually installed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A design decision I changed&lt;br&gt;
: I originally planned to give each specialist a distinct TTS voice, thinking it would make handoffs feel more dramatic. In practice it introduced bugs and felt jarring. I switched to one consistent voice, letting the specialist's spoken introduction ("Hi, I'm Smita, I specialize in...") signal the handoff instead — simpler and more robust.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Troubleshooting tip for other builders&lt;br&gt;
: if an outbound call fails with a bare dispatch_id error, check that your agent worker process is actually running and registered with LiveKit before dispatching. This error usually means the dispatch API call failed upstream, and the code just surfaces the missing response field instead of the real underlying error.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;6. How Readers Can Build and Run It&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.python.org/downloads/" rel="noopener noreferrer"&gt;Python 3.10+&lt;/a&gt; with &lt;a href="https://docs.astral.sh/uv/getting-started/installation/" rel="noopener noreferrer"&gt;uv&lt;/a&gt; installed&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/download/current" rel="noopener noreferrer"&gt;Node.js 18+&lt;/a&gt; with pnpm installed (npm install -g pnpm)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://livekit.com/" rel="noopener noreferrer"&gt;LiveKit Server CLI&lt;/a&gt; (livekit-server --dev)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Environment Setup&lt;/strong&gt;&lt;br&gt;
Create .env.local in both backend/ and frontend/ folders:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# LiveKit Credentials
&lt;/span&gt;&lt;span class="py"&gt;LIVEKIT_URL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;wss://your-livekit-domain.livekit.cloud&lt;/span&gt;
&lt;span class="py"&gt;LIVEKIT_API_KEY&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_livekit_api_key&lt;/span&gt;
&lt;span class="py"&gt;LIVEKIT_API_SECRET&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_livekit_api_secret&lt;/span&gt;

&lt;span class="c"&gt;# AI Models API Keys
&lt;/span&gt;&lt;span class="py"&gt;GOOGLE_API_KEY&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_gemini_api_key&lt;/span&gt;
&lt;span class="py"&gt;MURF_API_KEY&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_murf_api_key&lt;/span&gt;
&lt;span class="py"&gt;DEEPGRAM_API_KEY&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_deepgram_api_key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;a href=""&gt;Google API&lt;/a&gt;, &lt;a href="https://deepgram.com/" rel="noopener noreferrer"&gt;Deepgram API&lt;/a&gt;, &lt;a href="https://murf.ai/api" rel="noopener noreferrer"&gt;MURF API&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Start the Services&lt;/strong&gt;&lt;br&gt;
Run each component in a separate terminal:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Terminal 1 — LiveKit Server&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;livekit-server &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Terminal 2 — Escalation &amp;amp; Call Analytics REST API&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;backend
uv run python src/escalation_api.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Terminal 3 — Backend Voice Agent Workers (Anjali + Specialists)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;backend
uv &lt;span class="nb"&gt;sync
&lt;/span&gt;uv run python src/agent.py dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Terminal 4 — Next.js Frontend &amp;amp; Analytics Dashboard&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;frontend
pnpm &lt;span class="nb"&gt;install
&lt;/span&gt;pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Terminal 5 (Optional) — Trigger Outbound Phone Call&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;backend
uv run python src/outbound_call.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;7. Links&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
🔗 Code repository: &lt;a href="https://github.com/Abhrio-Star26/murf-livekit-starter" rel="noopener noreferrer"&gt;https://github.com/Abhrio-Star26/murf-livekit-starter&lt;/a&gt;&lt;br&gt;
🎥 Demo videos: Day 8 : &lt;a href="https://lnkd.in/p/dKUvuDz6" rel="noopener noreferrer"&gt;https://lnkd.in/p/dKUvuDz6&lt;/a&gt;&lt;br&gt;
                Day 2 : &lt;a href="https://lnkd.in/p/dzrTaXpC" rel="noopener noreferrer"&gt;https://lnkd.in/p/dzrTaXpC&lt;/a&gt;&lt;br&gt;
                Day 6 : &lt;a href="https://lnkd.in/p/dpHHwync" rel="noopener noreferrer"&gt;https://lnkd.in/p/dpHHwync&lt;/a&gt;&lt;br&gt;
(Caller data, phone numbers, and database files with real call history are excluded from the public repository.)&lt;/p&gt;

&lt;p&gt;Check out my &lt;a href="//www.linkedin.com/in/biprajit-biswas-54b611380"&gt;LinkedIn profile&lt;/a&gt; for More 😊&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note :&lt;/em&gt;  Built as part of the #VoiceForBharat challenge hosted by Murf AI, using Murf Falcon for text-to-speech throughout.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
