Voice AIDispatchNew
AI Agent Now Phones the Caterer for You
Dispatch finds local vendors for your event, calls and emails them, and brings back real quotes.
Rochester, N.Y. Planning an event means a lot of phone calls. Venues, caterers, florists, DJs, photographers. Every one of them wants to talk, plenty of them don't pick up, and every quote comes back in a different format. Dispatch does that part for you. You pick the event type and the services you need, describe the event, and it goes and gets the quotes.
Under the hood it finds local businesses with the Google Places API, then contacts each one the way that category actually works. Some vendors live on the phone, so a Retell AI voice agent calls them. Others run on email, so Resend sends a proper message from its own reply address. Call transcripts and email replies go through an LLM on OpenRouter, which turns them into structured quotes on your dashboard.
The phone is where this product wins or loses.
The phone agent was the hardest part to get right. Real business phone lines are messy. The agent listens first and works out who picked up: a person, voicemail, a call screener, an IVR menu, a dead line or a fax tone. It presses IVR digits with DTMF, and if it hears voicemail cues halfway through a sentence it pivots to leaving a message. Every finished call lands in exactly one of six outcome buckets, so nothing ends up stuck in a vague maybe.
Around the calls sits a multi-attempt outreach state machine backed by Supabase. It has three lanes (async, voicemail and no answer), a hard cap of 3 calls and 2 emails per vendor, and waits of 2, 4, 24 or 48 hours depending on the lane. Each retry lands in a different part of the day. All of the lane logic is one pure nextTransition() function, which made it easy to test and reason about.
Timing matters too. Calls only go out inside each vendor's real Google opening hours, with a buffer after opening and before closing, and the scheduler is timezone-aware. A pg_cron job inside Postgres wakes the worker, so there's no separate server to babysit.
Email has its own trick. Each outreach gets a unique reply address with a token in it, so when a vendor answers, the Resend webhook knows exactly which run the reply belongs to. The LLM parses the reply into a quote and moves the run to done or dead.
It's a real product, so it has real billing. Every account gets 5 free calls. After that there's a one-time $14.99 unlock per event or a $19.99 monthly plan through Stripe. Calls and emails are pre-charged through race-safe database functions and refunded if they fail. Sign-in is Google or a magic link, and row-level security keeps every event visible only to its owner. The dashboard has live status, a compare-quotes view and guest invites with RSVP links.
I also did a security pass: signature checks on the Retell and Resend webhooks, an SSRF guard on website scraping, database-backed rate limiting, escaped HTML in emails and proper security headers. Dispatch started as a two-day proof of concept in June on Vapi and Trigger.dev. The rebuild is about 12.8k lines of TypeScript.
Right now I'm running experiments on the voice agent itself: latency, turn-taking and how it opens a call. The phone is where this product wins or loses.
How it works
Dispatch, start to finish, in 6 steps.
- Step 1:
Intake
Pick the event, the services and describe it
- Step 2:
Discover
Google Places finds local vendors
- Step 3:
Reach out
Retell voice calls or Resend emails, by category
- Step 4:
Retry
State machine schedules follow-ups inside opening hours
- Step 5:
Parse
LLM turns transcripts and replies into quotes
- Step 6:
Compare
Dashboard shows live status and quotes side by side
Graphic: The Sahil Bachu
