Inspiration
Too many government benefits go unclaimed — not because people don't qualify, but because the application process is confusing, the information is buried across dozens of websites, and the people who need help the most (seniors, newcomers, people with disabilities) are the least likely to navigate complex digital systems. In Kingston alone, millions in provincial and federal benefits go unclaimed every year.
We asked: what if getting help was as simple as picking up the phone and having a conversation?
What it does
guvi is an AI-powered civic assistant that helps Kingston residents discover government benefits, report city issues, and get answers about city services, through a phone call, a text message, or web chat.
A senior can call guvi, say "I'm 72, I live alone, and I'm on a fixed income", and within minutes guvi will match them to programs they qualify for, like the Municipal Fee Assistance Program, the Ontario Electricity Support Program, or the Guaranteed Income Supplement, and tell them exactly how much they could save and how to apply. Across a typical conversation, guvi finds $10,000–$20,000+ in annual savings that residents didn't know they were eligible for.
guvi also handles service requests (potholes, streetlight outages, bylaw issues), answers city info questions (garbage schedules, transit routes, City Hall hours), and provides a real-time dashboard where residents can track their conversations, matched benefits, and reported issues, all scoped securely to their phone number.
How we built it
guvi is a full-stack multi-channel AI agent built on Next.js and Supabase, with a custom WebSocket server for real-time voice:
Voice Pipeline: Twilio receives inbound calls and opens a bidirectional Media Stream over WebSocket. Audio flows to Gradium and ElevenLabs for real-time speech-to-text, then to Claude (via Anthropic's tool-use API) for reasoning and response generation, and back through ElevenLabs Flash TTS for natural speech output. The system supports barge-in (callers can interrupt mid-sentence), filler phrases during tool execution latency, and sentence-level streaming so Guvi starts speaking before the full response is generated.
SMS Pipeline: Twilio's SMS webhook hits our API, which returns empty TwiML immediately (to avoid Twilio's 15-second timeout) and enqueues background processing. Claude processes the conversation, and the response is sent back via Twilio's REST API, split into natural paragraph-sized chunks.
Agent Architecture: All channels share a unified agent loop powered by Claude's tool-use capability. Claude decides when to call toolsm lookup_benefits (matches 50+ municipal/provincial/federal programs), get_city_info (FAQ + semantic RAG search over 20+ city knowledge documents), lookup_garbage_schedule (ReCollect API), or submit_service_request. The loop handles parallel tool calls and multi-step reasoning (up to 6 turns).
Benefits Engine: User profiles are extracted incrementally from natural conversation. Once enough info is gathered (age, income, household size, etc.), a scoring algorithm evaluates eligibility across 50+ programs with confidence levels and estimated annual savings.
Dashboard: A React dashboard with Supabase Realtime subscriptions shows live metrics, matched benefits, conversation history, and service requests, all phone-scoped so users only see their own data.
Challenges we ran into
Voice latency was brutal. A phone conversation needs sub-second response times or it feels broken. We had to optimize every millisecond: streaming Claude's output sentence-by-sentence to TTS instead of waiting for the full response, using Haiku for voice (faster) and Sonnet for SMS/web (smarter), keeping conversation state in-memory during calls, and only persisting to the database every 5 turns.
Accomplishments that we're proud of
- A senior can call a phone number and discover $18,000/year in unclaimed benefits through a natural 3-minute conversation, no apps, no websites, no forms.
- The voice experience feels genuinely conversational: barge-in support, natural filler phrases ("One sec, let me check on that"), sentence-level streaming, and silence detection tuned to conversational rhythm.
- 50+ benefit programs with real eligibility matching; not just a list, but personalized confidence scores and estimated savings based on the user's actual situation.
- A production-grade agent loop that handles parallel tool calls, multi-step reasoning, and graceful fallbacks across voice, SMS, and web, all from a shared codebase.
- Phone-scoped data isolation across the entire dashboard, so no user can ever see another user's data.
What we learned
- Elderly accessibility is a design discipline, not an afterthought. We redesigned the entire dashboard following WCAG AAA guidelines, including 16px minimum text, 44px touch targets, 7:1+ contrast ratios, plain language labels ("Report an Issue" not "Service Requests"). Small changes made a massive difference in usability.
- Voice AI is a fundamentally different UX from chat. You can't send a wall of text over a phone call. Responses need to be 2–3 sentences max, conversational in tone, and streamed at sentence boundaries. The latency budget is measured in hundreds of milliseconds, not seconds.
- The hardest part of benefits matching isn't the algorithm, but rather gathering the data. People don't volunteer their income or disability status unprompted. The agent needs to ask naturally, remember across turns, and know when it has enough to match confidently.
What's next for guvi.
- Expanding to more municipalities: the architecture is city-agnostic, with the knowledge base and programs as pluggable data layers.
- Application assistance: not just finding programs, but walking users through the actual application process step-by-step over the phone.
- Proactive outreach: when new programs launch or eligibility criteria change, Guvi could call or text residents who might qualify.
- Multilingual support: Kingston has significant Francophone and newcomer populations who would benefit from conversations in their preferred language.
- 311 integration: connecting service requests directly to Kingston's municipal work order system for real-time status tracking.
Built With
- claude-(anthropic-api)
- elevenlabs-(speech-to-text-+-text-to-speech)
- gemini-(google-ai-embeddings)
- gradium
- next.js
- node.js
- radix-ui
- react
- recharts
- supabase-(postgresql-+-pgvector-+-realtime)
- tailwind-css
- twilio-(voice-+-sms)
- typescript
Log in or sign up for Devpost to join the conversation.