AI Receptionist for Roofers: Why Storm Leads Get Lost

On this page
A hail line crosses three ZIP codes at 7 p.m. By midnight your platform's roofing customers have taken hundreds of calls. The dashboard says "100% answered." Nobody can say how many homeowners called and never became a usable lead.
This post is for product teams at roofing CRM and field software companies. Many sell an AI answering service for roofers as a feature. Inspection booking under surge is covered in our post on testing roof inspection booking before storm season. This one covers lead capture: why storm leads get lost, and how to measure and test it.
Where a storm lead actually gets lost
Storm surge is real and sudden. After an April 28, 2026 hailstorm in the Ozarks, one roofing owner told KY3 he went from "a handful of calls each day" to "hundreds of phone calls a day." His inspection lead time grew to two to three weeks. For that long, the lead record is the only thread back to the homeowner.
The call is the front door to a five-step workflow:
1. Capture. Name, callback number, address, damage, insurance status.
2. Create. A lead record is written to the CRM.
3. Route. The lead lands with the right sales territory or rep.
4. Confirm. The caller hears what happens next.
5. Follow up. A human or an outbound call works the lead.
A lead can fail at any step while the call sounds fine. The caller hears "Someone will call you back today." That sentence plays whether the lead was saved correctly, saved wrong, or never saved. It is the capture-to-write-back chain from our home services QA guide, squeezed into one storm night.
Lost lead: a real homeowner who called about their roof and did not become a contactable, correctly routed CRM lead within 24 hours. Tighten the window once you can measure it.
Nine ways an AI receptionist for roofing companies loses a lead
These nine failure modes cover roofing lead capture from first word to first follow-up. Each one is silent on the call itself.
| # | Failure | What the CRM shows | How you find it |
|---|---|---|---|
| 1 | Wrong callback number | A lead with a dead or wrong number | Callback differs from caller ID, unconfirmed |
| 2 | Address or subdivision wrong | Lead in the wrong place, or no geocode | Geocode fails, or ZIP disagrees with city |
| 3 | Insurance fields missing | No carrier, no claim status | Required-field completeness by tag |
| 4 | Call drops before the write | No lead at all | Phone log call with no matching lead |
| 5 | Duplicate merged wrongly | Two homes in one record | Audit of merges by address and phone |
| 6 | Wrong sales territory | Lead sits in an idle queue | Territory vs geocoded address |
| 7 | Voicemail-only lead | A recording nobody opened | Voicemails with no lead or no task |
| 8 | Homeowner flagged as spam | Lead hidden in a junk bucket | Sample of spam-labeled calls |
| 9 | Retail vs insurance mis-tagged | Lead in the wrong pipeline | Tag vs what the caller said on audio |
Failures 4, 7 and 8 leave no lead at all. Your CRM cannot report on a record that does not exist. Only the phone log knows those callers. That is why reconciliation, covered below, is the core measurement.
Callback numbers: ten digits, said fast, outdoors
Phone numbers are the hardest field on a storm call. The caller stands in the yard and says ten digits fast, with "double" or "oh." One wrong digit kills the lead.
Research on spoken dialogue shows how fragile slot capture is. The SpokenWOZ benchmark recorded 249 hours of human-to-human task calls. The best state tracker got every slot right at once in only 25.65% of turns. An earlier DSTC10 robustness study found a tracker trained on written data fell from 54.27% to 0.43% on spoken data. The test sets differ, so the gap is indicative. Still, text-tested extraction breaks on speech.
Three cheap defenses work well together:
- Compare with caller ID. If the stated number differs from caller ID, ask which one to use.
- Validate the shape. In the North American Numbering Plan, the area code and the exchange start with 2 through 9. NANPA reserves 555-0100 through 555-0199 as fictitious numbers. A stored number that fails these rules is a capture error, not a lead.
- Read back in groups. "417, 555, 2 1 8 9?" lets the caller catch one swapped digit.
Addresses in new subdivisions
Storms hit new subdivisions with streets your geocoder has never seen. "Oak Ridge Circle" becomes "Oak Ridge Court." USPS Publication 28 defines a "complete address" as one with every element needed to match the ZIP+4 file. Treat anything less as incomplete, and ask for the cross street. Address tests are covered in the roof inspection post.
Dropped calls: the lead that never existed
Cell coverage is patchy after storms, and callers hang up to answer a neighbor or an adjuster. Many voice agents call a `create_lead` tool only near the end of the call, after read-back. If the call drops at second 48, the tool never runs. The caller gave a name and an address, yet the CRM has nothing.

The fix is a progressive write. Create a draft lead at the first usable contact field. Update it per slot. Close it from a server-side hang-up event, not from the model.
On Twilio, a phone number's `statusCallback` URL gets call status updates for that number. The call resource docs say the `completed` event fires "regardless of the termination status." Terminal events carry `CallDuration` in seconds and a `SipResponseCode`. Two gotchas matter here. First, Twilio warns that status requests may arrive out of order, so use `SequenceNumber`. Second, the hang-up handler must be idempotent, because a retry should never create a second lead.
Flag it with `status = partial` and `next_action = call back`. A partial lead with a name and caller ID is still a lead.
Duplicates and wrong merges
Storm callers call back after drops and holds, and spouses call from a second phone. Dedupe is needed. Bad dedupe is worse than none.
Two merge rules cause most damage:
- Merge by address alone. "1204 Maple" exists in two towns, or as two units in a duplex. Two homeowners become one lead, and one of them never hears back.
- Merge by phone alone. A landlord calls about four rentals. A storm-restoration public adjuster calls for several clients. One phone, many properties, one record.
Each wrong merge is a duplicate lead problem solved the wrong way. A safer key is phone plus normalized address, with a human review queue for near-matches. Never let the voice agent itself decide a merge mid-call.
Wrong sales territory
Contractors route leads by ZIP, county or drawn polygon, using the address the agent heard. A wrong address means a wrong territory. A ZIP that spans two territories breaks ZIP-only rules. Either way, the lead sits in a queue nobody works.
Check territory against the geocoded point, not the spoken ZIP. Alert on any lead with no territory at all. The same many-configs problem appears in our post on testing one agent across hundreds of customer setups.
Spam, solicitation and the homeowner in the junk folder
Storm nights bring lead sellers, agencies, crews seeking subcontract work and robocalls. State officials such as Louisiana's attorney general warn homeowners about out-of-state "storm chasers." Some of those outfits call contractors too.
Filtering helps, but it has two error directions. Letting spam into the CRM wastes rep time. Labeling a real homeowner as spam loses a lead with no trace. STIR/SHAKEN lets carriers verify that caller ID is real. It says nothing about intent. Twilio's `StirStatus` attestation is a useful signal, not a lead filter. Sample spam-labeled calls every storm week and listen to them.
Insurance or retail: the tag that picks the pipeline
An insurance job needs an insurance carrier, claim status and often an adjuster date. A retail job needs scope and budget questions. A wrong tag sends the lead down the wrong pipeline.
Carrier names are hard for speech recognition. "USAA" may be spelled letter by letter. "Allstate" can come back as "all state." Store carrier as a picklist value plus the raw transcript, and allow `unknown`. Claim status should be `not filed`, `filed`, `adjuster scheduled` or `unknown`. Never let the agent guess, or say what insurance will cover. State limits on contractor claim talk are in the roof inspection post.
Worked example: 418 calls, 63 lost leads
Here is an illustrative storm night for one contractor. The numbers are a worked example, not measured data.

Start with the phone log, not the CRM:
- 418 inbound calls
- minus 52 solicitation and spam calls
- minus 41 existing customers asking about jobs
- minus 9 hang-ups under 10 seconds with no voicemail
- = 316 calls from prospective homeowners
- minus 37 repeat calls from the same people
- = 279 unique homeowners
Now match those 279 against the CRM. Suppose 216 are contactable, correctly routed leads after 24 hours. That leaves 63 lost leads, or 22.6% of genuine demand.
| Cause | Lost leads |
|---|---|
| Call dropped before the lead write | 14 |
| Wrong or invalid callback number | 12 |
| Voicemail-only, never worked | 11 |
| Routed to the wrong territory | 9 |
| Merged into another home's record | 6 |
| Real homeowner labeled spam | 6 |
| Address unusable, no callback either | 5 |
| Total | 63 |
If 30% of leads become signed jobs, 63 lost leads is about 19 jobs. Meanwhile the answered rate reads 100%. Your customer sees the gap only if your product computes it.
Six numbers that show whether storm leads are leaking
Answer rate is not a lead metric. Track these six per contractor, per storm week.
| Metric | Formula | Starting threshold |
|---|---|---|
| Lead capture rate | Unique genuine callers with a CRM lead within 15 min ÷ unique genuine callers | ≥ 99% |
| Dropped-call lead creation | Partial leads created ÷ dropped calls with at least one captured field | 100% |
| Required-field completeness | Leads with callback, address, territory and job tag ÷ leads | ≥ 95% |
| Contactability | Leads reached on the stored number within 24 h ÷ leads attempted | Within 5 pts of human-answered leads |
| Wrong-merge rate | Merges reversed in audit ÷ merges | ≤ 1% |
| Spam false-positive rate | Homeowners found in a 50-call spam sample ÷ 50 | 0 |

The thresholds are starting points, not industry standards.
Add one comparison metric: lead-to-inspection conversion by source. Split leads by lead source: AI-answered live, AI after hours, voicemail, human-answered, web form. If AI-answered leads convert to inspections 10 points below human-answered leads, look at contactability and routing first. Our lead quality post for moving companies uses the same source-split pattern.
For sampling math and field-level grading against call audio, see the booking accuracy scorecard. Broader lead metrics are in metrics for a lead qualification voice agent.
Code: reconcile the phone log against CRM leads
This lead reconciliation check finds failures 4, 7 and 8. Run it nightly and after every storm. Simplified, standard library only.
# Simplified: find genuine callers with no CRM lead, and leads with bad contact data.
GENUINE_MIN_SECONDS = 10
def norm(num: str) -> str:
return "".join(c for c in num if c.isdigit())[-10:]
def valid_nanp(n: str) -> bool:
# Area code and exchange start with 2-9; 555-0100..0199 is fictitious.
return (len(n) == 10 and n[0] in "23456789" and n[3] in "23456789"
and not (n[3:6] == "555" and n[6:8] == "01"))
def reconcile(calls, leads, spam_numbers, customer_numbers):
by_sid = {l["source_call_sid"]: l for l in leads if l.get("source_call_sid")}
by_phone = {}
for l in leads:
for p in (l.get("caller_id"), l.get("callback_phone")):
if p:
by_phone.setdefault(norm(p), l)
orphans, suspects, seen = [], [], set()
for c in calls: # one row per CallSid from your telephony logs
caller = norm(c["from"])
if caller in seen or caller in spam_numbers or caller in customer_numbers:
continue
if int(c["call_duration"]) < GENUINE_MIN_SECONDS and not c.get("voicemail_url"):
continue
seen.add(caller)
lead = by_sid.get(c["call_sid"]) or by_phone.get(caller)
if lead is None:
orphans.append(c) # in the phone log, missing from the CRM
continue
cb = norm(lead.get("callback_phone", ""))
if not valid_nanp(cb):
suspects.append((caller, "invalid callback number"))
elif cb != caller and not lead.get("callback_confirmed"):
suspects.append((caller, "callback differs from caller ID, unconfirmed"))
if not lead.get("territory"):
suspects.append((caller, "no territory"))
if lead.get("job_tag") not in {"insurance", "retail", "unknown"}:
suspects.append((caller, "missing insurance/retail tag"))
return orphans, suspectsTwo notes. Store the `CallSid` on every lead as `source_call_sid`, or matching falls back to phone numbers. And note that `spam_numbers` comes from your filter. Feed a sample of those calls to a human, or the spam false-positive rate stays invisible.
How storm conditions break capture
Quiet-day tests miss the conditions that cause the losses above. Three matter most.
Noisy outdoor callers
Storm callers stand in wind and rain, near generators, and pause to look at the roof. Speech recognition can fail in noise and invent words in silence. The Careless Whisper study found about 1% of Whisper transcriptions held text that was never spoken. Hallucinations were more common for speakers with longer non-speech stretches. A long pause while someone walks to the gutter is exactly that stretch.
Test digit capture under wind noise with long pauses mid-number. Our guide to testing STT under background noise covers how to mix noise at set levels.
Partial and interrupted calls
Script calls that end at every step: after the name, mid-number, during read-back, and while on hold for a transfer. Each should leave a partial lead with whatever was captured. Also script callers who interrupt the read-back with a correction. The stored value must be the correction.
Surge concurrency on the CRM write
At surge, the CRM write can fail while the voice side holds up. Rate limits and webhook timeouts return errors a model can ignore. The agent still says "you're all set." Test lead writes at your storm peak concurrency, and assert that every failed write is retried or queued. Sizing math for storm peaks is in the roof inspection post. Causes and fixes for agent-side load are in concurrency failure in voice agents.
| Scenario | Quiet, clear | Wind and rain noise | Call drops mid-flow | 100 concurrent calls |
|---|---|---|---|---|
| Callback differs from caller ID | Confirm asked | Digits correct | Partial lead, caller ID kept | Write succeeds |
| New subdivision address | Cross street asked | Street not invented | Partial lead | Territory set |
| Insurance claim filed, carrier named | Tag insurance | Carrier or `unknown` | Tag kept | No field loss |
| Second call from same homeowner | Linked, not merged | Linked | Linked | No double lead |
| Lead seller pitching services | Not a lead | Not a lead | No lead | No lead |
Evalgent fits this kind of matrix. It generates scenarios from your agent's prompt and flows. It then calls the agent over PSTN, SIP or WebRTC with caller profiles that set background noise, speech pace, interruption level and response delay. Verdicts are judged from the call audio, not only the transcript, so a misheard digit is caught against what was said.
Outbound storm follow-ups and TCPA
Many platforms add outbound follow-ups after a storm, such as a callback to a dropped caller. The FCC's declaratory ruling of February 2024 recognizes AI-generated voices as "artificial" under the TCPA. Consent rules for such calls are in 47 CFR 64.1200.
Revocation rules are changing. FCC 26-67 was adopted September 30 and released October 1, 2026, per Kelley Drye. It allows exclusive opt-out methods and drops "revoke all." It takes effect 30 days after Federal Register publication. Nixon Peabody reported that had not happened as of October 7, 2026.
Test that follow-ups stay informational, state the opt-out method and log every "stop calling." See the outbound voice agent testing plan and TCPA checks for speed-to-lead calls. This is not legal advice.
One agent, many roofing contractors
On a platform, an AI receptionist for roofing companies runs for many contractors at once. Each has its own territories, required fields and handoff rules. Products differ in what a call creates. JobNimbus support says its AssistAI "creates tasks to schedule appointments" for unknown callers. For existing customers it "creates notes on the Contact and Job levels." A task, a note and a lead reconcile differently. Decide which record counts as "the lead" before you measure capture.
Per-contractor config is where storm-week bugs hide: a new required field, redrawn territories, a prompt change that reaches everyone. Reconcile per contractor. A platform average hides one broken setup.
How to test an AI receptionist for roofing companies before storm season
1. Define a lost lead. Fix the record type, required fields and time window that count as "captured."
2. Store the call ID on every lead. Add `source_call_sid` and `caller_id` fields.
3. Move to progressive writes. Create a partial lead after the first usable contact field. Close it from the hang-up status event, idempotently.
4. Add capture guards. Compare callback with caller ID, validate NANP shape, read back in groups, and require a cross street for unknown streets.
5. Fix dedupe rules. Link repeat calls by phone plus address. Send near-matches to human review. Never merge on address or phone alone.
6. Run the scenario matrix. Cover dropped calls at each step, wind noise, corrections during read-back, landlords with several properties, lead sellers and insurance versus retail callers.
7. Load-test the CRM write path. Hit your storm peak concurrency and assert zero silent write failures.
8. Reconcile nightly in production. Run the phone-log-versus-CRM check per contractor. Sample 50 spam-labeled calls each storm week.
9. Report the gap to customers. Show lead capture rate next to the answered rate.
For step 8, Evalgent's production monitoring takes pushed call recordings, transcribes them, maps each call to a scenario and judges it. It flags tool-call failures, so a lead write that errored mid-call shows up next to the call that caused it. See also the AI phone agent go-live checklist.
Frequently asked questions
Can an AI receptionist answer calls for a roofing company?
An AI receptionist can answer calls for a roofing company, including storm-night surges a small office cannot staff. Answering is the easy part. The harder part is turning each call into a correct lead: a confirmed callback number, a usable address, the right territory and an insurance or retail tag. Measure lead capture, not answer rate.
Why do roofing companies lose storm leads?
Roofing companies lose storm leads mostly to silent capture failures, not unanswered calls. Common causes are dropped calls before the lead is saved, wrong callback digits, voicemails nobody works, wrong-territory routing, wrong duplicate merges and real homeowners filtered as spam. Each looks fine on the call. Only matching the phone log against the CRM shows the loss.
How do you know if an AI receptionist is losing leads?
Match every genuine caller in the phone log to a CRM lead within a set window, such as 15 minutes. Callers with no lead are losses. Then check each lead's callback number, territory and job tag. Compare lead-to-inspection conversion for AI-answered leads with human-answered leads. A gap of 10 points or more signals a capture problem.
What should an AI receptionist capture from a roofing lead?
A roofing lead needs a name, a confirmed callback number, a complete service address with cross street if unclear, the damage type and urgency, and an insurance or retail tag. Insurance leads also need carrier and claim status, with "unknown" allowed. Store the call ID and caller ID on the lead so it can be reconciled later.
What happens to a lead when a call drops?
When a call drops, the lead is lost if the agent only saves it at the end of the call. The fix is a progressive write: create a partial lead once one contact field is captured, then close it from the server's hang-up event. A partial lead with a name and caller ID still gets a callback.
How should an AI receptionist handle spam calls after a storm?
After a storm, an AI receptionist should screen out lead sellers, crews seeking subcontract work and robocalls without creating leads for them. The risk runs both ways. A homeowner wrongly labeled as spam disappears without a trace. Sample about 50 spam-labeled calls each storm week and listen to them. STIR/SHAKEN verifies caller ID, not intent.
Should an AI receptionist tag insurance or retail roofing jobs?
An AI receptionist should tag each roofing lead as insurance, retail or unknown, because the tag picks the sales pipeline and the first call. It should record carrier and claim status as stated, never guess them, and never say what insurance will cover. State laws in places like Florida and Texas limit contractor claim talk.
Can an AI receptionist make storm follow-up calls?
An AI receptionist can make storm follow-up calls only with the right consent. The FCC confirmed in 2024 that AI-generated voices count as artificial voice under the TCPA. FCC 26-67, released October 1, 2026, changes opt-out rules once published. Keep follow-ups informational, state the opt-out method and log every request. This is not legal advice.
The bottom line
An AI receptionist for roofing companies can answer every storm call and still lose leads without a trace. Match the phone log to the CRM every night, test dropped and noisy calls before hail season, and report lead capture rate to customers next to the answered rate.
Related Articles

How to automate voice agent testing: synthetic callers vs manual QA
Learn how ai test automation replaces manual QA for voice agents. Compare synthetic callers vs human testers, with a 5-step framework to scale without hiring.
Read more
AI Agent Testing vs Voice Agent Testing: What General Tools Miss for Voice
AI agent testing measures text outputs. Voice agent testing measures behaviour through an acoustic pipeline. Five failure categories general tools miss.
Read more