VoiceTel

Support / VoiceML examples / Build a call queue with VoiceML

Build a call queue with VoiceML.

The afterlife has a waiting room, and its phone line works the same way. Callers take a number and hold, hearing announcements while they wait; caseworkers call the same number to take whoever has waited longest. It runs on three documents published on voiceml.org, with no application server.

Free trial <Enqueue> reference

What callers get

  • A place in line

    <Enqueue> puts each caller in a named queue, first come, first served.

  • Announcements on hold

    A hold document plays a message, pauses, and repeats until a caseworker is free.

  • Agents take the next caller

    A caseworker who calls in is connected to whoever has waited longest, with <Dial><Queue>.

  • A word before connecting

    The caller hears “your number has been called” just before the two are connected.

How the pieces fit

Components of the waiting room line
Piece Where it lives What it does
Main documentvoiceml.org, /r/ URLThe number’s voice URL. Puts callers in the queue and connects caseworkers to them.
Hold documentvoiceml.org, /s/ URLThe waitUrl of the <Enqueue>. Plays while a caller waits, over and over.
Connect documentvoiceml.org, /s/ URLThe url of the <Queue>. Plays to the caller just before they are connected.
Caseworkers’ phonesAny phone numbersCall the same number to take the next caller.

Before you start

  1. A VoiceML account with a phone number. See VoiceML or start a free trial.
  2. The numbers your agents call from, in E.164 format.

The caseworker numbers in this document are fictional. They use the 555-0100 to 555-0199 range, which is set aside for fiction. Replace them with your agents’ numbers before you publish.

Step 1: Publish the hold and connect documents

Publish both at voiceml.org. Neither contains Liquid, so each is served from an /s/ URL. Keep the URLs exactly as returned, key included, and don’t post them publicly.

wait.xml

<Response>
  <Say>Please continue to hold. A caseworker will see you shortly.</Say>
  <Pause length="2"/>
  <Say>While you wait, this is a good time to read the Handbook for the Recently Deceased.</Say>
  <Pause length="20"/>
</Response>

connect.xml

<Response>
  <Say>Your number has been called. Your caseworker will see you now.</Say>
</Response>

Step 2: Publish the main document and point the number at it

Replace WAIT_URL and CONNECT_URL with the URLs from step 1, and the caseworker numbers with your agents’. Publish it, and set the /r/ URL it returns as the phone number’s voice URL.

main.xml

<Response>
  {% assign caseworkers = "+18605550101,+18605550102" | split: "," %}

  {% if caseworkers contains From %}
    <!-- Caseworkers take the caller who has waited longest -->
    <Say>Caseworker line. Connecting you to the next soul in the waiting room.</Say>
    <Dial timeout="10">
      <Queue url="CONNECT_URL">recently-deceased</Queue>
    </Dial>
    <Say>Call again to see the next soul. Goodbye.</Say>
    <Hangup/>

  {% else %}
    <!-- Everyone else takes a number and waits -->
    <Say>Welcome to the afterlife waiting room. Please take a number. A caseworker will see you in turn.</Say>
    <Enqueue waitUrl="WAIT_URL">recently-deceased</Enqueue>
    <Say>Thank you for waiting. Goodbye.</Say>
    <Hangup/>
  {% endif %}
</Response>

Step 3: Test it

  1. Call from a phone that isn’t on the caseworker list. You are asked to take a number and hear the hold announcements.
  2. From a caseworker phone, call the same number. The waiting caller hears “Your number has been called,” and the two of you are connected.
  3. Call from a caseworker phone again with nobody waiting. After ten seconds, you hear the goodbye.

How the queue works

Both sides use the same queue name, recently-deceased. Queues are private to your account, so another account using the same name gets a separate queue.

The two halves of the queue
Side Markup What happens
Caller<Enqueue waitUrl="…">The caller joins the back of the queue. The hold document is fetched and played, then fetched and played again, until a caseworker takes the call or the caller hangs up.
Caseworker<Dial timeout="10"><Queue url="…">The caller who has waited longest leaves the queue, hears the connect document, and is connected to the caseworker. With nobody waiting, the dial gives up after ten seconds.

Caseworkers are recognized by From, using the same Liquid list check as the call screening example. Neither side has an action, so when a call ends, each document carries on to its goodbye.

To play music instead of announcements, leave waitUrl out: callers then hear the platform’s default hold playlist.

Where the movie turns up

References to Beetlejuice in the call flow
Where Reference
The greetingThe afterlife’s waiting room, where the dead take a numbered ticket and wait for a caseworker.
The agentsCaseworkers, like Juno, the Maitlands’ caseworker.
The hold messageThe Handbook for the Recently Deceased.

Limits of this design

  • No position announcements. The hold document is fetched with the caller’s place in line and the queue’s wait times, but a voiceml.org document can’t read those values. Announcing “you are caller number 3” needs a hold document served from your own server.
  • Callers leave by hanging up. This hold document doesn’t offer a way to leave the line or leave a message instead.
  • Agents pull calls; calls aren’t pushed to them. A caller waits until a caseworker phones in. To ring agents as soon as someone joins, use the on-call escalation example instead.
  • Waiting callers don’t survive a platform restart. Queues are kept in memory, so a restart drops the callers waiting in them.

Credits

  • The waiting room, its caseworkers, and the handbook come from Beetlejuice (1988), directed by Tim Burton and distributed by Warner Bros. Michael Keaton plays Betelgeuse; Alec Baldwin and Geena Davis play Adam and Barbara Maitland; Winona Ryder plays Lydia Deetz; and Sylvia Sidney plays Juno, the Maitlands’ caseworker.
  • The line, its queue, and its phone numbers are fictional in this example. VoiceTel is not affiliated with the film or its rights holders.
  • References: the <Enqueue> reference, the <Queue> reference, and the voiceml.org publishing and integration guide.

Trusted by