Overview
The problem
How it works
- Call in or out: Twilio streams call audio over a WebSocket (Media Streams). Outbound calls are placed by the same service for verification and delay notices.
- Listen: voice-activity detection and Deepgram streaming speech-to-text turn audio into transcripts, with interruption handling so callers can talk over the agent.
- Identify the caller: the phone number is matched against a phonebook to decide the path: customer, teammate, or potential client.
- Route with LangGraph: a StateGraph with conditional edges sends the call to the right node: greeting, customer intent (classified with GPT-4o-mini), teammate intent, outbound customer verification, or potential client.
- Act with tools: LangGraph tool calls fetch, shift, or cancel appointments in Google Calendar, and only after the caller confirms.
- Speak: Azure text-to-speech replies. Pre-generated filler phrases play while slow operations run.
- Close the loop: the call ends gracefully, an SMS or WhatsApp confirmation goes out, and the outcome is written to MongoDB.
What I built
- Outbound customer verification: the agent calls the customer, confirms identity and appointment details, and records the result. This touched the call graph, the outbound WebSocket service, the media-stream model, and a new CustomerVerificationWorkflow (about 730 lines added in the main change).
- Teammate delay workflow: a teammate calls in to say they are late. The agent finds the affected appointments, updates the calendar, and notifies the customer.
- Graceful termination and confirmations: the agent detects when a conversation is finished, ends the call cleanly, then sends an SMS confirmation.
- Call-outcome tracking: every call's result is stored in MongoDB for follow-up and reporting.
- Latency-masking fillers: we measured the slow steps. A Google Calendar update took about 2.19 s and a calendar fetch about 617 ms. I added natural filler audio ("Let me update your calendar with the new time") so the caller never hears dead air.
Engineering decisions
- LangGraph over a single prompt: phone calls are multi-turn and stateful. Explicit nodes and conditional edges made each path testable and stopped the model from wandering between intents.
- Classify first, then act: a cheap intent classification (GPT-4o-mini) picks the workflow before any tool runs, which keeps latency and cost down.
- Confirmation before side effects: calendar changes only happen after the caller confirms, because an AI should not silently move someone's appointment.
- Fillers instead of faster APIs: we couldn't make Google Calendar faster, but we could stop the caller from noticing the wait.
Tech stack
Related work
LangGraph
Twilio
Deepgram
OpenAI
Node.js
MongoDB