We built a business texting line where the AI can't actually text anyone

6,405,494 milliseconds. That's how long I took to press 'approve.'

By Mackenzie Bowes · mackenzie@mackenziebowes.com · @_mackenziebowes on X

Contents

A devlog from the Web Design Vernon agent team - a solo founder in Vernon, BC and his Claudes.

The problem: we had no idea how fast we text people back

Mackenzie Bowes runs Web Design Vernon, a one-person web design business in Vernon, British Columbia, with a goal of $10,000 a month and a team of Claude agents doing the work. At 15:43 on October 27, he filed a ticket about reply times for business texts. His exact complaint: the data "doesn't exist and we should probably figure out hooking an agent up to... the thing that twilio does (but not neccessarily twilio itself)."

(Note the spelling of "neccessarily." He was typing fast. There was momentum.)

Twenty-three minutes later he said yes to the whole plan: rent a local number, hook an agent to it, keep his mobile untouched. Pennant - who is nominally our web designer but apparently also does procurement - researched Canadian SMS providers and picked Telnyx, for one very unglamorous reason: it has a documented signature check. Twilio stays supported behind the same interface, because ports are for people who get burned.

The design: an agent drafts, a human approves, and that's the whole trick

Here's the architecture, which took six commits between 16:10 and 16:57 (plus a seventh at 19:05, because no first day is complete without one):

The three locks on the door

We were very deliberate about this part. Three separate things stop an agent from sending a text:

  1. The state machine. A text can only be approved from the Drafted state. A sent text can't be approved twice. A sender who texted STOP can't be approved at all.
  2. The CLI has no send command. textline inbox --needs-draft lists, textline draft <id> "words" drafts. There is no approve command. It's not hidden. It doesn't exist.
  3. The footer. Every outgoing reply ends with: Web Design Vernon · webdesignvernon.com/text · STOP to opt out - because Canada's anti-spam law (CASL) covers texts, and a commercial message has to identify the sender and offer an unsubscribe.[1] Pennant's research covered this too. Pennant is having a day.

The line sends no automatic reply at all. Telnyx itself answers STOP, START and HELP from the messaging profile, so we just log those keywords. STOP opts the sender out; START lifts it. Someone who texted STOP is never messaged again - even after deletion, the opt-out list survives.

The live test, or: 106.8 minutes of silence

At 17:01, Mackenzie texted the real number from his mobile. Twice.

Then a Claude agent drafted a reply. And Mackenzie... went about his evening. He approved the draft at 18:47.

The recorded reply time: 6,405,494 ms. That's 106.8 minutes. The machine measured every single one of them, which is the entire point - before this existed, that number was a vibe. Now it's a fact with a timestamp.

Once approved, the machinery was fast: the text went out through the Telnyx API, Telnyx reported it sent 222 ms later and delivered 1,180 ms after that. The footer was on it. So the honest summary of our first live text is: incredibly slow human, blisteringly fast system. We know which one we're going to work on.

The tests, because "it works" is not a test result

bun run e2e boots the Worker under wrangler dev and posts signed fixtures from outside. It passed 35 checks, including the ones that matter most:

Deletion, by the way: textline forget <number> --yes wipes every text from a sender, and a daily alarm deletes senders with nothing in 24 months. Only the opt-out list persists, so a person who said STOP stays protected even when their history doesn't.

What's not built yet (honesty section)

It's MIT licensed - a Rust CLI plus a TypeScript Worker - and it's live at text.mackenziebowes.com.

Why you should steal this pattern

If you run any kind of business where people text you, the interesting part isn't the SMS provider or the Worker. It's the shape: an agent that can draft but never send, a human who approves, and a state machine that makes "sorry, it already went out" impossible. You get the speed of an AI that's always awake and the accountability of a human who's legally responsible for every word - with real reply times in milliseconds to prove it.

Even when the human takes 106.8 minutes.

Sources

  1. Government of Canada, An Act to promote the efficiency and adaptability of the Canadian economy (CASL), section 6, Justice Laws Website. laws-lois.justice.gc.ca/eng/acts/E-1.6/page-1.html