SWML connect Verb
connect bridges the active call to one or more destinations. Destinations can be PSTN numbers (E.164), SIP URIs, or a mix. This is the verb that powers call forwarding, hunt groups, ring-all groups, and every BYO SIP integration.
Simplest case — forward to a phone
version: 1.0.0
sections:
main:
- connect:
to: "+15555551234"
Inbound call is answered (implicitly) and bridged to +15555551234. The caller stays on the line until the destination hangs up.
Preserving caller ID
By default the inbound caller's number is forwarded. To override (for example to spoof your own DID), set from:
- connect:
from: "+15559876543"
to: "+15555551234"
Caller ID rules apply: from must be a verified or owned number on your project.
Sequential dialing (hunt group)
Pass an array of destinations. The list is dialed in order, top to bottom, until one answers.
- connect:
to:
- "+15555550101"
- "+15555550102"
- "+15555550103"
timeout: 20 # seconds per destination
Total ring time is timeout * len(to). Use a short timeout (15-20s) to avoid making the caller wait through three full timeouts.
Simultaneous dialing (ring all)
Wrap each leg in a [ ... ] inner array. All inner items ring at the same time; first to answer wins.
- connect:
to:
- ["+15555550101", "+15555550102", "+15555550103"]
timeout: 25
The outer list is sequential, the inner list is parallel. So [[a, b], c] means "ring a and b together; if neither answers in timeout, ring c."
SIP URI destinations
A SIP destination uses the sip: prefix.
- connect:
to: "sip:agent42@your-pbx.example.com"
Add ;transport=tcp or ;transport=tls when required by the receiving endpoint.
- connect:
to: "sip:%{call.to}@your-livekit-domain.com;transport=tcp"
%{call.to} substitutes the dialed DID so the receiving platform can route by called-number.
answer_on_bridge — delay answer until callee picks up
Default behaviour is to answer the inbound call immediately. With answer_on_bridge: true, SignalWire keeps the inbound leg ringing on the caller's side until the callee answers, then bridges. The caller hears ringing instead of dead air, and billing starts only when the callee picks up.
- connect:
answer_on_bridge: true
from: "+15559876543"
to: "+15555551234"
Use it for any plain forwarding scenario. Required for clean outbound-from-AI-platform setups where the receiving side expects ringback.
Whisper — play audio to the callee before they hear the caller
whisper makes SignalWire play a private prompt or SWML script to the answering party before the bridge completes. Useful for screening, recording warnings, or announcing the source of the call.
- connect:
to: "+15555551234"
whisper:
url: "say:Incoming call from a new lead. Press 1 to accept."
whisper.url can be a hosted audio file, a say: TTS string, or another SWML document URL.
confirm — secondary SWML before bridging
confirm runs a separate SWML doc against the callee leg before the bridge. Common pattern: start recording, log to your CRM, or whisper a prompt.
# record-helper.yaml
version: 1.0.0
sections:
main:
- record_call: { stereo: true, format: mp3 }
# main.yaml
version: 1.0.0
sections:
main:
- connect:
answer_on_bridge: true
from: "+15559876543"
to: "+15555551234"
confirm: "https://your.api/record-helper.yaml"
BYO-trunk patterns
Two patterns dominate BYO integration setups (VAPI, LiveKit, Bland, Retell):
Inbound: PSTN → AI platform
version: 1.0.0
sections:
main:
- connect:
to: "sip:%{call.to}@your-credential-id.sip.vapi.ai"
Outbound: AI platform → PSTN (assigned to a SIP Address)
version: 1.0.0
sections:
main:
- connect:
answer_on_bridge: true
from: "+15555551234"
to: "%{call.to.replace(/^sip:/i, '').replace(/@.*/, '')}"
The to expression strips the sip: prefix and @domain suffix so the value is clean E.164. Full BYO setup details: VAPI BYO and LiveKit BYO.
connect parameters reference
| Parameter | Notes |
|---|---|
| to | string or array — destination(s). Required. |
| from | string — override outbound caller ID. |
| timeout | int — seconds to ring each destination. Default 30. |
| answer_on_bridge | bool — keep ringback to inbound caller until bridge. |
| confirm | string — URL of secondary SWML to run against callee. |
| whisper | object — url (audio/say:/SWML URL) and optional terminators. |
| headers | object — custom SIP headers (SIP destinations only). |
| codecs | string — comma-separated codec preference list (G.722, G.711, Opus). |
| webrtc_media | bool — force WebRTC media path. |
| session_timeout | int — max bridge duration in seconds. |
Anti-patterns
- Forgetting
answer_on_bridge: trueon outbound BYO trunk scripts — caller hears dead air. - Hardcoding internal IPs as SIP destinations — always use a hostname so SignalWire's resolver finds the right edge.
- Long
timeout(60s+) on sequential dialing — multiplies the caller's wait. - Using one giant SIP URI string instead of headers — custom headers go in
headers, not appended to the URI. - Connecting to a SIP URI without
;transport=tcpwhen the receiver requires it (LiveKit inbound especially).