Getting an AI agent to answer a phone call is only the beginning.
The harder part is keeping the call going.
This example builds a voice agent on Telnyx Edge Compute that answers an inbound call, speaks a greeting, listens with streaming transcription, sends the caller's speech to Telnyx AI Inference, speaks the reply with TTS, and then goes back to listening.
Code: https://github.com/team-telnyx/telnyx-code-examples/tree/main/edge-voice-agent-holds-call
The core flow is:
call.initiated
-> answer
call.answered
-> speak greeting
call.speak.ended
-> start transcription
call.transcription final
-> stop transcription
-> run LLM turn
-> speak reply
call.speak.ended
-> listen again
call.hangup
-> persist final call state
Each live call gets a VoiceAgent
actor keyed by call_control_id
.
That actor stores:
POST /webhooks/voice
receives Call Control webhooksGET /debug/call?call_control_id=<call_id>
inspects actor statePOST /debug/respond
tests an LLM turn without a live callGET /health/liveness
and GET /health/readiness
support health checksThe VoiceAgent
extends the Agent SDK Agent
class from @telnyx/edge-runtime
.
It uses:
this.messages.add()
to store caller and assistant turnsthis.messages.toOpenAI()
to format history for the modelthis.setState()
and this.getState()
for durable call statethis.env.TELNYX.ai.openai.chat.createCompletion()
for zero-credential inference through the [telnyx]
bindingThe model call looks like this:
const completion = await this.env.TELNYX.ai.openai.chat.createCompletion({
model,
messages: [{ role: "system", content: SYSTEM_PROMPT }, ...history],
max_tokens: 200,
temperature: 0.5,
});
The webhook handler speaks the returned text through Call Control TTS.
The sample uses Call Control streaming transcription because the app owns the conversation loop.
The caller speaks. Telnyx sends a final transcript. The app stops transcription, runs the LLM turn, speaks the reply, and starts transcription again after TTS ends.
That gives you room to add your own logic:
npm install
telnyx-edge ship
Set the Call Control API key as an Edge secret:
telnyx-edge secret set TELNYX_API_KEY your_telnyx_api_key
Point your Call Control application webhook to:
https://edge-voice-agent-holds-call-<id>.telnyxcompute.com/webhooks/voice
Then call the Telnyx number assigned to that Call Control application.
Before shipping this pattern for real callers, I would add:
But even as a starter, this is a useful reference for building a voice agent that can actually stay on the call.
Resources: