
Voice AI for Roofing Contractors: Full Retell AI Setup Guide
I deployed an AI voice agent for a roofing contractor using Retell AI + Claude. It answers every inbound call 24/7, qualifies storm damage leads, and books inspections automatically. Here's the full setup — conversation flows, system prompt, webhook CRM handoff, and 30-day cost breakdown.
The Problem: Roofing Leads Die on the Phone
A roofing contractor in the DFW area came to me with a straightforward problem: after every hailstorm, his phone rings non-stop for 72 hours. He misses about 60% of those calls. Each missed call is a potential $8,000–$25,000 job. His answering service costs $380/month and takes 4–8 hours to follow up. By then, the homeowner has already booked someone else.
This isn't unique to him. Roofing is one of the highest-CAC industries in home services because lead response time determines who wins the job. The contractor who calls back first closes 40–60% more deals. That's the entire game.
The solution wasn't more staff. It was a voice AI agent that answers every call instantly, asks the right qualification questions, captures lead data to the CRM, and books an inspection slot — all before the homeowner can dial the next contractor on Google.
What the agent needed to do:
- Answer calls 24/7 with a human-sounding voice (no IVR menus)
- Qualify: homeowner vs. renter, type of damage, insurance status
- Capture address, callback number, and preferred inspection time
- Push structured lead data to GoHighLevel automatically
- Cost under $100/month for 200+ calls
Why Retell AI (Not Bland, Vapi, or ElevenLabs)
I've tested all four platforms in production. Here's the honest breakdown for a home services contractor use case:
| Platform | Latency | Custom LLM | Price/min | Verdict |
|---|---|---|---|---|
| Retell AI | 600–800ms | Yes (any OpenAI-compatible) | $0.07–$0.11 | Best overall |
| Bland AI | 800–1200ms | Limited | $0.09/min | Good for simple flows |
| Vapi | 700–900ms | Yes | $0.05–$0.10 | Good, docs need work |
| ElevenLabs | 400–600ms | Yes | $0.10–$0.15 | Best voice quality, highest cost |
Retell wins for three reasons: the LLM websocket architecture gives direct control over the Claude system prompt without going through Retell's own prompt layer, the built-in Twilio integration eliminates separate phone infrastructure management, and the post-call webhook fires reliably on every call. With Bland I had webhook delivery failures on 2–3% of calls. For a roofing contractor at 200 calls/month during storm season, that's 4–6 lost leads per month — unacceptable.
Retell Agent Configuration
Create an LLM Agent in Retell — not a Simple Agent. You need full conversation logic control. Key settings for roofing:
- Voice: ElevenLabs "Josh" or "Adam" — male voices test better for contractor brands in the South. "Rachel" works well for female-presenting brands.
- Interruption sensitivity: Set to
0.3(low). Homeowners ramble when anxious about roof damage — don't cut them off. - Turn detection threshold: 1000ms. Slightly longer pause detection prevents jumping in while the caller is thinking.
- Max call duration: 10 minutes. Anything longer is a transfer scenario.
Agent creation via the Retell API:
curl -X POST https://api.retellai.com/v2/create-agent \
-H "Authorization: Bearer YOUR_RETELL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_name": "Alex — DFW Roofing",
"voice_id": "11labs-Adam",
"response_engine": {
"type": "retell-llm",
"llm_id": "YOUR_RETELL_LLM_ID"
},
"language": "en-US",
"interruption_sensitivity": 0.3,
"enable_backchannel": true,
"max_call_duration_ms": 600000,
"end_call_after_silence_ms": 8000,
"reminder_trigger_ms": 15000,
"reminder_max_count": 2
}'The enable_backchannel flag adds natural "mm-hmm" and "got it" responses while the caller speaks. This dramatically improves how human the agent sounds during longer explanations of damage — homeowners don't feel like they're talking at a void.
The System Prompt (The Most Important Part)
The system prompt is where most voice AI deployments fail or succeed. For a roofing contractor, the agent needs to handle four call types: storm damage, active leak, new roof quote request, and wrong number. It also needs hard guardrails — never quote prices, never promise timelines, always redirect to the inspection offer.
Here's the production system prompt I used:
You are Alex, a friendly scheduling assistant for [Contractor Name]
Roofing, a licensed contractor serving the DFW metroplex.
Your ONLY job: qualify the caller and schedule a free roof inspection.
## TONE
- Warm, confident, professional. Never robotic.
- Natural speech: "absolutely", "of course", "let me grab that for you"
- Mirror the caller's energy — calm if anxious, quick if rushed
## QUALIFICATION FLOW (one question at a time)
1. "Are you the homeowner at the property?"
→ If no: "No problem — can I get the best number for the homeowner?"
2. "What kind of roofing concern brought you to us today?"
→ Storm/hail → ask: "Did this happen in the last 12 months?"
→ Active leak → treat as urgent, offer next-day inspection
→ New roof → standard inspection flow
3. "What's the full address of the property?"
4. "Have you already filed an insurance claim, or are you still deciding?"
→ Filing: "Our inspectors document everything for the adjuster — no cost to you"
→ Undecided: "We can do a free inspection first and let you know if it's claim-worthy"
5. "What days and times work best for you this week?"
→ Offer: morning (8–12), afternoon (12–5), or specific day
6. "And the best number to confirm the appointment?"
## GUARDRAILS
- NEVER quote a price or cost estimate
- NEVER promise same-day service unless it's an active leak emergency
- NEVER discuss competitors
- Insurance questions: explain the free inspection, don't give legal/claim advice
## END OF CALL
After your closing statement ("Perfect — I've got you scheduled..."),
output this JSON block silently (do NOT read it aloud):
{
"lead": {
"is_homeowner": true,
"damage_type": "storm|leak|new_roof|other",
"property_address": "123 Main St, Plano TX 75023",
"insurance_status": "filed|considering|none",
"preferred_time": "Saturday morning",
"callback_number": "+19725551234",
"urgency": "high|medium|low"
}
}The JSON block is how I extract structured data from the conversation. Claude outputs it after the closing statement — Retell captures it in the transcript and my webhook handler parses it to create the CRM record.
Why Claude over GPT-4o for this?
I tested both. GPT-4o occasionally fabricated insurance details when callers pushed back on costs. Claude's instruction following is tighter on guardrails — it reliably refuses to quote prices and redirects to the inspection offer. For regulated topics adjacent to insurance claims, that reliability matters.
Conversation Flow Design
Beyond the linear qualification flow, I designed four branch states the agent handles gracefully:
Branch: "I'll Call Back Later"
Agent: "Of course — can I just grab your number so we can reach out when we have availability this week? Storm season fills up fast and we'd hate for you to wait." This captures the number even when the caller isn't ready to book. 60% of these partial captures convert within 48 hours.
Branch: "How Much Does It Cost?"
Agent: "The inspection is completely free — there's no cost to have us take a look. If there's damage, our team will document it for your insurance company. Most homeowners end up paying nothing out of pocket for storm damage repairs." Never deflect on pricing — reframe to the free inspection offer.
Branch: Active Leak Emergency
When caller says water is actively coming in: agent skips full qualification, captures address and phone only, flags urgency as "high" in the JSON output, and triggers a separate webhook branch that fires an immediate SMS to the contractor's personal cell.
Branch: Escalate to Human
Triggered by: angry tone, mention of legal action or BBB complaint, or explicit request to speak to the owner. Agent says: "Let me connect you with someone directly right now" and executes a warm Retell transfer to the contractor's mobile.
Transfer config for the escalation branch:
{
"transfer_call": {
"type": "warm_transfer",
"phone_number": "+19725550001",
"caller_id": "+19725550100",
"handoff_message": "Hi, transferring a homeowner with
an urgent roofing situation. Address: {{property_address}}.",
"transfer_conditions": [
"caller_requests_human",
"urgency == high",
"negative_sentiment_score > 0.8"
]
}
}Webhook Integration: Leads to CRM in 30 Seconds
Retell fires a call_ended webhook after every call. The payload includes the full transcript, call metadata, and dynamic variables. Here's the n8n Code node handler:
// n8n Code node — parses Retell post-call webhook
const body = $input.first().json;
// Extract JSON block from transcript
const transcript = body.transcript || '';
const jsonMatch = transcript.match(/\{[\s\S]*?"lead"[\s\S]*?\}/);
let leadData = {};
if (jsonMatch) {
try {
leadData = JSON.parse(jsonMatch[0]).lead;
} catch (e) {
// fallback to Retell dynamic variables
leadData = {
callback_number: body.retell_llm_dynamic_variables?.callback_number,
property_address: body.retell_llm_dynamic_variables?.property_address,
urgency: 'medium'
};
}
}
// Build GHL contact payload
const ghlContact = {
phone: leadData.callback_number,
address1: leadData.property_address,
customFields: [
{ id: 'damage_type', value: leadData.damage_type || 'unknown' },
{ id: 'insurance_status', value: leadData.insurance_status || 'unknown' },
{ id: 'preferred_time', value: leadData.preferred_time || '' },
{ id: 'urgency', value: leadData.urgency || 'medium' },
{ id: 'call_id', value: body.call_id }
],
tags: [
'voice-ai-lead',
`damage-${leadData.damage_type || 'unknown'}`,
leadData.urgency === 'high' ? 'urgent' : 'standard'
],
source: 'Retell AI Voice Agent'
};
return [{ json: ghlContact }];From this n8n node, the workflow splits into two branches: one POSTs to the GHL Contacts API to create the lead record, the other sends an SMS confirmation to the homeowner via Twilio. The GHL contact creation:
curl -X POST https://services.leadconnectorhq.com/contacts/ \
-H "Authorization: Bearer GHL_API_KEY" \
-H "Version: 2021-07-28" \
-H "Content-Type: application/json" \
-d '{
"locationId": "YOUR_GHL_LOCATION_ID",
"phone": "+19725551234",
"tags": ["voice-ai-lead", "damage-storm", "standard"],
"customFields": [
{ "id": "damage_type", "value": "storm" },
{ "id": "insurance_status", "value": "considering" },
{ "id": "urgency", "value": "medium" },
{ "id": "call_id", "value": "retell_call_abc123" }
],
"source": "Retell AI Voice Agent"
}'Cost Breakdown: Real Numbers
This contractor handles roughly 200 inbound calls/month during active season (March–June, October–November in Texas). Average call duration: 3.5 minutes.
| Component | Unit Cost | Volume | Monthly |
|---|---|---|---|
| Retell AI (LLM agent) | $0.09/min | 700 min | $63.00 |
| Claude Sonnet 4.6 API | ~$0.008/call | 200 calls | $1.60 |
| Twilio number + inbound | $1.15 + $0.0085/min | 700 min | $7.10 |
| n8n (self-hosted) | $0 | — | $0 |
| SMS confirmations (Twilio) | $0.0079/msg | 140 msgs | $1.11 |
| Total (200 calls/month) | ~$72.81/mo |
The answering service also had a 4–8 hour follow-up lag. The AI agent creates the CRM record within 30 seconds of the call ending and fires the SMS confirmation while the homeowner is still in their driveway looking at their roof. Speed wins deals in this market.
Testing, Launch, and Monitoring
Retell's call simulator lets you test the full conversation flow before forwarding the real number. I ran 40 test calls covering every branch state before launch. Issues caught in testing:
- Agent was cutting off callers who said "ummm" frequently — fixed by dropping interruption sensitivity from 0.5 to 0.3
- Claude was outputting the JSON block mid-conversation when it anticipated the call ending — fixed with explicit instruction: "output the JSON block ONLY after your closing statement"
- Transfer logic triggering on casual mentions of "the owner" unrelated to escalation — refined condition to require explicit request phrasing
Pre-Launch QA Checklist:
- Test all 4 call branches in simulator (storm, leak, new roof, escalation)
- Verify JSON block appears in transcript for every completed qualification
- Confirm webhook fires and n8n receives payload correctly
- Confirm GHL contact is created with correct tags and custom fields
- Test SMS confirmation delivery to a real number
- Test warm transfer to contractor's mobile from escalation branch
- Verify max call duration cutoff works cleanly
- Run a call with heavy background noise (contractors call from job sites)
For ongoing monitoring I built an n8n error workflow: if a Retell webhook arrives and the GHL contact creation fails, a Slack alert fires with the call transcript for manual recovery. In 30 days of production this triggered twice — both GHL API timeouts, not Retell failures.
Results After 30 Days
The agent went live during a hailstorm week in DFW. Here's what happened:
The 11pm call story is worth telling. A homeowner in Plano called during a Thursday night storm. The AI agent qualified her, captured the address, and booked a Saturday morning inspection — at 11:23pm. The contractor closed a $4,200 repair job from that call. That's the ROI case in one data point: $73/month in AI costs captured a job the contractor would have missed entirely.
What I'd Do Differently
Build for JobNimbus/AccuLynx first, not GHL
Most DFW roofing contractors use industry-specific CRMs, not GoHighLevel. GHL is an agency tool. Building the webhook handler for JobNimbus from day one would save a full onboarding conversation explaining why the leads go to a different system.
SMS follow-up for partial qualifications from day one
Added this in week two after noticing 20% of callers hung up before completing the flow. The partial-lead SMS — "Hi, you called us about your roof — can we schedule a quick call?" — recovered 6 leads in the first week alone.
Spanish-language flow from launch
DFW has a large Spanish-speaking homeowner market. Retell supports Spanish TTS and Claude handles it natively. Lost at least 8 calls to language barriers in month one. A 4-hour build that would have paid for itself immediately.
Retell knowledge base for FAQ handling
Retell supports attaching a knowledge base so the agent can answer FAQ-style questions without bloating the system prompt. Keeping FAQs in the knowledge base lets the contractor update answers without a developer touching the prompt — a much better maintenance pattern.
Frequently Asked Questions
How much does a Retell AI voice agent cost for a roofing contractor?
For 200 inbound calls/month averaging 3.5 minutes each, expect roughly $70–$95/month total: Retell AI at $0.09/min, Claude API at ~$0.008/call, and a Twilio number at ~$7/month. Traditional answering services run $300–$600/month for the same volume — a 70–80% cost reduction.
Can I use Retell AI without Twilio?
Yes. Retell offers managed phone numbers via their dashboard — no Twilio account required. You lose some control over call routing and number porting, but for a simple inbound setup it works fine. Recommend Twilio only if the contractor has an existing business number they want to forward rather than replace.
What Claude model works best for Retell voice agents?
Claude Sonnet 4.6 is the sweet spot. Low enough latency for natural conversation (typically 500–700ms with Retell's websocket architecture), smart enough to handle multi-turn objection handling and dynamic qualification flows without fabricating details.
How long does the full setup take?
From Retell account creation to first live call: 4–6 hours for an experienced developer. System prompt writing and conversation flow testing takes the most time — budget 2–4 hours just for that. Plan 1–2 weeks of post-launch tuning before client handoff.
Want This Built for Your Client?
I build Retell AI voice agents for contractors, service businesses, and agency clients. Setup takes 2–3 weeks including QA and CRM integration.
Get In TouchRelated Posts
Voice AI
Retell AI Setup Guide: Voice Agents That Actually Convert
A step-by-step Retell AI setup guide — voice config, webhook design, Claude prompts, and the conversion math behind the deploy.
n8n
n8n + Claude Content Pipeline: From Outline to Published Post
A production n8n workflow that takes an outline, drafts with Claude, runs QA passes, and publishes — with the prompts and nodes.
n8n
Supabase + n8n Lead Database: A Practical Build
A practical Supabase + n8n lead database — schema, dedupe logic, scoring with Claude, and the dashboards on top.