The Asterisk Manager Interface (AMI) Protocol
The Asterisk Manager Interface (AMI) protocol is a very simple protocol that allows you to communicate and manage your asterisk server, almost completely. It has support to edit/create asterisk configuration files and also manage the calls, clients, agents, dialplan, etc.
You might also be interested in PAMI. An AMI client/framework that allows you to quickly develop ami clients in an oop/event-driven fashion.
Overview of the AMI Protocol
AMI is a plain text protocol, and it works by sending and receiving packets. Each packet consists in a series
of text lines delimited by \r\n. And each packet is delimited by \r\n\r\n.
AMI uses a tcp port configured in manager.conf. As soon as the connection is established, asterisk salutes you with something like:
Asterisk Call Manager/1.1
This message indicates that the communication can begin. Packets may be transmitted in either direction at any time after authentication.
AMI Packets (Actions, Responses, Events)
AMI defines 3 kind of possible packets:
- Actions: This kind of packet is what the client sends. Only the client can generate Actions.
- Responses: Actions have at least one Response, indicating the result of the executed (or requested) action.
- Events: There are two kind of events. The ones attached to a particular response for a particular action, and the ones that asterisk generate to inform the connected client about things that are happening in the server (like call events, changes in variables values, agents and other clients that connect/disconnect to/from the server, etc).
The first line of a packet will have a key of "Action" when sent from the client to Asterisk, but "Event" or "Response" when sent from Asterisk to the client.
A typical action is the Login action, which looks like this:
And its response is something like:
Message: Authentication accepted\r\n
Notice the ActionId field in the action and response packet. This field is optional, but highly recommended to send, because it tells asterisk to respond with this same actionid value so the client can easily associate the response with the action sent. If any events are attached to this response, they will also contain the same actionid value.
So the general format for an action packet is something like this:
Different actions require different keys and/or variables. You can find the complete list of actions here.
A response that contains a:
Is considered a failed action. Otherwise, should be a successfull one.
This kind of events are the ones that asterisk sends you at any given time without the need of you sending
any action. This events can be disabled via the Event action.
These events are used by asterisk whenever a response has a long payload to send. For example, when you ask for the dialplan lines, or the connected clients, or the status of all channels, etc.
Asterisk will return a Response packet indicating that the response actually has more data that will be sent in Events packets. A little note here. AMI is kind of broken and inconsistent (at least in asterisk 1.6). This means that there exists a couple of ways (depending on the action issued) for asterisk to report a Response with events attached.
To actually know if a given response contains events attached, you should check for
any of the following conditions:
Message: Result will follow
Message: Result follows
Response: Result will follow
The same happens when you're trying to know when to consider a response as completed (all events received). You should check for:
AMI is a pretty straightforward protocol. You can even try to create a client using netcat via a shell script or whatever programming language you like, allowing you to make console operators or manage the asterisk queues, calls, agents, etc from a single controlled point of your architecture. It has it pitfalls. For example, there is no specification as to quoting the ":" (semicolon) character (which separates keys from values) and some asterisk versions have a broken implementation for some events/resposes (i.e: not even sending the "Event:" / "Response:" keys,) sending a "follows" without a "complete", sending "follow" instead of "follows", not even sending "follows", etc.. a real nightmare).