> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.jambonz.org/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.jambonz.org/_mcp/server.

# Answering machine detection

> Configure answering machine detection in jambonz to identify voicemail and human answers on outbound calls. Tuning parameters explained.

The answering machine detection (amd) feature can be enabled on either outbound or inbound calls
to provide an indication of whether a call has been answered by a person or a machine.

> **Note**
>
> The reason for supporting amd on inbound calls is that some dialers will place an outbound call and then
> connect it to jambonz by sending an INVITE to jambonz.  While jambonz sees this as an incoming call,
> you may still want to peform answering machine detection on the call.  You can do this by having your
> application use a [config](/verbs/verbs/config) verb with an `amd` property.

```json
{
  "verb": "dial",
  "actionHook": "/outdial",
  "callerId": "+16173331212",
  "target": [
    {
      "type": "phone",
      "number": "+15083084809",
      "trunk": "Twilio"
    }
  ],
  "amd": {
    "actionHook": "/amdEvents"
  }
}
```

In the example above when the dialed call is answered the answering machine
detection feature will begin listening on the outbound call leg and after a short period of time will send a
webhook to '/amdEvents' with an indication of whether a human or a machine has answered the call.

## Parameters

**`actionHook`** `string` — required

Webhook to send AMD events.

---

**`recognizer`** `object`

Speech [recognizer](/verbs/verbs/recognizer) to use, if you want to override the application default settings.

---

**`thresholdWordCount`** `number` — default: 9

Number of spoken words in a greeting that result in an `amd_machine_detected` result.

---

**`digitCount`** `number` — default: 0

Number of digits in a greeting to trigger a `amd_machine_detected` result. 0 is off

---

**`timers`** `object`

Object containing various timeouts.

---

**`timers.decisionTimeoutMs`** `number` — default: 15000

Time in milliseconds to wait before returning `amd_decision_timeout`.

---

**`timers.greetingCompletionTimeoutMs`** `number` — default: 2000

Silence in milliseconds to wait for during greeting before returning `amd_machine_stopped_speaking`.

---

**`timers.noSpeechTimeoutMs`** `number` — default: 5000

Time in milliseconds to wait for speech before returning `amd_no_speech_detected`.

---

**`timers.toneTimeoutMs`** `number` — default: 20000

Time in milliseconds to wait to hear a tone.

---

### actionHook properties

The payload in the webhook will look something like this:

```json
{
  "type": "amd_human_detected"
}
```

or

```json
{
  "type": "amd_machine_detected",
  "reason": "hint",
  "hint": "call has been forwarded",
  "language": "en-us"
}
```

If no speech is detected at all from the far end, the payload will look like this:

```json
{
  "type": "amd_no_speech_detected"
}
```

And, finally, if the answering machine detection feature is unable to determine whether the remote party is a machine or human it will return

```json
{
  "type": "amd_decision_timeout"
}
```

The `type` property can have the following values:

| type                         | meaning                                           | additional properties              |
| ---------------------------- | ------------------------------------------------- | ---------------------------------- |
| amd_human_detected           | a human is speaking                               | reason, greeting, language         |
| amd_machine_detected         | a machine is speaking                             | reason, hint, transcript, language |
| amd_no_speech_detected       | no speech was detected                            | none                               |
| amd_decision_timeout         | no decision was able to be made in the time given | none                               |
| amd_machine_stopped_speaking | machine has completed the greeting                | none                               |
| amd_tone_detected            | a beep was detected                               | none                               |
| amd_error                    | an error has occurred                             | error                              |
| amd_stopped                  | answering machine detection was stopped           | none                               |

Additional properties:

| name       | description                                                 |
| ---------- | ----------------------------------------------------------- |
| reason     | describes why the decision was made (e.g. "short greeting") |
| greeting   | the text of the greeting that was detected                  |
| hint       | the hint that was matched in the greeting                   |
| transcript | the transcript that was gathered                            |
| language   | the language that was detected                              |

> **Note**
>
> It is possible to receive more than one event for a single call.  For instance, a possible sequence of events on a call to an answering machine is:
>
> 1. amd_machine_detected, then
> 2. amd_tone_detected, then
> 3. amd_machine_stopped_speaking

The application receiving the webhook can optionally return a new jambonz payload of verbs to change the call flow
based on the result of the answering machine detection.

For instance, say you had an outbound dialer application and you want
to deliver a message when you connect to a person, but otherwise hang up.
In that case, your app can respond to the webhook with a simple [hangup](/verbs/verbs/hangup) verb
if you receive an event payload indicating a machine has answered.

### Length of greeting

The answering machine detection feature leverages the fact that voicemail greetings are typically quite a bit more lengthy than a human's greeting.  When the call is answered, speech recognition is used to determine the length of the greeting and if it is shorter than a (configurable) threshold, it is determined to be human; if longer then it is determined to be a machine.

### Key Voicemail phrases

Optionally, the feature can also given a list of common phrases that one might hear on a voicemail greeting.  If any of the phrases are detected then the determination is immediately made that this is a machine.  These phrases are supplied via an external file, so they can be easily updated as needed for a specific deployment.  As example, here are sample phrases that might be used for an english language greeting:

```json
{
  "en-US": [
    "call has been forwarded",
    "at the beep",
    "at the tone",
    "leave a message",
    "leave me a message",
    "not available right now",
    "not available to take your call",
    "can't take your call",
    "I will get back to you",
    "I'll get back to you",
    "we will get back to you",
    "we are unable",
    "we are not available"
  ]
}
```

The current set of phrases is defined [here](https://github.com/jambonz/jambonz-feature-server/blob/main/data/example-voicemail-greetings.json).
Feel free to make a pull request against that repo to suggest additional phrases or languages that should be added.

### Digit Count

Many voicemail systems (especially on cellular) include the called number as part of their default greeting, the transcription returns these digits as a single "word" eg "07790123900 is not availble",
therefore the `thresholdWordCount` is often not reached for what is in effect a long message.\

By default the feature is off (digitCount = 0) so won't trigger. The length is adjustable for different scenarios and countries, with UK numbers I've found that 5-6 is a good value.\

There are some humans (in the UK at least) that still answer their landlines with the phone number eg "London 212555" so you may need to consider your audience with this feature.

### Beep detection

The feature also attempts to detect audio tones, or beeps that are commonly used on voicemail systems.  If detected, an event is sent via the actionHook to the webapp.

### Determining when to leave a voicemail

For an application that wishes to leave a message on a voicemail system, it is necessary to know when the voicemail greeting has completed and the voicemail system is now ready to record the message.  If the feature determines that the remote party is a machine, it will continue listening to the greeting until it completes and then send an event via the `actionHook` to the application.  This can be used as a cue to let the application know that it is time to start leaving the message.