> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tryhamsa.com/llms.txt
> Use this file to discover all available pages before exploring further.

# DTMF Features

> Three DTMF features for keypad interaction in voice agents

DTMF (Dual-Tone Multi-Frequency) signaling represents keypad button presses (0-9, \*, #) in telecommunication systems. Hamsa provides **three distinct DTMF features** for different use cases.

## Overview

| Feature                | Purpose                    | Availability                         | Use Case                       |
| ---------------------- | -------------------------- | ------------------------------------ | ------------------------------ |
| **Simple Transitions** | IVR menu navigation        | Conversation & Start nodes           | "Press 1 for Sales"            |
| **Input Capture**      | Collect digit sequences    | Conversation & Start nodes\*         | Account numbers, PINs          |
| **Global Triggers**    | Universal keypad shortcuts | All nodes (except web\_tool & start) | "Press 0 for operator anytime" |

\*Start nodes support DTMF input capture but do not have completion condition UI (timeout/termination/digitLimit).

### DTMF Processing Flow

```mermaid theme={null}
graph TD
    CALL[Call Active] --> DETECT{DTMF Tone<br/>Detected}

    DETECT -->|Key Pressed| TYPE{Which DTMF<br/>Feature?}

    TYPE -->|Feature 1| TRANS[Simple DTMF Transition]
    TYPE -->|Feature 2| CAPTURE[DTMF Input Capture]
    TYPE -->|Feature 3| GLOBAL[Global DTMF Trigger]

    TRANS --> CHECK1{Matching<br/>Transition?}
    CHECK1 -->|Yes| NEXT1[Transition to<br/>Target Node]
    CHECK1 -->|No| IGNORE1[Ignore Key]

    CAPTURE --> COLLECT[Collect Digits]
    COLLECT --> TERM{Termination<br/>Condition Met?}
    TERM -->|Digit Limit| STORE[Store in Variable]
    TERM -->|Termination Key| STORE
    TERM -->|Timeout| STORE
    TERM -->|No| COLLECT
    STORE --> CONTINUE[Continue Flow]

    GLOBAL --> CHECK3{Global Node<br/>with DTMF Key?}
    CHECK3 -->|Yes| JUMP[Jump to<br/>Global Node]
    CHECK3 -->|No| IGNORE3[Ignore Key]

    style TRANS fill:#e1f5ff
    style CAPTURE fill:#fff4e1
    style GLOBAL fill:#ffe1f5
    style STORE fill:#e1ffe1
    style JUMP fill:#e1ffe1
```

### DTMF Feature Comparison

```mermaid theme={null}
graph LR
    subgraph "Feature 1: Simple Transitions"
        F1[User presses key<br/>→ Route to node<br/>IVR menu navigation]
    end

    subgraph "Feature 2: Input Capture"
        F2[User enters sequence<br/>→ Store in variable<br/>Account numbers, PINs]
    end

    subgraph "Feature 3: Global Triggers"
        F3[User presses key<br/>→ Jump to global node<br/>Press 0 for operator]
    end

    CALL[Phone Call] --> F1
    CALL --> F2
    CALL --> F3

    style F1 fill:#e1f5ff
    style F2 fill:#fff4e1
    style F3 fill:#ffe1f5
```

***

## Feature 1: Simple DTMF Transitions

<Info>
  **Always available** on conversation and start nodes. No toggle or special configuration required.
</Info>

### Purpose

Enable IVR-style menu navigation where users press a single key to select an option and advance to a specific node.

### How It Works

Create menu options like "Press 1 for Sales, Press 2 for Support" by adding DTMF transitions to your nodes.

### Configuration

<Steps>
  <Step title="Add Transition">
    On a conversation or start node, click "+ Add Transition"
  </Step>

  <Step title="Select Type">
    Choose "DTMF" as the transition type
  </Step>

  <Step title="Pick Key">
    Click a key on the 3×4 keypad grid (0-9, \*, #)
  </Step>

  <Step title="Connect Node">
    Draw an edge to the target node
  </Step>
</Steps>

### Example

```yaml theme={null}
Conversation Node: 'Welcome! Press 1 for Sales, Press 2 for Support'
├─ Transition: DTMF key=1 → Sales_Department
└─ Transition: DTMF key=2 → Support_Department
```

<Tip>
  Use descriptive auto-generated labels like "Press 1" for clarity in your flow diagram.
</Tip>

***

## Feature 2: DTMF Input Capture

<Warning>
  Available on **conversation nodes and start nodes**. Requires variable name when enabled.

  **Note:** Start nodes support DTMF input capture but do not display completion condition UI (timeout/termination/digitLimit). These conditions only appear on conversation nodes.
</Warning>

### Purpose

Capture a sequence of DTMF digits (account number, PIN, phone number) and store it in a variable for use throughout your workflow.

### How It Works

When enabled, the AI listens for multiple keypad presses and stores the complete sequence in a named variable. Capture completes based on optional conditions.

### Configuration

<Steps>
  <Step title="Enable Capture">
    Open conversation node form → Find "DTMF Input Capture" → Toggle ON
  </Step>

  <Step title="Set Variable Name">
    Enter variable name (required): `account_number`, `pin_code`, etc.

    **Must follow snake\_case format**: lowercase, underscores allowed, starts with letter
  </Step>

  <Step title="Configure Completion">
    Set optional conditions (at least one recommended):

    * **Digit Limit**: Stop after X digits (1-20)
    * **Termination Key**: Stop when user presses #, \*, or 0-9
    * **Timeout**: Stop after X seconds of no input (1-30)
  </Step>
</Steps>

### Schema

```typescript theme={null}
{
  enabled: boolean,
  variableName: string,        // Required: ^[a-z][a-z0-9_]*$
  digitLimit?: number,          // Optional: 1-20
  terminationKey?: '0'-'9'|'#'|'*',  // Optional
  timeoutMs?: number           // Optional: 1000-30000
}
```

### Variable Usage

<Info>
  DTMF captured variables are **fully integrated** into the variable system and available to all downstream nodes.
</Info>

Once captured, use the variable in:

* **Message templates**: `"Your account number is {{account_number}}"`
* **Tool parameters**: Pass to API calls
* **Router conditions**: Branch based on value
* **Subsequent prompts**: Reference in any downstream node

### Example

```yaml theme={null}
Node: Account_Lookup
Message: "Please enter your 6-digit account number followed by pound"

DTMF Input Capture:
  enabled: true
  variableName: account_number
  digitLimit: 6
  terminationKey: #
  timeout: 15 seconds

→ User enters: 1-2-3-4-5-6-#
→ Variable {{account_number}} = "123456"

Next Node (Tool):
  API Call: lookup_customer
  Parameters:
    account_id: {{account_number}}
```

<Tip>
  The captured variable appears on the node with a phone icon badge for easy identification.
</Tip>

<Warning>
  **DTMF Capture Restriction:** When DTMF input capture is enabled on a node, number keys (0-9) **cannot be used** for DTMF transitions on that same node. Only **#** and **\*** keys remain available for menu navigation. This prevents conflicts between digit capture and menu options.
</Warning>

***

## Feature 3: Global Node DTMF Triggers

<Info>
  Available on all node types except **web\_tool** and **start** nodes.
</Info>

### Purpose

Allow global nodes to be triggered from anywhere in the workflow by pressing a specific key, providing quick access to critical functions.

### How It Works

When a node is marked as global with DTMF trigger type, pressing the configured key from anywhere in the call immediately activates that node.

### Configuration

<Steps>
  <Step title="Enable Global Mode">
    Open any node form → Find "Global" section → Toggle ON
  </Step>

  <Step title="Select Trigger Type">
    Choose between:

    * **Natural Language (Prompt)**: Triggered by speech
    * **Keypad Press (DTMF)**: Triggered by key press
  </Step>

  <Step title="Configure DTMF Key">
    If DTMF selected, choose key from keypad grid

    **Common conventions:**

    * 0: Operator/human agent
    * 9: Repeat main menu
    * \*: Go back/previous menu
    * \#: Confirm/submit
  </Step>
</Steps>

### Schema

```typescript theme={null}
{
  isGlobal: true,
  globalConditionType: 'dtmf',  // or 'prompt'
  globalDtmfKey: '0',          // Required when type='dtmf'
}
```

### Examples

#### Operator Transfer (DTMF 0)

```yaml theme={null}
Transfer Call Node (Global):
  isGlobal: true
  globalConditionType: dtmf
  globalDtmfKey: 0
  phoneNumber: +1-800-OPERATOR

→ User can press 0 anytime to reach operator
```

#### Repeat Menu (DTMF 9)

```yaml theme={null}
Conversation Node (Global):
  isGlobal: true
  globalConditionType: dtmf
  globalDtmfKey: 9
  message: "Main menu: Press 1 for Sales, 2 for Support"

→ User can press 9 anytime to hear menu again
```

#### Emergency Support (DTMF \*)

```yaml theme={null}
Transfer Call Node (Global):
  isGlobal: true
  globalConditionType: dtmf
  globalDtmfKey: *
  phoneNumber: +1-800-EMERGENCY

→ User can press * anytime for emergency support
```

***

## Roadmap

**Outbound IVR Navigation** — the ability for agents to automatically navigate external IVR phone trees when making outbound calls — is not yet available. It is on the roadmap and will be supported in a future release.

***

## Complete IVR Flow Example

Here's a comprehensive example combining all three DTMF features:

```mermaid theme={null}
graph TD
    Start[Start Node: Main Menu<br/>Press 1=Sales, 2=Support, 0=Operator]
    Sales[Sales Node:<br/>Enter Customer ID]
    Support[Support Node]
    Lookup[Tool: Lookup Customer]
    Operator[Global: Transfer to Operator<br/>DTMF Key: 0]
    Menu[Global: Repeat Menu<br/>DTMF Key: 9]

    Start -->|DTMF: 1| Sales
    Start -->|DTMF: 2| Support
    Sales -->|Capture: customer_id| Lookup

    Start -.->|DTMF: 0 (anytime)| Operator
    Start -.->|DTMF: 9 (anytime)| Menu
```

**Implementation:**

```yaml theme={null}
Start Node (Conversation):
  message: "Welcome! Press 1 for Sales, 2 for Support, 0 for operator"
  transitions:
    - type: dtmf, key: 1 → Sales_Node
    - type: dtmf, key: 2 → Support_Node

Sales Node (Conversation):
  message: "Please enter your customer ID followed by #"
  dtmfInputCapture:
    enabled: true
    variableName: customer_id
    terminationKey: #
    timeout: 15s
  transitions:
    - type: always → Lookup_Tool

Lookup Tool (Tool):
  tool: lookup_customer
  parameters:
    id: {{customer_id}}  # Uses captured DTMF variable

Operator Node (Transfer Call - Global):
  isGlobal: true
  globalConditionType: dtmf
  globalDtmfKey: 0
  phoneNumber: +1-800-OPERATOR

Repeat Menu Node (Conversation - Global):
  isGlobal: true
  globalConditionType: dtmf
  globalDtmfKey: 9
  message: "Main menu: Press 1 for Sales, 2 for Support"
```

***

## Validation

<Warning>
  DTMF features are validated at both node and workflow levels. Errors prevent saving until resolved.
</Warning>

### Validation Rules

| Feature               | Field         | Requirement             | Error                      |
| --------------------- | ------------- | ----------------------- | -------------------------- |
| **Input Capture**     | Variable Name | Required when enabled   | Must be snake\_case format |
| **Simple Transition** | DTMF Key      | Required                | Must select a key          |
| **Global Trigger**    | DTMF Key      | Required when type=dtmf | Must select a key          |

### Error Indicators

* **Node level**: Red icon in node header
* **Workflow level**: Errors in workflow header dropdown
* **Focus button**: Navigate to problematic nodes

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="DTMF transitions not working">
    **Possible causes:**

    * Key not selected in popover
    * Transition not connected to target node
    * Using on unsupported node type (not conversation/start)

    **Solution:** Verify key selection and node connections
  </Accordion>

  <Accordion title="Input capture variable empty">
    **Possible causes:**

    * User didn't enter any digits
    * Timeout occurred before input
    * Variable name typo in usage

    **Solution:** Add validation, check variable name syntax
  </Accordion>

  <Accordion title="Global DTMF not triggering">
    **Possible causes:**

    * Node not marked as global
    * DTMF key not configured
    * Trigger type set to 'prompt' instead of 'dtmf'

    **Solution:** Verify global settings and trigger type
  </Accordion>

  <Accordion title="Validation errors on save">
    **Possible causes:**

    * Missing variable name when input capture enabled
    * Invalid variable name format
    * DTMF key not selected

    **Solution:** Check workflow header dropdown, click "Focus" to navigate to errors
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Variables" icon="code" href="/agents/variables/introduction">
    Learn how to use captured variables throughout your flow
  </Card>

  <Card title="Transitions" icon="arrows-split-up-and-left" href="/agents/flow-agent/transitions">
    Master all transition types including DTMF
  </Card>

  <Card title="Router Node" icon="route" href="/agents/flow-agent/nodes/router-node">
    Use captured variables in routing logic
  </Card>

  <Card title="Best Practices" icon="check" href="/agents/flow-agent/best-practices">
    Learn flow agent best practices
  </Card>
</CardGroup>
