Skip to content

twilio-sms (Go)

hum by text message — Twilio SMS webhook nestling

Built in Go with the stdlib net/http. Imports the clients/go/thrum reference client. The canonical Go bee in this repo.

A bee that turns a Twilio phone number into a hum agent. Send an SMS to your Twilio number → Twilio POSTs to this bee → the message becomes a chi:"prompt" to humd → humd’s reply comes back as TwiML so Twilio answers inline.

Same conversation continues across messages from the same phone number (sid = sha256(“twilio-sms:From”)[..16] — stable per remote).

Propensity

statefulnessrichnesswire shapehides
stateful (per-phone sid)leanTwilio Messaging webhooktools, system prompts, perf, drone, breath

Wire

phone user ──SMS──► Twilio ──POST /sms──► twilio-sms ──chi:prompt──► humd
phone user ◄──SMS── Twilio ◄──TwiML <Response>── twilio-sms ◄──chi:finish─┘

Configure Twilio

In your Twilio console:

  1. Buy / select a phone number with SMS capability.
  2. Under Messaging → Configuration, set:
    • A MESSAGE COMES IN: Webhook
    • URL: https://<your-public-host>/sms (must be reachable; for dev, point a tunnel like cloudflared or ngrok at your laptop)
    • HTTP: POST

You also need humd reachable from the same machine that runs this bee (its thrum socket is local-only by default — that’s fine, the bee itself terminates the SMS, hum stays private).

Configure (this bee)

envdefaultwhat
HUM_TWILIO_PORT14623HTTP listen port
HUM_TWILIO_HOST0.0.0.0HTTP listen host
HUM_TWILIO_MODELclaude-haiku-4.5model the daemon spawns
HUM_TWILIO_SYSTEMterse SMS-friendly system promptsystem instruction prepended to every turn
HUM_TWILIO_REPLY_LIMIT1500hard cap on reply length (Twilio caps long-form SMS)
TWILIO_AUTH_TOKEN(unset)reserved — signature verification not yet implemented
HUM_THRUM_SOCK$XDG_RUNTIME_DIR/hum/thrum.sockhumd’s NDJSON socket

Run

Terminal window
cd hives/twilio-sms
go run .
# Custom port:
HUM_TWILIO_PORT=8080 go run .

Smoke test without Twilio:

Terminal window
curl -X POST http://localhost:14623/sms \
-d "From=%2B14155551234" \
-d "To=%2B18005550000" \
-d "Body=ping"

You’ll get a TwiML response back — same shape Twilio gets.

What flows where

Twilio webhook fieldhum chi field
From (phone number)prompt.ext["twilio-sms"].from + sid seed
To (your number)prompt.ext["twilio-sms"].to
Body (the text)prompt.text
MessageSidrid
daemon’s chi:"chunk" text parts (collected)TwiML <Message> body
daemon’s chi:"finish"response sent

What it doesn’t do

  • No signature verification yet. Reserved env (TWILIO_AUTH_TOKEN) will be wired to HMAC-SHA1 verification per Twilio docs. Today: trust the network path. Don’t expose to the open internet without verification.
  • No async / long-reply path. Twilio’s inline webhook deadline is ~15s; replies that take longer than that timeout will still complete on humd’s side but won’t reach the user. A future revision can send via Twilio REST API (Account SID + Auth Token required) for async.
  • No MMS / images. Inbound media URLs are ignored. Future revision could pass them through as petal-cell attachments.
  • No outbound-initiated chat. This bee only answers; humd doesn’t push unsolicited messages to phone numbers.

See also