Asterisk Dialplan: Subroutines (Latest Versions)
Updated guide for modern Asterisk (PJSIP era): subroutines with real configs, common mistakes, and troubleshooting steps.
As Asterisk dialplans grow, repeating the same logic in multiple places becomes difficult to manage and error-prone.
Subroutines solve this problem by allowing you to write reusable dialplan logic that can be called from anywhere.
Modern telecom systems—IVR menus, call logging, CRM updates, recording setup, compliance checks, and AI triggers—depend heavily on clean reusable subroutine design.
This guide explains subroutines in latest Asterisk with PJSIP, using real production-ready patterns.
What Is a Dialplan Subroutine?
A subroutine is a separate block of dialplan logic that can be executed and then returned from, similar to a function in programming.
In Asterisk, subroutines are typically implemented using:
- Gosub() → call a subroutine
- Return() → come back to original execution point
Basic Subroutine Syntax
Calling a Subroutine
same => n,Gosub(sub-log-call,s,1)
Defining the Subroutine Context
[sub-log-call]
exten => s,1,NoOp(Logging call ${UNIQUEID})
same => n,Return()
Execution flow:
- Main dialplan calls
Gosub() - Asterisk runs logic inside subroutine
Return()sends control back
Why Subroutines Matter in Production Systems
- Avoid duplicate dialplan code
- Centralize logging and compliance checks
- Enable reusable CRM/API integrations
- Simplify maintenance and debugging
Large call centers may execute dozens of subroutines per call.
Passing Arguments to Subroutines
You can pass parameters using:
Gosub(sub-check-user,s,1(${CALLERID(num)},sales))
Inside the subroutine:
[sub-check-user]
exten => s,1,NoOp(Caller ${ARG1} requested ${ARG2})
same => n,Return()
Argument variables:
- ${ARG1}, ${ARG2}, …
Returning Values from Subroutines
Set a channel variable before Return():
[sub-lookup-agent]
exten => s,1,Set(AGENT=1001)
same => n,Return()
Back in main dialplan:
same => n,Gosub(sub-lookup-agent,s,1)
same => n,Dial(PJSIP/${AGENT},20)
Real-World Example: Centralized Call Recording Setup
[sub-start-recording]
exten => s,1,Set(RECORD_FILE=/var/spool/asterisk/recordings/${UNIQUEID}.wav)
same => n,MixMonitor(${RECORD_FILE})
same => n,Return()
[from-internal]
exten => 2000,1,Gosub(sub-start-recording,s,1)
same => n,Dial(PJSIP/1001,20)
same => n,Hangup()
This ensures every call is recorded consistently.
Using Pre-Dial and Post-Answer Subroutines with Dial()
Modern Asterisk allows subroutines inside Dial():
Dial(PJSIP/1001,20,b(sub-before^s^1)U(sub-after^s^1))
- b() → run before dialing
- U() → run after answer on called channel
Used for:
- Compliance announcements
- Whisper coaching
- AI call tagging
Difference Between Gosub() and Macro() (Legacy Warning)
Older tutorials use:
Macro()
But Macro() is:
- Legacy / deprecated
- Limited recursion support
- Less flexible than Gosub()
Modern Asterisk should always use: Gosub() + Return().
Debugging Subroutines
Use CLI logging:
asterisk -rvvv
core set verbose 5
Add tracing:
NoOp(Entering subroutine)
NoOp(Leaving subroutine)
This quickly shows execution flow.
Common Subroutine Design Patterns
- Call recording initializer
- CRM logging trigger
- Caller blacklist checker
- Business hours validator
- AI bot routing decision
These reusable blocks create enterprise-grade telecom architecture.
Best Practices for Clean Subroutine Architecture
- Keep subroutines short and single-purpose
- Always end with
Return() - Use clear naming like
sub-log,sub-record - Pass arguments instead of using globals
- Centralize common telecom logic
Key Takeaway
Subroutines transform dialplan from a simple script into a modular telecom application framework.
Mastering Gosub(), arguments, return values, and Dial() subroutine hooks is essential for building scalable call centers, AI voice systems, and enterprise-grade Asterisk deployments.
Want to see API-driven CRM + Telecom workflows in action? Try the WhatsApp bot or explore the demos.
Comments (0)
Be the first to comment.