Back to Case Studies

Two-Way SMS Inside a Voice AI Recruiting Platform (Client Under NDA)

Contract work for a US voice AI startup whose agents call and text truck-driver applicants. I added texting to the conversation view: queued sends, delivery status and history, no duplicate texts, clear carrier errors, and fixes for voice session race conditions. Next.js, TypeScript, Supabase, BullMQ.

next.jstypescriptsupabasebullmqsmsvoice ainda
Diagram of the SMS flow I built: conversation view, job queue, SMS provider, status and history
A diagram of my part of the work. The client's name, screens and code are under NDA.

The client

A US startup runs AI voice agents that call and text truck-driver applicants for recruiting teams. I joined their engineering team on contract in February 2026, after a paid test exercise, to add texting to the platform's conversation view. Their name, code and screens are covered by an NDA, so this page describes the work only.

What I built

  • Send SMS from a conversation. Recruiters text an applicant from the conversation they already have open. The phone number is checked first, and there is a field to add one by hand when none is on file.
  • A queue for outbound texts. Messages go through a background job queue instead of the web request, so a slow provider or a retry never blocks the screen.
  • Delivery status and history. Each text shows queued, sent or failed, and the side panel shows the applicant's full SMS history, kept in sync with the provider.
  • No duplicates. Fixed the paths that could send the same text twice.
  • Clear carrier errors. A text from an unregistered US sender number (A2P 10DLC) now returns a message that says what to fix, not a generic failure.
  • Voice session fixes. Fixed race conditions where the AI voice session was cleaned up or recreated while a text was in flight.
  • An applicant sync worker. A scheduled worker that pulls applicant data from the client's applicant-tracking system.

Code quality along the way

Moved data loading from effects to React Query, removed a duplicated database client, fixed a webhook handler that saved contacts under the wrong ID, and cleaned up error logging. Everything went through pull requests into the team's development branch.

Stack

Next.js and TypeScript, Supabase (Postgres), a Redis job queue (BullMQ), a voice AI provider and an SMS provider behind the platform's provider-agnostic layer, Sentry.

What it does not claim

I was one engineer on a larger team, on a short contract. The platform, its voice agents and its other integrations were built by the client's team.

Adding messaging to a product that already works?

Queued sends, delivery status, clear errors and no duplicates, built into the code you already have.