--- title: "Dynamic Routing Module Documentation" description: "Documentation for Dynamic Routing" --- ## Table of Contents 1. [Navigation & Access](#navigation--access) 2. [Screenshots & Visual Interface](#screenshots--visual-interface) 3. [Module Overview (Technical)](#1-module-overview-technical) 4. [Module Overview (Commercial/Business)](#2-module-overview-commercialbusiness) 5. [Module Overview (End User/Administrator)](#3-module-overview-end-useradministrator) 6. [Configuration Fields Reference](#4-configuration-fields-reference) 7. [How It Works](#5-how-it-works) 8. [Common Scenarios & Examples](#6-common-scenarios--examples) 9. [Model Context Protocol (MCP) AI Integration](#7-model-context-protocol-mcp-ai-integration) 10. [Limitations & Important Notes](#8-limitations--important-notes) 11. [Troubleshooting Tips](#9-troubleshooting-tips) 12. [Glossary](#10-glossary) --- ## Navigation & Access To access the Dynamic Routing module: 1. Log in to the Ring2All Web Portal. 2. In the left navigation sidebar, expand **PBX Engine**. 3. Under **Call Routing**, click **Dynamic Routing** (`/pbx/calls-routing/dynamic`). --- ## Screenshots & Visual Interface ### Dynamic Routing Pending Entries View Displays active dynamic route entries awaiting callback, including caller token/number, mapped internal extension, and expiration timestamps. ![Dynamic Routing List View](/screenshots/pbx/call-routing/dynamic-routing-list.png) ### Dynamic Routing Configuration Form Provides global domain settings for digits matching, automatic record purging upon callback answer, expiration window, and missed-call-only filtering. ![Dynamic Routing Configuration Form](/screenshots/pbx/call-routing/dynamic-routing-form.png) --- ## 1. Module Overview (Technical) ### What Is Dynamic Routing? Dynamic Routing (also called "Callback on No Answer") is a feature that **automatically routes inbound calls to the extension that previously called the caller**. When an extension makes an outbound call that goes unanswered, the system registers the caller ID. If that person calls back, they're automatically routed to the original extension. ### Architecture ``` ┌─────────────────────────────────────────────────────────────────┐ │ Dynamic Routing System │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ PHASE 1: OUTBOUND CALL (Registration) │ │ ─────────────────────────────────────── │ │ Extension 1001 calls +15055551234 │ │ │ │ │ ▼ │ │ [Outbound call goes to gateway] │ │ │ │ │ ▼ │ │ Call NOT answered (NO_ANSWER, USER_BUSY, etc.) │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ dynamic_routing_register.lua │ │ │ │ │ │ │ │ 1. Check extension has dynamic_routing_enabled │ │ │ │ 2. Check only_keep_missed_calls config │ │ │ │ 3. Normalize destination: +15055551234 → 5055551234 │ │ │ │ 4. Apply digits_match: 5055551234 → 5551234 (7 digits) │ │ │ │ 5. Insert into public.dynamic_route_entries │ │ │ │ -> token: 5551234, extension: 1001 │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ═══════════════════════════════════════════════════════════ │ │ │ │ PHASE 2: INBOUND CALLBACK (Matching) │ │ ──────────────────────────────────── │ │ +15055551234 calls in │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ route_with_fallback.lua │ │ │ │ │ │ │ │ 1. Normalize caller ID: +15055551234 → 5551234 │ │ │ │ 2. Query public.dynamic_route_entries WHERE │ │ │ │ token LIKE '%5551234' AND expires_at > NOW() │ │ │ │ 3. Match found! extension = 1001 │ │ │ │ 4. Route caller directly to extension 1001 │ │ │ │ 5. Delete entry if delete_used_records = true │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 2. Module Overview (Commercial/Business) ### Business Value Dynamic Routing provides **automatic callback recognition**: | Without Dynamic Routing | With Dynamic Routing | |-------------------------|----------------------| | Callback goes to main IVR | Callback goes to original caller | | Caller navigates menus | Direct connection | | Receptionist routing | Automatic routing | | Poor callback experience | Seamless callback | ### Use Cases 1. **Sales Teams** - Sales rep calls prospect - Prospect calls back → routed to same rep - Better customer relationships 2. **Support Teams** - Tech calls back customer - Customer returns call → same tech - Continuity of service 3. **Personal Extensions** - User makes outbound call - Callback routed to their extension - Personal call management ### Feature Highlights | Feature | Benefit | |---------|---------| | **Automatic Registration** | No manual setup | | **Missed Calls Only** | Register unanswered calls | | **Configurable Expiration** | Time-limited matching | | **Digits Match** | Flexible caller ID matching | | **Per-Extension Enable** | Selective activation | | **Auto-Delete** | Clean up after callback | --- ## 3. Module Overview (End User/Administrator) ### What Can You Do? **Domain Configuration:** - Set digits to match (caller ID suffix) - Configure expiration time - Enable/disable delete after use - Enable/disable missed calls only **Extension Settings:** - Enable dynamic routing per extension **Pending Routes:** - View active callback entries - Delete entries manually - Search by caller ID or extension ### Administrator Workflow ``` ┌─────────────────────────────────────────────────────────────────┐ │ Dynamic Routing Configuration │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Tab: Configuration │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ │ │ │ │ Caller ID Digits to Match: [7 ] │ │ │ │ (Extracts last N digits from caller ID for matching) │ │ │ │ │ │ │ │ Expiration (Minutes): [60 ] │ │ │ │ (How long entries remain valid) │ │ │ │ │ │ │ │ ☑ Delete Used Records │ │ │ │ (Remove entry after successful callback routing) │ │ │ │ │ │ │ │ ☑ Only Keep Missed Calls │ │ │ │ (Only register calls not answered by called party) │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────┘ │ │ │ │ Tab: Pending Routes │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ Caller ID │ Extension │ Expires At │ Actions │ │ │ │ 5551234 │ 1001 │ 2026-01-16 17:00 │ [Delete] │ │ │ │ 5559999 │ 1002 │ 2026-01-16 17:30 │ [Delete] │ │ │ └────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ### Extension Enable In Extension settings: ``` Extension 1001 → Dynamic Routing Enabled: ✓ ``` ### Quick Tips > [!TIP] > **Digits Match = 7**: Works well for 10-digit numbers where prefix varies. > [!TIP] > **Expiration = 60**: One hour is typical for callback windows. > [!CAUTION] > **Too Few Digits**: Low digits_match may cause false matches. --- ## 4. Configuration Fields Reference ### Domain Configuration | Field | Description | Default | |-------|-------------|---------| | **Digits to Match** | Last N digits of caller ID to use | 7 | | **Expiration (Minutes)** | How long entries remain valid | 60 | | **Delete Used Records** | Remove entry after callback routed | On | | **Only Keep Missed Calls** | Only register unanswered calls | On | ### Digits Match Examples | Caller ID | Digits Match | Token Stored | |-----------|--------------|--------------| | +15055551234 | 7 | 5551234 | | +15055551234 | 10 | 5055551234 | | +15055551234 | 0 (blank) | 15055551234 | ### Missed Call Detection These hangup causes register an entry: - `NO_ANSWER` - `USER_BUSY` - `CALL_REJECTED` - `ORIGINATOR_CANCEL` - `NO_USER_RESPONSE` - `SUBSCRIBER_ABSENT` - `DESTINATION_OUT_OF_ORDER` ### Extension Settings | Field | Description | |-------|-------------| | **Dynamic Routing Enabled** | Enable callback registration for this extension | --- ## 5. How It Works ### Registration Flow (Outbound) ``` 1. Extension 1001 dials 918005551234 2. Route strips 9, dials 18005551234 via gateway 3. Call is NOT answered (NO_ANSWER) 4. route_with_fallback.lua completes bridge 5. dynamic_routing_register.lua runs: - Check: extension has dynamic_routing_enabled? ✓ - Check: only_keep_missed_calls & is this a missed call? ✓ - Normalize: 18005551234 → digits → 5551234 (7 digits) - Insert: token=5551234, extension=1001, expires=NOW()+60min ``` ### Matching Flow (Inbound) ``` 1. Caller +18005551234 calls in 2. route_with_fallback.lua starts 3. Check dynamic_route_entries: - Normalize caller ID → 5551234 - Query: WHERE token LIKE '%5551234' AND expires_at > NOW() - Match found! extension = 1001 4. Route caller to extension 1001 5. If delete_used_records: DELETE entry ``` ### Token Matching Logic ``` Digits Match = 7 Outbound: +15055551234 → Store: 5551234 Inbound: +18005551234 → Match: %5551234 Token: 5551234 Query: WHERE token LIKE '%5551234' Match: ✓ ``` --- ## 6. Common Scenarios & Examples ### Scenario 1: Sales Rep Callback **Configuration:** | Setting | Value | |---------|-------| | Digits Match | 7 | | Expiration | 120 min | | Delete Used | ✓ | | Only Missed | ✓ | **Flow:** 1. Sales rep 1001 calls prospect 2. Prospect doesn't answer 3. Entry created: 5551234 → 1001 4. Prospect calls back 30 min later 5. Routed directly to extension 1001 ### Scenario 2: Support Technician **Configuration:** | Setting | Value | |---------|-------| | Digits Match | 10 | | Expiration | 480 min (8 hours) | | Delete Used | ✓ | | Only Missed | Off | **Flow:** 1. Tech 1002 calls customer, call answered 2. Entry created (even though answered) 3. Customer calls back later 4. Routed to same tech ### Scenario 3: High Volume Call Center **Configuration:** | Setting | Value | |---------|-------| | Digits Match | 7 | | Expiration | 30 min | | Delete Used | ✓ | | Only Missed | ✓ | **Flow:** - Short expiration to reduce false matches - Only missed calls to reduce entries - Auto-delete to keep table clean --- ## 7. Model Context Protocol (MCP) AI Integration Ring2All exposes native Model Context Protocol (MCP) tools for **Dynamic Routing (Smart Callback)**, enabling AI assistants, CRM automation bots, and contact center supervisors to inspect dynamic callback rules, query pending callback tokens across customer numbers, adjust matching parameters in real time, and prune stale callback records programmatically with domain-level isolation. ### Available MCP Tools | Tool Name | Description | Key Parameters | |:---|:---|:---| | `get_dynamic_routing_config` | Retrieves the domain's current Dynamic Routing configuration, including digits match length, record expiration window, and purge flags. | None | | `update_dynamic_routing_config` | Updates dynamic callback behavior: number of digits to match from caller ID (1-20), expiration in minutes, and flags for purging answered records or logging missed calls only. | `digitsMatch` (string), `expirationMinutes` (number), `deleteUsedRecords` (boolean), `onlyKeepMissedCalls` (boolean) | | `list_dynamic_route_entries` | Lists active remembered callback entries awaiting incoming customer callbacks, showing phone token, mapped agent extension, and expiration timestamps. | `search` (optional string - phone number or extension) | | `delete_dynamic_route_entry` | Manually removes/expires a specific remembered dynamic route entry before its TTL expires. | `id` (required number) | ### Operational Logic & Guardrails - **Domain-Isolated Memory**: Dynamic route entries and configurations are strictly bound to `domain_id`. Customer numbers called from one tenant will never trigger callback routing into a different tenant's extensions. - **Atomic Upsert Config**: Configuration updates execute atomic PostgreSQL `ON CONFLICT (domain_id) DO UPDATE` queries, eliminating race conditions when multiple automation triggers update matching windows. - **Fast In-Memory Dialplan Evaluation**: Inbound matching queries execute direct index-backed queries in `route_with_fallback.lua`, ensuring sub-millisecond route decisions during high-volume call traffic. ### AI Agent Operational Examples #### Auditing Active Dynamic Callback Entries for a Customer Number ```json { "tool": "list_dynamic_route_entries", "arguments": { "search": "5551234" } } ``` #### Adjusting Dynamic Callback Window for High-Urgency Campaigns ```json { "tool": "update_dynamic_routing_config", "arguments": { "digitsMatch": "10", "expirationMinutes": 180, "deleteUsedRecords": true, "onlyKeepMissedCalls": true } } ``` ### Recommended Natural Language Prompts - *"Check the current Dynamic Routing configuration for this domain."* - *"Show me all pending callback entries currently registered for extension 1001."* - *"Increase the dynamic callback expiration window to 2 hours."* - *"Remove the dynamic route entry with ID 42."* --- ## 8. Limitations & Important Notes ### Technical Notes > [!NOTE] > **Suffix Matching**: Uses SQL `LIKE '%token'` for flexible matching. > [!WARNING] > **False Matches**: Too few digits_match may route wrong caller. > [!WARNING] > **International Prefixes**: Ensure consistent normalization for global use. ### Best Practices 1. **Use 7-10 Digits**: Balances flexibility and accuracy 2. **Set Reasonable Expiration**: 1-2 hours typical 3. **Enable Delete Used**: Prevents stale entries 4. **Enable Only Missed**: Reduces unnecessary entries 5. **Test Before Production**: Verify matching works correctly --- ## 9. Troubleshooting Tips ### Common Issues | Symptom | Possible Cause | Solution | |---------|---------------|----------| | No entry created | Extension not enabled | Enable dynamic_routing_enabled | | Entry not created | Call was answered | Check only_keep_missed_calls | | No match found | Digits don't match | Adjust digits_match | | Entry expired | Expiration too short | Increase expiration_minutes | | Wrong extension | Digits too few | Increase digits_match | ### Diagnostic SQL **Check domain configuration:** ```sql SELECT * FROM public.dynamic_routing_configs WHERE domain_id = [domain_id]; ``` **List pending entries:** ```sql SELECT id, token, extension, expires_at, created_at FROM public.dynamic_route_entries WHERE domain_id = [domain_id] AND expires_at > NOW() ORDER BY created_at DESC; ``` **Check extension setting:** ```sql SELECT extension, dynamic_routing_enabled FROM public.sip_extensions WHERE domain_id = [domain_id] AND extension = '1001'; ``` ### Telephony Server Logs ```bash # Check registration grep "DYNAMIC_ROUTING_REGISTER" /var/log/freeswitch/freeswitch.log # Check matching grep "DYNAMIC_ROUTING" /var/log/freeswitch/freeswitch.log ``` --- ## 10. Glossary | Term | Definition | |------|------------| | **Dynamic Routing** | Automatic callback-to-extension routing | | **Token** | Normalized caller ID digits stored for matching | | **Digits Match** | Number of digits to extract from caller ID | | **Expiration** | How long an entry remains valid | | **Delete Used** | Remove entry after successful callback | | **Only Missed** | Only register unanswered outbound calls | --- *Documentation last updated: January 2026*