Missed call recovery agent for CallRail and HubSpot

Every 30 minutes, find missed and abandoned CallRail calls, look up each caller in HubSpot, and send a personalized callback text from the tracking number they dialed.

Agentic Task
CallRailHubSpotSlack BotSalesCustomer SupportNotifications & AlertsLead Enrichment

Build me an agent-based workflow that recovers missed inbound calls by sending a personalized text from the same tracking number the caller dialed.

Trigger: cron, every 30 minutes, only during business hours (Monday to Friday, 8am to 6pm in my local timezone). Make the schedule and business-hours window easy to edit.

On each run, do the following:

1. Use the CallRail List All Calls operation to fetch calls from the last 30 minutes where answered is false. Include missed calls, voicemails, and abandoned calls. Request the fields needed to get the caller's phone number, the caller's display name if CallRail has one, the tracking number that was dialed, the call's start time, and the call's CallRail URL.

2. For each missed call, use the HubSpot Search Contacts operation to look up the caller by phone number. If a contact matches, pull their first name, last name, lifecycle stage, contact owner, and any associated active deals (deal name, stage, amount, close date). If multiple contacts match, prefer the one with the most recent activity.

3. Decide whether to skip. Skip the caller (do not text, but still post a Slack notice) if they are associated with an active deal whose stage is past discovery (for example: qualified to buy, presentation scheduled, decision maker bought-in, contract sent, closed won). The exact late-funnel stages should be configurable. The goal is to never auto-text a prospect who is already in active sales conversations with a rep.

4. For callers we are not skipping, draft a short, personalized SMS apology and callback offer. If we have a HubSpot match, greet them by first name and reference relevant prior context lightly (for example, the open deal name or the fact that they are an existing customer) without sounding creepy. If no contact was found, fall back to a friendly generic apology. Keep the text under 320 characters, sign off with the business name, and include a callback offer.

5. Send the SMS using the CallRail Send a Text Message operation. The from number must be the same CallRail tracking number that the caller originally dialed so attribution is preserved and the text appears as a reply from our business line. The to number is the caller's phone number.

6. Post a one-line summary per missed call into a configurable Slack channel (default: #sales) using the Slack Bot Send a Message operation. Each line should include: caller name (or phone number if unknown), the HubSpot contact link if matched, the SMS body that was sent (or "skipped: late-funnel deal" if we skipped), a click-to-call tel: link to the caller's number, and the CallRail URL for the call. Use Slack mrkdwn formatting (single asterisks for bold, angle-bracket links). If there are no missed calls in the window, post nothing.

Other requirements:

- Be idempotent within a run window: do not text the same phone number twice in a single run, even if they have multiple missed calls. Combine those into one summary line.

- Respect CallRail's SMS rate limit (150 sends per hour) and HubSpot's search rate limit (4 requests per second) by spacing out requests if there is a large batch.

- Expose the following as easy-to-edit inputs at the top of the agent instructions: the Slack channel, the business-hours window and timezone, the late-funnel deal stage list, the text message templates (matched vs unmatched), and the lookback window (default 30 minutes).

- If any individual call fails (bad number, SMS rejected, HubSpot lookup error), log the failure into the Slack summary line for that call but keep processing the rest. Do not abort the whole run on a single error.

Additional information

What does this prompt do?
  • Checks CallRail every 30 minutes for calls that came in during business hours and went unanswered, hit voicemail, or were abandoned before connecting.
  • Looks up each caller's phone number in HubSpot to pull their name, lifecycle stage, and recent deal context when there's a match.
  • Sends a personalized apology and callback offer by text from the same tracking number the caller dialed, so it shows up as a normal reply from your business line.
  • Posts a one-line summary of every recovery to your sales channel in Slack with the caller, the text that went out, the HubSpot link, and a click-to-call link.
  • Skips callers who are already in an active deal past the discovery stage, so reps stay in control of late-funnel conversations.
What do I need to use this?
  • A CallRail account with at least one SMS-enabled tracking number and an API key.
  • A HubSpot login with access to contacts and deals.
  • A Slack workspace with a channel for sales notifications.
  • A short script for the apology text and a business-hours window you want the agent to run inside.
How can I customize it?
  • Change the schedule, business-hours window, or lookback period (the default is the last 30 minutes, every 30 minutes).
  • Edit the text message script, including how it greets known contacts versus unknown callers.
  • Adjust which deal stages are treated as late-funnel so different prospects are auto-texted versus left for a rep.
  • Swap the Slack channel, or send a direct message to the call owner instead of posting to a shared channel.

Frequently asked questions

Does the text actually come from my business number?
Yes. The agent sends the SMS through the same CallRail tracking number the caller originally dialed, so it appears as a reply from your business line and keeps the call attribution clean.
What happens when the caller isn't in HubSpot?
The agent falls back to a generic but friendly apology with a callback offer. The Slack summary will note that no HubSpot match was found so a rep can decide whether to create a new contact.
Will it text someone who's already deep in a deal with us?
No. If the caller is associated with an active deal past the discovery stage, the agent skips the auto-text and just posts a heads-up in Slack so the rep can follow up personally.
Can I run this outside of business hours?
Yes, but it's set up to respect a business-hours window by default so customers do not get a 2am apology text. You can widen, narrow, or remove that window when you customize the workflow.
Does this work with HubSpot Free?
Yes. Contact search and basic deal info are available on every HubSpot tier, so the agent works the same on Free as it does on Sales Hub Professional or Enterprise.
What if a caller is already getting a separate sequence in another tool?
You can extend the skip rule to look for tags, lifecycle stages, or list membership in HubSpot, so anyone in an active outreach sequence is left alone.

Stop losing missed calls to silence.

Connect CallRail, HubSpot, and Slack once, and Geni recovers every missed call with a personal text within 30 minutes.