How to Build an AI Appointment Setter That Qualifies Callers Before It Books


Most guides to AI phone agents stop at the part where the agent picks up and says hello. That part is easy. The hard part is getting it to ask the questions your best dispatcher would ask, and to book the job only when the answers are worth booking.
Get that wrong and you have automated your noise. The calendar fills with renters who cannot authorize the work, callers outside your service area, and people who are three months from deciding anything. Every one of those is a slot a real job could have used.
This guide builds an AI appointment setter that qualifies first and books second. It is a conversation flow wired to a live Cal.com calendar, and it takes about fifteen minutes. If you came here only for the prompts, every one of them is collected in the prompt index near the end.
The video below is the same build, start to finish, on screen. Follow along with it if you would rather watch than read. The written steps and the prompts on this page match the video, so you can keep this open in a second tab and copy from it as you go.
Every inbound call that does not get a qualifying conversation ends one of two ways. It books a job that was never going anywhere, which burns a slot and a technician's drive time. Or nobody picks up fast enough and the caller moves to the next name on the list.
Both cost the same thing. The first wastes capacity you already paid for. The second hands revenue to a competitor whose phone was answered. An agent that qualifies solves both, because it answers on the first ring and refuses to book the calls that should not be booked.
When you create a new voice agent you get two choices: a single prompt agent, or a conversation flow agent.
A single prompt agent is one block of instructions the model reads and improvises around. It is fast to set up and fine for a linear script, like reading out hours and an address.
A conversation flow is a node by node map of the call with explicit branches. The caller's answer at each node decides which node comes next. The agent type comparison in the docs covers the full trade-off.
For qualification you want the flow. Qualification is a decision, and a decision needs branches you can see, test, and fix. If you cannot point at the node where a renter gets turned away, you do not have a qualification step, you have a hope that the model remembers your instructions.
Start from scratch rather than from a template if your qualifying criteria are specific to your business, which they almost always are.
You do not have to drag out every node by hand. Conductor is the AI copilot built into Retell: you describe the call you want, it proposes the nodes and branches, and you review before anything goes live.
Use prompt 1 from the prompt index at the end of this guide. The description is doing real work, so write it like a spec rather than a wish.
Conductor comes back with clarifying questions before it builds. Answer them concretely. Naming your exact service area, and naming Cal.com as the booking tool, is what lets it place the disqualify branch and the booking node correctly instead of guessing. Ask for placeholders on anything needing credentials you have not connected yet.
Read every node before you accept it. Conductor proposes, you approve, the same way you would review a pull request. This is the step people skip, and it is where a missing branch is cheapest to catch.
Here is the failure worth internalizing. You can write "if the caller says they're renting, end the call" and get a flow that contains a disqualify path which only fires when a caller happens to volunteer that they rent while answering something else.
That is not a qualifying question. That is luck.
What you do not explicitly ask for, you do not reliably get. If owner versus renter decides whether you send a truck, there needs to be a node whose only job is asking that question directly. Same for service area. Prompt 7 in the index checks whether those nodes exist, and prompt 8 adds them.
Booking needs a real calendar behind it, and this is the one step the copilot cannot do for you, because it needs your credentials.
In Cal.com, open Settings, find the API keys tab, and create a new key. Set an expiry that matches how long you expect to use it. In Retell, go to Integrations, add Cal.com, and paste the key. The account shows as connected once it takes.
That is the entire manual portion of the build.
Open the booking sub flow. Inside it you need two functions: one that checks availability, and one that books.
Both need your Cal.com event type ID. You find it in the URL of the booking link you want the agent to use. It is the number in that URL, and it goes in the event type ID input on each function.
Add the check availability function first, paste the event type ID, save. Then add the book appointment function, same event type ID, fill the remaining inputs, save. The full list of Cal.com functions covers rescheduling and cancellation too, once you need them.
With both real functions in place, run prompt 3 from the index so Conductor rewires the nodes to point at the live integration.
Run a test call from inside the dashboard and play a caller who should qualify.
What you are watching for is not whether the agent sounds good. It is whether the sequence holds. In a correct run the agent asks what is wrong, asks repair or replacement, asks owner or renter, confirms the service area, asks about urgency, then offers times.
Three checks catch the common breakages, and prompts 4, 5 and 6 in the index are the fixes:
Does it offer real times? If the agent says nothing is available while your calendar is open, it usually does not know today's date, so it is checking a window in the past.
Does it handle a date it did not already fetch? Ask for a day outside the times it first offered. A flow that checked once and never looks again insists that day is unavailable even when it is open.
Does it collect name and email before booking? Cal.com rejects a booking without them. If nothing asks, the booking fails after the caller has already picked a time, which is the worst possible place to fail.
Run the disqualify paths too. A renter with no authorization and a caller outside the service area should both end the call politely, with no booking attempted. Confirm that rather than assuming it.
Publish the agent, then buy a phone number and assign it. The same number works for inbound and outbound.
The habit worth building is reading call history. Every call leaves a transcript and a summary, so you can see what the caller wanted and how the agent handled it. In the test call for this build, the record shows a roof repair booked for a hole in an existing roof, at a rental property in Long Island City, with landlord permission on file.
That is the context your technician needs before the truck leaves, and nobody typed it. Prompt 9 in the index turns the same information into structured fields your CRM can read, using post-call analysis.
Read the first few weeks of transcripts properly. They tell you which question the agent asks badly, which branch nobody reaches, and which disqualification you forgot to build.
Once qualification holds, the useful additions are a second calendar so different job types route to different technicians, and dynamic variables so an agent answering a known customer already knows who is calling instead of asking from scratch.
The sequence matters. An agent that books the wrong callers faster is worse than no agent. Qualification first, then volume.
There are two ways to build this flow. You can describe it to Conductor and approve what it proposes, or you can place the nodes yourself and paste the instruction copy into each one. Both sets are here, along with a single spec that skips the four problems this build originally ran into.
If you only copy one thing from this page, copy this. It hands Conductor all four requirements at once instead of letting you discover them as bugs later.
Before building: connect Cal.com under the dashboard's Integrations page first (API key, cal.com vs cal.eu). Build the check-availability and book-appointment nodes using Retell's native Cal.com integration tools directly. Do not use placeholder custom functions.
Global prompt: include "Today's date and time is {{current_time}}. Always resolve relative dates, today, tomorrow, next Monday, in a couple of days, against this actual date. Never guess a date."
Availability node: always query a 14-day default window from today, regardless of how vague or specific the caller's first answer is. If the caller later names a date outside the currently fetched window, re-run the check with a window that includes it before saying it's unavailable.
Before the booking node: collect the caller's full name and email, both required fields for the Cal.com booking call. Do not call the booking function until both are captured.
That single block prevents four separate failures: placeholder functions pointed at nothing real, an agent that does not know today's date, an availability window too narrow to answer the caller's actual question, and a booking that fails because nobody asked for a name and email.
Type these one at a time and read what Conductor proposes before accepting. Prompts 4 through 6 are the fixes for the three failures in step 5, if you would rather hit them and solve them as you go.
1. Scaffold the flow
Build a conversation flow for an HVAC and roofing company. Greet the caller and ask if they need a repair or a full system replacement. Branch based on the answer. If the caller says they're renting and can't approve the work, or they're outside our service area, end the call politely without booking. Otherwise ask if they want this done in the next couple of weeks or if they're just collecting quotes, then move toward booking an appointment.
2. Swap the placeholders for your real calendar
Can check-availability and book-appointment be replaced with my actual Cal.com integration?
3. Point the flow at functions you wired by hand
I added the Cal.com integration functions. Please use those and substitute them into the placeholder sub nodes.
4. The agent says nothing is ever available
Every time I want to book an appointment the availability never works, it says they don't have appointments in the next couple days, why is that?
5. The availability window is too narrow
I tested it and the AI said availability was only through Friday, but today's Wednesday and the calendar lets me book next Monday. Why wouldn't the agent offer that?
6. The booking fails at the last step
We got the Monday booking, but then the booking fails, I think because of some info that needs to be collected first.
7. Check whether qualification actually exists
I don't see any qualification in the flow, do we have cases built for this?
8. Add an explicit qualifying layer
We need another qualification question layer to figure out if they're renting or own. Owning is fine, renting means we need authorization from the landlord. Same thing for location, outside of Queens, NY is a no.
9. Capture the lead data on the way out
Add a post-call analysis step that captures whether the caller qualified, whether it was a repair or a replacement, how urgent they said it was, and a one-line summary for the technician.
Paste each block into the matching node instead of prompting for it.
Agent-level prompt, set at the top of the flow
You are a scheduling assistant for a home services company that handles HVAC and roofing repair calls. Your job is to quickly understand what the caller needs, decide if it's worth sending a technician out for, and if so, book an on-site appointment. Keep it short and natural, like a friendly dispatcher, not a script being read aloud. Never make up availability, only use what the calendar tool returns.
Today's date and time is {{current_time}}. Always resolve relative dates against this actual date. Never guess a date.
Node 1, greeting and first question
Greet the caller and ask what's going on with their HVAC or roofing issue. Then ask: "Is this something you're looking to get repaired, or are you looking at a full system replacement?" Wait for their answer before moving on.
Node 2, branch conditions. These go on the edges out of node 1, not on a node of their own:
Node 3, disqualify
Politely explain this falls outside what we can schedule right now, either renting without owner authorization or outside our service area. Suggest they check with their property manager or reach back out if that changes. Thank them and end the call politely. Do not offer to book anything.
Node 4, urgency question
Ask: "Are you looking to get this done in the next couple of weeks, or are you just collecting quotes right now?" Use the answer to set urgency, but continue toward booking unless they clearly say they're not ready to schedule.
Node 5, collect contact info. This one sits between the urgency question and the booking node, and it is the step most builds forget:
Ask for the caller's full name and email address so we can send a confirmation. Keep it quick, one question at a time if needed. Do not proceed to booking until you have both.
Booking node, where the Cal.com functions live
Once both questions are answered and the caller wasn't disqualified, call Check Availability. Read back 2 or 3 open times in a natural sentence, not a list. Wait for the caller to confirm one out loud, then call Book Appointment with that time. Never call Book Appointment before a verbal confirmation.
Post-call extraction fields. Four fields worth capturing on every call: qualified as a boolean, true if booked and false if disqualified or declined. repair_or_replacement as a selector, taken from the first answer. urgency as a selector of this week, this month, or just quoting, taken from the second answer. And summary_for_tech as text, one or two sentences on the issue written for whoever shows up.
Run these as simulations before you put the agent on a real number. Conductor will ask you to confirm scope first, because simulation runs are billed.
Can you run a simulation test call where the caller says they're renting the property and can't approve the work? I want to confirm the agent declines to book and ends the call instead of continuing toward booking.
Same thing but for a caller outside our service area, can you simulate that and confirm it ends the call without booking?
If a live call books someone it should have turned away, these two diagnose it:
I tested a call as a renter who can't approve the work, but the agent kept going and tried to book anyway, why isn't it disqualifying that answer?
I called from outside our service area and it still offered to book, why isn't the disqualify branch firing?
About fifteen minutes for the build in this guide, from an empty account to a published agent with a phone number. Budget more for testing. The flow itself is scaffolded from one prompt, but the test calls that catch date handling, availability windows and missing booking fields are where the real time goes.
No. The whole flow is built by describing it in plain language and approving what the copilot proposes. The only manual steps are pasting a Cal.com API key and copying an event type ID out of a URL.
A single prompt agent reads one block of instructions and improvises. A conversation flow is an explicit node by node map with branches you can inspect and test. Use a single prompt for a linear script, and a conversation flow whenever the call involves a decision, which qualification always does.
Yes. Cal.com is used here because its booking API is straightforward to wire up. The same pattern, a check availability function followed by a book appointment function, applies to other calendar integrations.
Two usual causes. The agent does not know the current date, so it is checking a window that has already passed. Or it checked a narrow window once and never re-checked when the caller named a different day. Prompts 4 and 5 in the prompt index fix each case.
They reach a disqualify node that ends the call politely without booking anything. That path has to be built explicitly. Describing the rule in your first prompt is not enough, which is what prompts 7 and 8 exist to catch.
See how much your business could save by switching to AI-powered voice agents.
Total Human Agent Cost
AI Agent Cost
Estimated Savings
A Demo Phone Number From Retell Clinic Office

Start building smarter conversations today.


