Voice AI · Voice AI Receptionist
One service for the whole call
A Node.js service answers on SignalWire, keeps each call to five minutes, and clears private call data when the work is done.
- Voice
- Node.js
- SignalWire

The problem
A phone call falls apart when telephony, the conversation, and the voice each wait on the last one to finish. The caller hears the gaps. The same system also has to stop a call that runs too long, and it has to delete private call data instead of leaving it behind.
The build
The receptionist is a Node.js and Fastify modular monolith, hosted on Railway. SignalWire places and receives the call. Anthropic Claude Haiku handles the conversation. The knowledge base lives in PostgreSQL with pgvector, and search uses OpenAI embeddings so answers stay on the business. BullMQ on Redis queues call work, caps each call at five minutes, and runs the privacy cleanup. Callers hear a natural-sounding voice. An ElevenLabs voice is connected and currently falls back to SignalWire's built-in voice, so the product does not name a specific voice. The team dashboard is React and TypeScript on Vercel. GitHub Actions runs CI.
- Modular monolith in Node.js and Fastify, so the call path is one service on Railway
- BullMQ on Redis queues each call, caps it at five minutes, and runs privacy cleanup
- Claude Haiku for the conversation; PostgreSQL and pgvector for the knowledge base, searched with OpenAI embeddings
The outcome
One service answers the call, bounds it at five minutes, and schedules the cleanup of private call data. The team reviews what was captured in the dashboard. Hours follow how the phone line is set up. The write-up does not promise round-the-clock answering, and it does not promise a particular named voice while that ElevenLabs path falls back to SignalWire's built-in voice.
Next step
See the receptionist, or scope a build.
Book a demonstration of the AI receptionist, or tell us about a custom project. You get a real reply either way.