Route new HubSpot leads to the nearest rep with a drive-time map
When a new contact lands in HubSpot, pick the rep with the shortest live drive to the lead, update the record, and post a Slack alert with the ETA and a map.
Build me an agent workflow that runs every time a new contact is created in HubSpot (contact.creation). The goal is to auto-assign the closest sales rep to the lead based on real drive time, write the decision back to HubSpot, and announce it in Slack with a map.
For each new HubSpot contact, the agent should:
1. Read the contact's mailing address fields (address, city, state, postal code, country). If any of those are missing so the address cannot be formed cleanly, skip this contact and do not post anything to Slack. Log the skip with a short reason.
2. Call Mapbox Forward Geocode (v6) to turn the address into a longitude/latitude. Use the structured-input form when all address parts are present, otherwise fall back to a free-form query. If the top result has low relevance or geocoding fails outright, skip the contact and log why.
3. Compare the lead against a configurable roster of sales reps. The roster lives at the top of the workflow as a list of { name, slackUserId, homeLng, homeLat } so I can edit it without changing the logic. Call Mapbox Get Distance Matrix with profile=mapbox/driving-traffic, the lead as the single origin (sources=0), and every rep as a destination. Pick the rep with the shortest duration. Convert that duration to whole minutes. Keep the roster size at or under 24 destinations per call (Mapbox driving-traffic matrix cap is 10 coordinates per request on the free tier and 25 on enterprise; the workflow should chunk if needed).
4. Update the HubSpot contact via Update Contact. Write the latitude and longitude, the assigned rep's name, and the drive-time minutes into custom contact properties. The exact property names should be configurable at the top of the workflow (defaults: lead_latitude, lead_longitude, assigned_rep, drive_time_minutes). By default, only set assigned_rep if it is currently empty so manual overrides stick.
5. Render a Mapbox Get Static Map Image centered on the lead's coordinates with a single pin marker at the lead, zoom around 11, and a clean style (default to mapbox/streets-v12). Size 600x400 PNG is fine. Save the image bytes.
6. Post a Slack message to the configured sales channel using Slack Bot Send a Message. The message should include: the lead's name and company, a link to the HubSpot contact record, an @-mention of the assigned rep via their Slack user ID, the drive time in minutes, and the static map image (upload via Slack Bot Upload a File and reference it in the message, or post the message first and reply in-thread with the image, whichever the platform supports cleanly).
Configurable inputs that should be exposed at the top of the workflow: the HubSpot custom property names (lead_latitude, lead_longitude, assigned_rep, drive_time_minutes), the Slack sales channel ID, the rep roster array, the Mapbox style and zoom for the static image, the geocoding relevance threshold (default 0.8), and a boolean for whether to overwrite an existing assigned_rep value.
Error handling: if any step fails after a successful geocode (matrix, HubSpot update, map render, Slack post), log the error with the contact ID and continue. Do not retry endlessly. Never post a malformed Slack alert; if the image fails, post the text alert without it.
Additional information
What does this prompt do?
- Listens for new contacts in HubSpot and turns each address into a precise location on the map.
- Compares live drive time from the lead to every rep on your roster (real traffic, not straight-line distance) and picks the closest one.
- Writes the assigned rep, the drive time in minutes, and the lead's coordinates back to the HubSpot contact so the routing decision lives in your CRM.
- Posts a clean Slack alert to your sales channel with the lead summary, the assigned rep, the ETA, and a static map image showing the pin.
What do I need to use this?
- A HubSpot account where new contacts arrive with mailing addresses, plus permission to update contact properties.
- A Mapbox account (free tier is fine) for address lookup, drive-time routing, and map images.
- A Slack workspace and the channel ID where you want lead alerts to land.
- Your sales rep roster: names, Slack handles, and the home base or office address each rep is dispatched from.
How can I customize it?
- Swap which Slack channel the alerts go to, or send a direct message to the assigned rep instead of (or in addition to) a channel post.
- Edit the rep roster (names, Slack handles, home bases, on/off-duty flags) without touching the rest of the workflow.
- Add a pre-filter so only leads that meet a minimum score, a target country, or a specific lifecycle stage get routed and announced.
Frequently asked questions
What happens if a new contact does not have a complete address?
Does the drive time take real traffic into account?
How many sales reps can I include in the roster?
Will this overwrite a rep who has already been assigned manually?
Can I use this with HubSpot Starter or Professional?
Stop guessing which rep is closest to every new lead.
Connect HubSpot, Mapbox, and Slack once, and every new contact lands with the right rep already attached and the team already alerted.