Subscribe to GEN
Login to GEN
Add a Comment
Asterisk, now in its 21st version, has been a cornerstone of open-source telephony since its inception in 1999. Developed by Digium (now part of Sangoma Technologies), Asterisk has evolved into a powerful and flexible communications engine. It serves as the foundation for IP PBX systems, VoIP gateways, conference servers, and other custom communications applications. With its ability to connect various communication technologies, from PSTN to VoIP, Asterisk has become the go-to solution for businesses seeking powerful & customisable telephony solutions. Its robust feature set, including IVR, voicemail, call recording, and advanced call routing, coupled with its active community and extensive documentation, makes Asterisk a formidable player in the telecommunications landscape.
Unlike many soft switches, Asterisk requires some programming expertise to bend it to your will, unless you want to use a configuration framework like FreePBX, PBxact, AsteriskNOW etc which provide a nice GUI to configure the commonly required features. These configuration frameworks simply generate the asterisk configuration for you, saving you a great deal of typing. This configuration is called the 'Dialplan'.
The Dialplan determines call flow and is broken into contexts, which you can liken to extensions in some other proprietary soft switches but are far more flexible. When a call arrives on the switch, it arrives at a context, and the dialplan for that context is then executed.
Asterisk's dialplan uses a simple, easy-to-read, and powerful configuration syntax that allows you to define call flows and perform various operations, such as routing calls, playing voicemail, or triggering events based on certain conditions. For more complex logic, the dialplan can incorporate external scripts written in languages like Lua, Python, or use the Asterisk Gateway Interface (AGI).
Asterisk is designed to be extensible. This means that you can easily add new features and functionality to the platform without modifying the core source code.
Let's look at a worked example to see just how powerful this can be, and how simple it is to do complex things. Here, we're asking the caller to state the nature of the medical emergency, then we're listening to that, asking an AI LLM for the treatment and then reading that out to the caller.
[Emergency]
exten => s,1,Answer()
same => n,Set(TTS_TEXT=Please state the nature of the medical emergency)
same => n,AGI(gTTS.agi)
same => n,Wait(1)
same => n,Set(VTT_FILE=/tmp/emh-${UNIQUEID}.wav) same => n,Record(${VTT_FILE},60,5,q)
same => n,AGI(voice-to-text.agi)
same => n,GotoIf($["${AGISTATUS}" = "SUCCESS"]?continue:error)
same => n(continue),NoOp
same => n,Set(TTS_TEXT=Please wait whilst we ask the EMH)
same => n,AGI(gTTS.agi)
same => n,Set(LLM_PROMPT=Please suggest the most appropriate treatment for :${SPEECH})
same => n,Set(LLM_MODEL=llama3)
same => n,AGI(llm.agi,1)
same => n,GotoIf($["${AGISTATUS}" != "SUCCESS"]?error)
same => n,Set(LLM_RESPONSE=${SHELL(cat ${LLM_RESPONSE_FILE})})
same => n,System(rm -f ${LLM_RESPONSE_FILE})
same => n,Set(TTS_TEXT=${LLM_RESPONSE})
same => n,AGI(gTTS.agi)
same => n,Hangup()
same => n(error),Flite(Sorry an error occurred. Please try again.)
same => n,Hangup()
Let's break this dialplan down into its component parts and explain how it works. In asterisk, each line starts with same => n, and then has a statement. This isn't always the case, but for this example it is.
In Asterisk, variables are commonly used and are named, to set a variable we use set(VARIABLE_NAME=Variable Value), and we can then use that variable later by referring to it as ${VARIABLE_NAME}.
Here we answer the call, and we use a GEN Function gTTS.agi to take "TTS_TEXT" and convert that into audio and then play it to the caller. In this case we say "Please state the nature of the medical emergency" in a professional female voice.
exten => s,1,Answer()
same => n,Set(TTS_TEXT=Please state the nature of the medical emergency)
same => n,AGI(gTTS.agi)
same => n,Wait(1)
Here we record what the caller says, up to 60 seconds, waiting for at least 5 seconds of silence to end. We store this recording in an audio file in "VTT_FILE", which is "/tmp/emh-${UNIQUEID}.wav" where "UNIQUEID" is a uniquely generated string.
same => n,Record(/tmp/emh-${UNIQUEID}.wav,60,5,q)
We now use a GEN function to convert this audio recording into 'text', this is voice recognition. voice-to-text looks for the variable "VTT_FILE" to find the recording, and it deletes the recording after it is converted and stored in the variable "SPEECH".
same => n,AGI(voice-to-text.agi)
same => n,GotoIf($["${AGISTATUS}" = "SUCCESS"]?continue:error)
First we tell the caller we're going to ask the EMH using our gTTS function.
Next we need to ask the AI and to do that we need to build a 'prompt' which is the question we're going to ask. In this example, that is "Please suggest the most appropriate treatment for :${SPEECH}" and remember that "SPEECH" is the text version of the recording of the callers medical emergency.
Again, we have a GotoIf to check that the function is successful, otherwise we go to 'error' to tell the caller it all went wrong. The AI LLM because of the way it works stores its answer in a file which it returns in "LLM_RESPONSE_FILE". It does this because the response can be plain text, or JSON or even XML depending on what we ask for, and the asterisk dialplan doesn't like passing these kinds of data directly in variables as they can be sizeable.
same => n,Set(LLM_PROMPT=Please suggest the most appropriate treatment for :${SPEECH})
same => n,Set(LLM_MODEL=llama3)
same => n,AGI(llm.agi,1)
same => n,GotoIf($["${AGISTATUS}" != "SUCCESS"]?error)
same => n,NoOp(LLM Response File: ${LLM_RESPONSE_FILE})
Here we simply need to get the AI LLMs response, then play to the caller. We take the file "LLM_RESPONSE_FILE" and put that in a variable "LLM_RESPONSE" because we need a variable to pass to gTTS. This now reads the diagnosis and treatment to the caller.
same => n,Set(LLM_RESPONSE=${SHELL(cat ${LLM_RESPONSE_FILE})})
same => n,System(rm -f ${LLM_RESPONSE_FILE})
same => n,Set(TTS_TEXT=${LLM_RESPONSE})
same => n,AGI(gTTS.agi)
In Asterisk, we have to do something with the caller or they'll just be left flapping about in the breeze, so we hangup the call. We could of course pass them back to the start, or give them an option to hear the diagnosis again or an option to be transferred to a physician, all of which is simple to do but I don't want to add too much into the dialplan, it is, after all an example.
same => n,Hangup()
With Asterisk you can literally do anything you can imagine. We have a set of code that asks the caller the nature of their call, then asks an AI LLM given a list of departments and extension numbers, which would be the most appropriate for the callers call, then receiving an extension back and transferring the caller.
We have code that asks the caller for a pin code if they have one, and that pin code either directly connects them or bypasses or jumps a queue, so that priority customers don't have to wait with everyone else, this is surprisingly common but we don't use it internally.
We have code that asks the caller to read out their tracking number, which is then validated by reading it back, and ultimately passed via API to a backend after which the tracking information is read back to the caller.
We have code that asks the caller for the date they would like to book an appointment, and then using an API reads out any available slots allowing the caller to select one, leave their name, and book that appointment. The code is actually quite complex and allows finding the first available appointment and announcing this.
As you can see, the list is limited only by your imagination. Anything you need can be done, and the power of AI now allows fuzzy to determine absolute, providing an improved human-machine interface.
If you'd rather have the UK's Asterisk Experts code your chosen solution, then you know where to find us, nothing too small or large, we've got you covered.
--- This content is not legal or financial advice & Solely the opinions of the author ---
Index v1.032 Standard v1.114 Module v1.062 Copyright © 2025 GEN Partnership. All Rights Reserved, Content Policy, E&OE. ^sales^ 0115 933 9000 Privacy Notice 51 Current Users, 135 Hits