dialessa Have it call me

Build in public

Groundwork for self-serve cold calling: uploads, minute limits and a careful Start button

Today was about letting customers run cold calling themselves. Until now I set up each campaign by hand. Today I built the groundwork so a business can bring its own list, set its own limits and press go, without me in the middle.

It was a big day: 1 working session with coding agents, 5 prompts typed, 95 commits, 16 deploys, about 7 hours of active work and 8743 lines of code changed. The voice agent, the API, the web app, a background worker and the website all went to production.

What I built

  • List upload. Customers can upload their own cleaned call list. A background worker imports it, so the web app doesn't hang on a large file.
  • Monthly minutes allowance with a hard stop. The owner sets the limit and calls stop when it's reached. Minutes used show in the app, so nobody has to guess.
  • A Start dialling step. A campaign only begins once every safety check passes. If something isn't ready, it doesn't dial.
  • Calendar-aware calling. If a customer's calendar is unavailable, the voice agent holds calls. Once the calendar is back, it places them. There's no point booking meetings into a calendar the agent can't see.
  • Per-business scripts. Each self-serve call now builds its own campaign script from the customer's details, so the voice agent speaks for that business and not as a generic caller.

I also removed the line in the voice agent's opening clips that said the call is recorded.

What was hard

The fiddliest part was calling hours. Some regions span several time zones, and my earlier logic treated a region as if it had only 1 clock. That works until it doesn't: a lead's consent could have allowed a call at a time that was already outside legal hours where they actually live. I fixed the logic so consent can never allow a call outside legal hours, whichever time zone applies.

None of this is glamorous work. Self-serve means I'm no longer the person catching mistakes before a campaign starts, so the software has to do that job. A lot of today went into deciding when the system should refuse to act: stop at the minutes limit, hold when the calendar is down, don't start until the checks pass.

Shipping 16 deploys across every part of the product in a single day also added pressure. I leaned on many automated review passes along the way. They caught things I would have missed at that pace, and they made it easier to keep releasing without losing track of what had changed.

What I learned

  • With self-serve, the safe default matters most. When a customer is driving, the system should fail closed. Holding a call is cheap. A call at the wrong time, or past a limit the owner set, is not.
  • Time zones belong to the person, not the region. Any rule built on a region-level clock will break at the edges.
  • Limits only help if they're visible. A hard stop nobody can see feels like a bug. Showing minutes used in the app turns it into a control the owner can trust.
  • Small prompts can go a long way when the plan is clear. I typed 5 prompts today. Most of the effort went into knowing exactly what each one should produce, then reviewing what came back.

It was a long day, but the pieces a business needs to run its own campaigns are now in place.

Written from that day's build log: the work sessions, commits and deploys recorded for it.

← All posts