← All work
Independent Build

AI Voice Receptionist

A voice agent that answers inbound calls for a dental clinic — checking live appointment availability, answering questions it doesn’t already know the answer to, logging every conversation, and reviewing its own worst calls to improve its prompt.

The Problem

What needed solving

A clinic with no after-hours coverage loses patients silently. Calls go unanswered in the evening and at weekends, and the caller books somewhere else.

Reception staff also lose time each morning working through voicemails and transferring appointment requests into the calendar by hand.

This build set out to answer a specific question: could a voice agent hold a real intake conversation — checking live availability, looking things up it doesn’t know, and remembering callers between calls — well enough that no call goes unanswered?

The Build

How the system works

n8n workflow for the AI voice agent: a webhook receives the call payload and a rules-based router splits it by request type, branching to Calendly availability lookup, call logging and email reporting, a tools router covering email sending and Tavily web search, and a separate analysis flow that reviews saved conversations with an OpenAI model.
The voice agent in n8n — Vapi posts to the webhook, a rules router splits by request type, and the self-review flow runs along the bottom.
  1. Vapi handles the voice layer

    Vapi answers the inbound call and manages the spoken conversation — speech recognition, turn-taking and voice output. When it needs data or an action it cannot perform itself, it posts the request to an n8n webhook and waits for a response.

  2. A rules router splits the request by type

    The webhook payload hits a rules-based switch that reads what the agent is asking for and routes it down one of three paths: an availability check, a call-logging request, or a tool call.

  3. Live availability from Calendly

    For booking requests, the workflow queries the Calendly API for real open slots, formats the dates into something speakable, pulls the caller’s last conversation from Supabase for context, builds a prompt from both, and responds to the webhook so Vapi can say it out loud — all inside the live call.

  4. Tools the agent can reach for

    A second rules router gives the agent capabilities beyond its own knowledge: sending an email, running a Tavily web search when a caller asks something it has no stored answer for, or sending a confirmation to the caller alongside an internal notification to the clinic. Each branch responds to its own webhook so the agent gets the result mid-conversation.

  5. Every call written to Supabase

    Calls are created as rows in Supabase as they happen, and prior conversations are read back by caller on subsequent calls. The database is what lets the agent recognise a returning caller instead of starting cold every time.

  6. Email reporting

    Once a call is logged, a report goes out over Gmail so the clinic has a written record of what was discussed without opening a dashboard.

  7. The agent reviews its own worst calls

    A separate flow pulls all logged calls from Supabase, a JavaScript node filters down to the worst-performing conversations, and an OpenAI model reads them and proposes an improved system prompt. The revised prompt is written back to the database. The agent gets better from its own failures rather than from someone manually reading transcripts.

Stack

Tools used

Vapi (Voice AI) n8n Calendly API Supabase Tavily Search API OpenAI API Gmail API Webhooks
Outcome

What the system delivers

The agent answers calls at any hour and checks genuine Calendly availability during the conversation rather than promising a slot it cannot confirm.

Tavily search means a caller asking something outside the agent’s stored knowledge gets a real answer instead of a dead end.

Supabase gives it memory. A returning caller is recognised, and their previous conversation is available as context on the next call.

The self-review loop is the part I’d build again. Pulling the worst conversations and having a model rewrite the system prompt turns every bad call into an improvement instead of a complaint.

Have a process like this?

Tell me what your team keeps doing by hand and I’ll tell you what it would take to automate.