Build a Voice Agent That Holds a Live Call on Telnyx Edge Compute

작성자

카테고리:

← 피드로
DEV Community · Sonam · 2026-08-12 개발(SW)

Sonam

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 call loop

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

Enter fullscreen mode Exit fullscreen mode

Each live call gets a VoiceAgent actor keyed by call_control_id.

That actor stores:

  • call phase
  • caller and callee
  • turn count
  • last transcript
  • last reply
  • durable message history

The main routes

  • POST /webhooks/voice receives Call Control webhooks
  • GET /debug/call?call_control_id=<call_id> inspects actor state
  • POST /debug/respond tests an LLM turn without a live call
  • GET /health/liveness and GET /health/readiness support health checks

The Agent SDK piece

The VoiceAgent extends the Agent SDK Agent class from @telnyx/edge-runtime.

It uses:

  • this.messages.add() to store caller and assistant turns
  • this.messages.toOpenAI() to format history for the model
  • this.setState() and this.getState() for durable call state
  • this.env.TELNYX.ai.openai.chat.createCompletion() for zero-credential inference through the [telnyx] binding

The 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,
});

Enter fullscreen mode Exit fullscreen mode

The webhook handler speaks the returned text through Call Control TTS.

Why streaming transcription?

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:

  • human handoff
  • CRM lookup
  • order status tools
  • turn limits
  • cost tracking
  • transcript summaries
  • safety rules

Deploy

npm install
telnyx-edge ship

Enter fullscreen mode Exit fullscreen mode

Set the Call Control API key as an Edge secret:

telnyx-edge secret set TELNYX_API_KEY your_telnyx_api_key

Enter fullscreen mode Exit fullscreen mode

Point your Call Control application webhook to:

https://edge-voice-agent-holds-call-<id>.telnyxcompute.com/webhooks/voice

Enter fullscreen mode Exit fullscreen mode

Then call the Telnyx number assigned to that Call Control application.

Production notes

Before shipping this pattern for real callers, I would add:

  • webhook signature verification
  • idempotency for Call Control actions
  • max turn count and call-duration limits
  • human transfer
  • transcript redaction
  • latency monitoring across STT, LLM, and TTS
  • stronger barge-in handling
  • observability around call phases

But even as a starter, this is a useful reference for building a voice agent that can actually stay on the call.

Resources:

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다