gateways/ - Twilio SMS
Webhook-driven push-style gateway - form-urlencoded, HMAC-SHA1 signatures, dual-path TwiML response.
Twilio SMS
Part of the push-style gateways/ family - see there for the shared "secrets stay external" rule, GatewaySession, and the scheduler these gateways run under. This page covers Twilio SMS's own config shape and (where BxAgents does anything platform-specific) how it talks to Twilio SMS.
// gateways/twilioChannel.bx
class {
function configure() {
return {
type : "twilio",
accountSidEnvVar: "TWILIO_ACCOUNT_SID",
authTokenEnvVar : "TWILIO_AUTH_TOKEN", // also the X-Twilio-Signature HMAC key
fromEnvVar : "TWILIO_FROM_NUMBER" // the Twilio phone number outbound sends go through, E.164
// messagingServiceSid: "MG..." // optional - if set, used instead of `from` on outbound sends
// publicUrl: "https://your-real-public-host/webhooks/twilio" // optional override for reverse-proxy/tunnel deployments - see the Twilio subsection below
};
}
}
Validation: type: "twilio" requires accountSidEnvVar, authTokenEnvVar, and fromEnvVar. Checked the same way a channel-adapter http entry's secretEnvVar is.
Generated registration statement:
aiGatewayRegistry().register( aiGateway( "bxModules.bxagents.models.gateways.TwilioGateway", { "accountSid" : getSystemSetting( "TWILIO_ACCOUNT_SID", "" ), "authToken" : getSystemSetting( "TWILIO_AUTH_TOKEN", "" ), "from" : getSystemSetting( "TWILIO_FROM_NUMBER", "" ) } ) )
Twilio SMS - a genuinely different signature scheme, and a dual-path response model
TwilioGateway is webhook-driven the same way WhatsAppCloudGateway/TeamsGateway are:
post( "/webhooks/twilio" ).toHandler( "Twilio.process" )
Two things make Twilio's own webhook contract meaningfully different from every other gateway in this project, both ported faithfully from Vercel Eve's real Twilio channel (packages/eve/src/public/channels/twilio/, MIT licensed):
- The inbound body is form-urlencoded (
Body,From,To,MessageSid,AccountSid), not JSON -TwilioGatewayparses it itself (java.net.URLDecoder), no JSON deserialization involved. - Signature verification is
X-Twilio-Signature: HMAC-SHA1, base64-encoded (every other webhook gateway in this project uses HMAC-SHA256, hex-encoded) - the signing base is the exact request URL followed by every POST param's ownkey & valueconcatenated directly (no separators), sorted alphabetically by key. Because the URL itself is part of what's signed, a project running behind a reverse proxy or tunnel (where the URL ColdBox sees viaevent.getUrl()doesn't match what Twilio actually POSTed to) needs the optionalpublicUrlconfig override - the same class of gotcha Eve's own docs flag for itswebhookUrloption. - The synchronous webhook response is always an empty TwiML
<Response></Response>- Twilio's own classic dual-path model. The real agent reply is sent later, out-of-band, via a separatedeliver()REST call to the Messages API once GatewaySession's async turn completes - matching Eve's ownemptyTwilioResponse()exactly (Eve never uses a synchronous TwiML<Message>to answer inline).
Outbound sends are Basic-Auth REST calls to POST /2010-04-01/Accounts/{AccountSid}/Messages.json, form-encoded body (To, Body, and either From or MessagingServiceSid if configured). v1 is SMS-text only - Eve's own Twilio channel is a combined SMS+voice channel (/voice routes, <Gather>/<Say> TwiML, call transcription); none of the voice-specific pieces were ported.
SMS has no native button/card affordance at all (confirmed via Eve's own docs), so human-in-the-loop is degraded the same way Email's is - getDeclaredCapabilities() omits "interactiveActions" (and "threads", since Twilio's classic Messages API has no native reply/quote concept either). requestHumanInteraction() sends a plain-text SMS listing the allowed decisions; unlike Email (which embeds a [bxagents:<requestID>] tag in the Subject line to correlate the eventual reply), SMS has no subject line to tag - so the pending request is keyed by the sender's own phone number (conversationID) instead, a v1 simplification that assumes at most one open HITL request per phone number at a time.
Unlike Eve (which has no length-limiting logic at all - confirmed absent by grepping its source - and relies entirely on Twilio's own server-side segmentation), TwilioGateway still applies MessageChunker at 1600 chars (Twilio's own documented single-message concatenation ceiling) for consistency with every other gateway's chunking behavior. The HMAC-SHA1 signature scheme was cross-verified this session against an independently computed Python hmac/hashlib reference value before trusting the BoxLang implementation, the same discipline used for WhatsApp Cloud's own HMAC-SHA256 scheme.