Voicemail is where urgency goes to wait. A caller leaves ninety seconds of audio that contains, somewhere in the middle, one fact you actually need: an appointment time, a callback number, or a deadline. The fix is not a better voicemail player. The fix is an agent that listens for you.
In this walkthrough, we build a TypeScript agent that runs on Telnyx Edge, reacts to voicemail events in real time, transcribes the recording, summarizes it with an LLM, texts the result, and archives the original audio. By the end, voicemail turns into a two-sentence SMS instead of a playback queue.
The complete runnable source is in the telnyx-code-examples repo.
What the App Does
When someone leaves a voicemail on your Telnyx number, the agent runs this pipeline:
- Call Control fires a webhook when the call status becomes
voicemail. - The Edge agent downloads the recording using the voicemail recording metadata.
- Speech-to-Text transcribes the audio.
- Telnyx AI Inference summarizes the transcript into a concise SMS-ready message.
- Messaging sends the summary to the mailbox owner.
- Cloud Storage archives the original audio.
The important shift is that voicemail becomes triage. The owner can see who called, what they need, and whether it is urgent without listening to the recording first.
How It Works
The core of the sample is a single VoicemailAgent. Its onTask() method receives the webhook task, ignores anything that is not a voicemail event, and then runs the processing steps.
const payload = task.input as WebhookPayload;
if (
!payload ||
payload.event !== "call.status" ||
payload.data?.payload?.call_status !== "voicemail"
) {
return { status: "ignored" };
}
const callControlId = payload.data.payload.call_control_id;
const recordingId = payload.data.payload.recording?.id;
const callerNumber = payload.data.payload.from;
That keeps the agent narrow. It is not trying to own every call event. It starts only when the call has produced voicemail audio.
Downloading and Transcribing Audio
The agent downloads the voicemail recording through the Telnyx binding:
const audioBuffer = await telnyx.calls.downloadRecording({
call_control_id: callControlId,
recording_id: recordingId,
});
Then it sends that audio to Speech-to-Text:
const transcription = await telnyx.ai.stt.transcribe({
audio: audioBuffer,
language: "en-US",
});
At this point the workflow has converted a phone-network event into text that an application can reason over.
Summarizing With AI Inference
The transcript is summarized with a Telnyx-hosted model through an OpenAI-compatible chat completion call:
const summaryResponse = await telnyx.ai.openai.chat.createCompletion({
model: "gpt-4o-mini",
messages: [
{
role: "system",
content:
"Summarize the following voicemail transcription into a concise SMS message.",
},
{
role: "user",
content: `Caller: ${callerNumber}\nTranscription: ${transcriptText}`,
},
],
max_tokens: 60,
});
The model has one job: turn a transcript into a useful summary. The rest of the workflow stays explicit and observable.
Sending the SMS Safely
The sample includes a LIVE_MODE flag. In demo mode, it logs the exact SMS payload it would send. In live mode, it sends the summary with the Messaging API:
await telnyx.messages.send({
from: this.env.config?.TELNYX_SMS_NUMBER,
to: destinationNumber,
text: `Voicemail from ${callerNumber}: ${summaryText}`,
});
That small switch matters. You can test the whole pipeline end to end before sending real messages.
Archiving the Original
After the SMS step, the recording is stored in Telnyx Cloud Storage:
await telnyx.storage.put({
bucket: this.env.config?.STORAGE_BUCKET || "voicemail-archives",
key: `voicemails/${recordingId}.mp3`,
body: audioBuffer,
contentType: "audio/mpeg",
});
The summary becomes the fast path, while the original recording remains available for audit or review.
Setup
Clone the repo and move into the example:
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/voicemail-to-sms-agent
Install dependencies and create your environment file:
npm install
cp .env.example .env
Configure the values for your Telnyx account:
TELNYX_API_KEY=<your_telnyx_api_key>
TELNYX_SMS_NUMBER=<your_telnyx_sms_number>
MAILBOX_OWNER_NUMBER=<summary_recipient_number>
STORAGE_BUCKET=voicemail-archives
LIVE_MODE=false
Then typecheck, test, and deploy:
npx tsc --noEmit
npm test
npm run deploy
After deployment, point your Call Control voicemail webhook at the deployed Edge URL. Start with LIVE_MODE=false, inspect the generated SMS payloads in the logs, then switch to live mode when you are ready.
Why This Pattern Matters
This example is small, but the architecture is useful: react to a communications event, pull the relevant media, run AI on it, notify a human through the right channel, and store the source artifact.
You could adapt the same pattern for missed sales calls, after-hours support lines, appointment reminders, or any workflow where voice messages need to become structured follow-up.
Voicemail does not have to stay a hidden queue of audio. With Call Control, Speech-to-Text, AI Inference, Messaging, and Cloud Storage in one workflow, the useful part can show up where people already look: their messages.