ADR-0079implemented

Telnyx Voice & SMS Notification Channel

Context

joelclaw needed outbound notification beyond Telegram — a way to phone-call or text Joel when time-sensitive work completes. The system already had:

  • Telegram bot for async text/media
  • Todoist for task-based Q&A
  • Gateway for event delivery

None of these interrupt. A phone call does.

Decision

Use Telnyx as the outbound voice and SMS provider via their REST API v2.

Why Telnyx (not Twilio)

  • Already configured: SIP connection (joelclaw-livekit-sip), OVP, phone number (+13606051697) provisioned for LiveKit SIP bridge (ADR-0043)
  • TeXML support for TTS calls without webhook infrastructure
  • SMS on the same number (if enabled)
  • Cheaper than Twilio for low-volume

Architecture

joelclaw call "message"
  → notification/call.requested event
    → telnyx-notify Inngest function
      → step: place TeXML TTS call
      → step: wait 30s
      → step: check call status
      → step: if unanswered → send SMS fallback

Components

FilePurpose
packages/system-bus/src/lib/telnyx.tsAPI client (placeCall, sendSMS, checkSMSEnabled, getCall)
packages/system-bus/src/inngest/functions/telnyx-notify.tsDurable call→SMS flow
packages/cli/src/commands/call.tsjoelclaw call "message" CLI

Secrets

NamePurpose
telnyx_api_keyAPI authentication
telnyx_connection_idSIP connection for calls
telnyx_phone_numberFROM number
telnyx_ovp_idOutbound voice profile
joel_phone_numberTO number (+18176756031)

Security

  • Joel’s phone is the only allowed destination (caller allowlist already configured on Telnyx side)
  • Secrets leased via agent-secrets CLI with env var fallback
  • OVP whitelisted to US/CA only

Consequences

  • System can now interrupt Joel for urgent completions
  • SMS fallback ensures delivery even if call is missed
  • TeXML means no webhook server needed for TTS
  • Future: could add inbound call handling (already have LiveKit SIP bridge)