Files
hold-slayer/docs/dial-plan.md
Robert Helewka ecf37658ce feat: add initial Hold Slayer AI telephony gateway implementation
Complete project scaffolding and core implementation of an AI-powered
telephony system that calls companies, navigates IVR menus, waits on
hold, and transfers to the user when a human answers.

Key components:
- FastAPI server with REST API, WebSocket, and MCP (SSE) interfaces
- SIP/VoIP call management via PJSUA2 with RTP audio streaming
- LLM-powered IVR navigation using OpenAI/Anthropic with tool calling
- Hold detection service combining audio analysis and silence detection
- Real-time STT (Whisper/Deepgram) and TTS (OpenAI/Piper) pipelines
- Call recording with per-channel and mixed audio capture
- Event bus (asyncio pub/sub) for real-time client updates
- Web dashboard with live call monitoring
- SQLite persistence via SQLAlchemy with call history and analytics
- Notification support (email, SMS, webhook, desktop)
- Docker Compose deployment with Opal VoIP and Opal Media containers
- Comprehensive test suite with unit, integration, and E2E tests
- Simplified .gitignore and full project documentation in README
2026-03-21 19:23:26 +00:00

105 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Hold Slayer Gateway — Dial Plan
## Overview
The gateway accepts calls from registered SIP endpoints and routes them
based on the dialled digits. No trunk-access prefix (no "9") is needed.
All routing is pattern-matched in order; the first match wins.
---
## ⚠️ Emergency Services — 911
> **911 and 9911 are always routed directly to the PSTN trunk.**
> No gateway logic intercepts, records, or delays these calls.
> `9911` is accepted in addition to `911` to catch the common
> mis-dial habit of dialling `9` for an outside line.
>
> **Your SIP trunk provider must support emergency calling on your DID.**
> Verify this with your provider before putting this system in service.
> VoIP emergency calling has location limitations — ensure your
> registered location is correct with your provider.
---
## Extension Ranges
| Range | Purpose |
|-------|--------------------------------|
| 2XX | SIP endpoints (phones/softphones) |
| 5XX | System services |
---
## 2XX — Endpoint Extensions
Extensions are auto-assigned from **221** upward when a SIP device
registers (`SIP REGISTER`) with the gateway or via `POST /api/devices`.
| Extension | Format | Example |
|-----------|---------------------------------|--------------------------------|
| 221299 | Auto-assigned to registered devices | `sip:221@gateway.helu.ca` |
### Assignment policy
- First device to register gets **221**, next **222**, and so on.
- Extensions are persisted in the database and survive restarts.
- If a device is removed its extension is freed and may be reassigned.
- `GATEWAY_SIP_DOMAIN` in `.env` sets the domain part of the URI.
---
## 5XX — System Services
| Extension | Service | Notes |
|-----------|----------------------|-----------------------------------------|
| 500 | Auto-attendant | Reserved — not yet implemented |
| 510 | Gateway status | Plays a status announcement |
| 511 | Echo test | Returns audio back to caller |
| 520 | Hold Slayer launch | Prompts for a number to hold-slay |
| 599 | Operator fallback | Transfers to preferred device |
---
## Outbound PSTN
All outbound patterns are routed via the configured SIP trunk
(`SIP_TRUNK_HOST`). No access code prefix is needed.
### Pattern table
| Pattern | Example input | Normalised to | Notes |
|----------------------|--------------------|---------------------|------------------------------------|
| `+1NPANXXXXXX` | `+16135550100` | `+16135550100` | E.164 — pass through as-is |
| `1NPANXXXXXX` | `16135550100` | `+16135550100` | NANP with country code |
| `NPANXXXXXX` | `6135550100` | `+16135550100` | 10-digit NANP — prepend `+1` |
| `011CC…` | `01144201234567` | `+44201234567` | International — strip `011` |
| `00CC…` | `004420…` | `+4420…` | International alt prefix |
| `+CC…` | `+44201234567` | `+44201234567` | E.164 international — pass through |
### Rules
1. E.164 (`+` prefix) is always passed to the trunk unchanged.
2. NANP 11-digit (`1` + 10 digits) is normalised to E.164 by prepending `+`.
3. NANP 10-digit is normalised to E.164 by prepending `+1`.
4. International via `011` or `00` strips the IDD prefix and prepends `+`.
5. 7-digit local dialling is **not supported** — always dial the area code.
---
## Inbound PSTN
Calls arriving from the trunk on the DID (`SIP_TRUNK_DID`) are routed
to the highest-priority online device. If no device is online the call
is queued or dropped (configurable via `MAX_HOLD_TIME`).
---
## Future
- Named regions / area-code routing
- Least-cost routing across multiple trunks
- Time-of-day routing (business hours vs. after-hours)
- Ring groups across multiple 2XX extensions
- Voicemail (extension 500)