SIP outbound dial provider for the R18 (#561) voice channel — alternative to the Twilio Programmable Voice impl in R18.1 (#532), for businesses that already have SIP infrastructure (PBX, SIP trunks, cloud SIP providers like Sonetel / Voxbone / Sonus).
Why this is a separate provider
- Business reality: many enterprises already pay for SIP trunks and PBX systems. Sending outbound voice through Twilio means duplicate capacity + duplicate billing. SIP integration uses what's already there.
- Per-minute economics: SIP trunks often beat Twilio's rates for high-volume outbound (sales-call agents, notification fleets, debt-collection robocalls).
- Compliance / data residency: some EU customers prefer SIP through a local provider over US-anchored Twilio infrastructure.
- Different lifecycle and auth (registrar URL, SIP user/password or client certs vs Twilio API tokens) — peer implementation, not a refinement of R18.1.
Acceptance criteria
- Implements the same outbound-dial interface as the Twilio provider (R18.1 / #532). Skill code calling
dial(agent_id, e164_number) should not need to know which provider answers.
- Auth via SIP credentials in the encrypted runtime secret store (registrar URL, SIP user/password OR client cert).
dial() initiates a SIP INVITE through the registered trunk to the given E.164 number; returns a call_id.
- Cost recorded in
UsageTotals (per-minute or per-call basis depending on operator's SIP contract).
- TTS pipeline reuse (R18.2 / #533) and STT for callee responses (R18.3 / #534) work the same way through SIP audio streams (RTP).
- Audit-log entries (R18.5 / #536) —
voice.call.start, voice.call.end — emitted with SIP-specific call IDs (Call-ID header).
- Unit tests using a SIP mock (e.g.
sipp or a mocked SIP client library).
- Operator docs covering SIP trunk setup, common providers (FreeSWITCH / Asterisk / cloud SIP), TLS-SRTP for encrypted calls.
Depends on
- R18.1 (#532) Twilio outbound dial — primarily to define the
dial() interface contract
- R18.2 (#533) TTS pipeline reuse, R18.3 (#534) STT for callee responses
Out of scope (future tickets)
- Inbound SIP (agent receives calls from a SIP trunk) — different scope, would be tracked under R18 or as a new R-item once outbound is shipped.
- WebRTC as a transport — different protocol family; can be a peer to SIP later.
Priority
P2 — same priority as the rest of R18 (channel expansion, not core wedge), but enables B2B-grade voice deployments that Twilio alone doesn't cover well.
SIP outbound dial provider for the R18 (#561) voice channel — alternative to the Twilio Programmable Voice impl in R18.1 (#532), for businesses that already have SIP infrastructure (PBX, SIP trunks, cloud SIP providers like Sonetel / Voxbone / Sonus).
Why this is a separate provider
Acceptance criteria
dial(agent_id, e164_number)should not need to know which provider answers.dial()initiates a SIP INVITE through the registered trunk to the given E.164 number; returns acall_id.UsageTotals(per-minute or per-call basis depending on operator's SIP contract).voice.call.start,voice.call.end— emitted with SIP-specific call IDs (Call-ID header).sippor a mocked SIP client library).Depends on
dial()interface contractOut of scope (future tickets)
Priority
P2 — same priority as the rest of R18 (channel expansion, not core wedge), but enables B2B-grade voice deployments that Twilio alone doesn't cover well.