The preceding section discussed the variations of AGI that
can be used. This section goes into more detail about how your custom AGI
application communicates with Asterisk once AGI()
has been invoked.
Once AGI()
or EAGI()
has been invoked from the Asterisk
dialplan, some information is passed to the AGI application to set up
the AGI session. This section discusses what steps are taken at the
beginning of an AGI session for the different variants of AGI.
For a process-based AGI application or a connection to a FastAGI server, the variables listed in Table 21.1, “AGI environment variables” will be the first pieces of information sent from Asterisk to your application. Each variable will be on its own line, in the form:
agi_variable
:value
Table 21.1. AGI environment variables
Variable | Value / Example | Description |
---|---|---|
agi_request | hello-world.sh | The first argument that was passed to the AGI() or EAGI() application. For
process-based AGI, this is the name of the AGI application
that has been executed. For FastAGI, this would be the URL
that was used to reach the FastAGI server. |
agi_channel | SIP/0004F2060EB4-00000009 | The name of the channel that has executed the AGI() or EAGI() application. |
agi_language | en | The language set on agi_channel . |
agi_type | SIP | The channel type for agi_channel . |
agi_uniqueid | 1284382003.9 | The uniqueid of
agi_channel . |
agi_version | 1.8.0-beta4 | The Asterisk version in use. |
agi_callerid | 12565551212 | The full caller ID string that is set on agi_channel . |
agi_calleridname | Russell
Bryant | The caller ID name that is set on agi_channel . |
agi_callingpres | 0 | The caller presentation associated with the caller ID
set on agi_channel . For
more information, see the output of core show function CALLERPRES at the
Asterisk
CLI. |
agi_callingani2 | 0 | The caller ANI2 associated with agi_channel . |
agi_callington | 0 | The caller ID TON (Type of Number) associated with
agi_channel . |
agi_callingtns | 0 | The dialed number TNS (Transit Network Select)
associated with agi_channel . |
agi_dnid | 7010 | The dialed number associated with agi_channel . |
agi_rdnis | unknown | The redirecting number associated with agi_channel . |
agi_context | phones | The context of the dialplan that agi_channel was in when it executed
the AGI() or EAGI() application. |
agi_extension | 500 | The extension in the dialplan that agi_channel was executing when it
ran the AGI() or EAGI() application. |
agi_priority | 1 | The priority of agi_extension in agi_context that executed AGI() or EAGI() . |
agi_enhanced | 0.0 | An indication of whether AGI() or EAGI() was used from the dialplan.
0.0 indicates that AGI() was used. 1.0 indicates that EAGI() was used. |
agi_accountcode | myaccount | The accountcode
associated with agi_channel . |
agi_threadid | 140071216785168 | The threadid of the
thread in Asterisk that is running the AGI() or EAGI() application. This may be
useful for associating logs generated by the AGI application
with logs generated by Asterisk, since the Asterisk logs
contain thread IDs. |
agi_arg_ | my argument | These variables provide the contents of the additional
arguments provided to the AGI() or EAGI() application. |
For an example of the variables that might be sent to an AGI application, see the AGI communication debug output in the section called “Quick Start”. The end of the list of variables will be indicated by a blank line. Example 21.1, “A sample AGI script, hello-world.sh” handles these variables by reading lines of input in a loop until a blank line is received. At that point, the application continues and begins executing AGI commands.
When you use async AGI, Asterisk will send out a manager event to initiate the async AGI session. Here is an example manager event sent out by Asterisk:
Event: AsyncAGI Privilege: agi,all SubEvent: Start Channel: SIP/0000FFFF0001-00000000 Env: agi_request%3A%20async%0Aagi_channel%3A%20SIP%2F0000FFFF0001-00000000%0A \ agi_language%3A%20en%0Aagi_type%3A%20SIP%0Aagi_uniqueid%3A%201285219743.0%0A \ agi_version%3A%201.8.0-beta5%0Aagi_callerid%3A%2012565551111%0A \ agi_calleridname%3A%20Julie%20Bryant%0Aagi_callingpres%3A%200%0A \ agi_callingani2%3A%200%0Aagi_callington%3A%200%0Aagi_callingtns%3A%200%0A \ agi_dnid%3A%20111%0Aagi_rdnis%3A%20unknown%0Aagi_context%3A%20LocalSets%0A \ agi_extension%3A%20111%0Aagi_priority%3A%201%0Aagi_enhanced%3A%200.0%0A \ agi_accountcode%3A%20%0Aagi_threadid%3A%20-1339524208%0A%0A
Once an AGI session has been set up, Asterisk begins performing call processing in response to commands sent from the AGI application. As soon as an AGI command has been issued to Asterisk, no further commands will be processed on that channel until the current command has been completed. When it finishes processing a command, Asterisk will respond with the result.
The AGI processes commands in a serial manner.
Once a command has been executed, no further commands can be executed
until Asterisk has returned a response. Some commands can take a very
long time to execute. For example, the EXEC
AGI command executes an Asterisk
application. If the command is EXEC
Dial
, AGI communication is blocked until the call is done.
If your AGI application needs to interact further with Asterisk at
this point, it can do so using the AMI, which is covered in Chapter 20, Asterisk Manager Interface (AMI).
A full list of available AGI commands can be retrieved from the Asterisk console by running the
command agi show commands. These commands are described in Table 21.2, “AGI commands”. To get more detailed information on a
specific AGI command, including syntax information for any arguments
that a command expects, use agi show commands
topic <COMMAND>. For example, to see the built-in documentation for the
ANSWER
AGI command, you would
use agi show commands topic
ANSWER.
Table 21.2. AGI commands
AGI command | Description |
---|---|
ANSWER | Answer the incoming call. |
ASYNCAGI BREAK | End an async AGI session and have the channel return to the Asterisk dialplan. |
CHANNEL STATUS | Retrieve the status of the channel. This is used to retrieve the current state of the channel, such as up (answered), down (hung up), or ringing. |
DATABASE DEL | Delete a key/value pair from the built-in AstDB. |
DATABASE
DELTREE | Delete a tree of key/value pairs from the built-in AstDB. |
DATABASE GET | Retrieve the value for a key in the AstDB. |
DATABASE PUT | Set the value for a key in the AstDB. |
EXEC | Execute an Asterisk dialplan application on
the channel. This command is very powerful in that between
EXEC and GET FULL VARIABLE , you can do anything
with the call that you can do from the Asterisk
dialplan. |
GET DATA | Read digits from the caller. |
GET
FULL VARIABLE | Evaluate an Asterisk dialplan expression. You can send a
string that contains variables and/or dialplan functions, and
Asterisk will return the result after making the appropriate
substitutions. This command is very powerful in that between
EXEC and GET FULL VARIABLE , you can do anything
with the call that you can do from the Asterisk
dialplan. |
GET OPTION | Stream a sound file while waiting for a digit from
the caller. This is similar to the Background() dialplan
application. |
GET VARIABLE | Retrieve the value of a channel variable. |
HANGUP | Hang up the channel.[a] |
NOOP | Do nothing. You will get a result response from this command, just like any other. It can be used as a simple test of the communication path with Asterisk. |
RECEIVE CHAR | Receive a single character. This only works for
channel types that support it, such as IAX2 using TEXT frames or SIP using the MESSAGE method. |
RECEIVE TEXT | Receive a text message. This only works in the
same cases as RECEIVE
CHAR . |
RECORD FILE | Record the audio from the caller to a file. This
is a blocking operation similar to the Record() dialplan application. To
record a call in the background while you perform other
operations, use EXEC Monitor or EXEC MixMonitor . |
SAY ALPHA | Say a string of characters. You can find an
example of this in the section called “Quick Start”. To get
localized handling of this and the other SAY commands, set the channel language
either in the device configuration file (e.g., sip.conf ) or in the dialplan, by
setting the CHANNEL(language)
dialplan function. |
SAY DIGITS | Say a string of digits. For example, 100 would be said as “one zero zero” if the channel’s language is set to English. |
SAY NUMBER | Say a number. For example, 100 would be said as “one hundred” if the channel’s language is set to English. |
SAY PHONETIC | Say a string of characters, but use a common word for each letter (Alpha, Bravo, Charlie…). |
SAY DATE | Say a given date. |
SAY TIME | Say a given time. |
SAY DATETIME | Say a given date and time using a specified format. |
SEND IMAGE | Send an image to a channel. IAX2 supports this, but there are no actively developed IAX2 clients that support it that we know of. |
SEND TEXT | Send text to a channel that supports it. This can be used with SIP and IAX2 channels, at least. |
SET AUTOHANGUP | Schedule the channel to be hung up at a specified point in time in the future. |
SET CALLERID | Set the caller ID name and number on the channel. |
SET CONTEXT | Set the current dialplan context on the channel. |
SET EXTENSION | Set the current dialplan extension on the channel. |
SET MUSIC | Start or stop music on hold on the channel. |
SET PRIORITY | Set the current dialplan priority on the channel. |
SET VARIABLE | Set a channel variable to a given value. |
STREAM FILE | Stream the contents of a file to a channel. |
CONTROL STREAM
FILE | Stream the contents of a file to a channel, but also allow the channel to control the stream. For example, the channel can pause, rewind, or fast forward the stream. |
TDD MODE | Toggle the TDD (Telecommunications Device for the Deaf) mode on the channel. |
VERBOSE | Send a message to the verbose logger channel.
Verbose messages show up on the Asterisk console if the verbose
setting is set high enough. Verbose messages will also go to any
log file that has been configured for the verbose logger channel in /etc/asterisk/logger.conf . |
WAIT FOR DIGIT | Wait for the caller to press a digit. |
SPEECH CREATE | Initialize speech recognition. This must be done before using other speech AGI commands.[b] |
SPEECH SET | Set a speech engine setting. The settings that are available are specific to the speech recognition engine in use. |
SPEECH DESTROY | Destroy resources that were allocated for doing speech recognition. This command should be the last speech command executed. |
SPEECH LOAD GRAMMAR | Load a grammar. |
SPEECH UNLOAD
GRAMMAR | Unload a grammar. |
SPEECH ACTIVATE GRAMMAR | Activate a grammar that has been loaded. |
SPEECH DEACTIVATE GRAMMAR | Deactivate a grammar. |
SPEECH RECOGNIZE | Play a prompt and perform speech recognition, as well as wait for digits to be pressed. |
GOSUB | Execute a dialplan subroutine. This will perform
in the same way as the GoSub() dialplan application. |
[a] When the |
AGI commands are sent to Asterisk on a single line. The line must end with a single newline character. Once a command has been sent to Asterisk, no further commands will be processed until the last command has finished and a response has been sent back to the AGI application. Here is an example response to an AGI command:
200 result=0
The Asterisk console allows debugging the communications with an AGI application. To enable AGI communication debugging, run the agi set debug on command. To turn debugging off, use agi set debug off. While this debugging mode is on, all communication to and from an AGI application will be printed out to the Asterisk console. An example of this output can be found in the section called “Quick Start”.
When you’re using async AGI, commands are issued by
using the AGI
manager action. To
see the built-in documentation for the AGI manager action, run
manager show command AGI at the Asterisk CLI. A demonstration will help
clarify how AGI commands are executed using the async AGI method.
First, an extension is created in the dialplan that runs an async AGI
session on a channel:
exten => 7011,1,AGI(agi:async)
The following shows an example manager action
execution and the manager events that are emitted during async AGI
processing. After the initial execution of the AGI
manager action, there is an immediate
response to indicate that the command has been queued up for
execution. Later, there is a manager event that indicates that the
queued command has been executed. The CommandID
header can be used to associate
the initial request with the event that indicates that the command has
been executed:
Action: AGI
Channel: SIP/0004F2060EB4-00000013
ActionID: my-action-id
CommandID: my-command-id
Command: VERBOSE "Puppies like cotton candy." 1
Response: Success
ActionID: my-action-id
Message: Added AGI command to queue
Event: AsyncAGI
Privilege: agi,all
SubEvent: Exec
Channel: SIP/0004F2060EB4-00000013
CommandID: my-command-id
Result: 200%20result%3D1%0A
The following output is what was seen on the Asterisk console during this async AGI session:
-- Executing [7011@phones:1] AGI("SIP/0004F2060EB4-00000013", "agi:async") in new stack agi:async: Puppies like cotton candy. == Spawn extension (phones, 7011, 1) exited non-zero on 'SIP/0004F2060EB4-00000013'
An AGI session ends when your AGI application is ready for it to end. The details about how this happens depend on whether your application is using process-based AGI, FastAGI, or async AGI.
Your AGI application may exit or close its connection at any time. As long as the channel has not hung up before your application ends, dialplan execution will continue. If channel hangup occurs while your AGI session is still active, Asterisk will provide notification that this has occurred so that your application can adjust its operation as appropriate.
This is an area where behavior has changed since Asterisk 1.4. In Asterisk 1.4 and earlier versions, AGI would automatically exit and stop operation as soon as the channel hung up. It now gives your application the opportunity to continue running if needed.
If a channel hangs up while your AGI
application is still executing, a couple of things will happen. If an
AGI command is in the middle of executing, you may receive a result
code of -1
. You should not depend
on this, though, since not all AGI commands require channel
interaction. If the command being executed does not require channel
interaction, the result will not reflect the hangup.
The next thing that happens after a channel
hangs up is that an explicit notification of the hangup is sent to
your application. For process-based AGI, the signal SIGHUP
will be sent to the process to notify
it of the hangup. For a FastAGI connection, Asterisk will send a line
containing the word HANGUP
. If you
would like to disable having Asterisk send the SIGHUP
signal to your process-based AGI
application or the HANGUP
string to
your FastAGI server, you can do so by setting the AGISIGHUP
channel variable, as demonstrated
in the following short example:
; ; Don't send SIGHUP to an AGI process ; or the "HANGUP" string to a FastAGI server. ; exten => 500,1,Set(AGISIGHUP=no) same => n,AGI(my-agi-application)
At this point, Asterisk automatically adjusts its operation to be in DeadAGI mode. This just means that an AGI application can run on a channel that has been hung up. The only AGI commands that may be used at this point are those that do not require channel interaction. The documentation for the AGI commands built into Asterisk includes an indication of whether or not each command can be used once the channel has been hung up.
When you’re using async AGI, the manager
interface provides mechanisms to notify you about channel hangups.
When you would like to end an async AGI session for a channel, you
must execute the ASYNCAGI BREAK
command. When the async AGI session ends, Asterisk will send an
AsyncAGI
manager event with a
SubEvent
of End
. The following is an example of ending
an async AGI session:
Action: AGI
Channel: SIP/0004F2060EB4-0000001b
ActionID: my-action-id
CommandID: my-command-id
Command: ASYNCAGI BREAK
Response: Success
ActionID: my-action-id
Message: Added AGI command to queue
Event: AsyncAGI
Privilege: agi,all
SubEvent: End
Channel: SIP/0004F2060EB4-0000001b
At this point, the channel returns to the Asterisk dialplan if it has not yet been hung up.