feat: add SMS (Twilio) platform adapter
Add SMS as a first-class messaging platform via the Twilio API. Shares credentials with the existing telephony skill — same TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE_NUMBER env vars. Adapter (gateway/platforms/sms.py): - aiohttp webhook server for inbound (Twilio form-encoded POSTs) - Twilio REST API with Basic auth for outbound - Markdown stripping, smart chunking at 1600 chars - Echo loop prevention, phone number redaction in logs Integration (13 files): - gateway config, run, channel_directory - agent prompt_builder (SMS platform hint) - cron scheduler, cronjob tools - send_message_tool (_send_sms via Twilio API) - toolsets (hermes-sms + hermes-gateway) - gateway setup wizard, status display - pyproject.toml (sms optional extra) - 21 tests Docs: - website/docs/user-guide/messaging/sms.md (full setup guide) - Updated messaging index (architecture, toolsets, security, links) - Updated environment-variables.md reference Inspired by PR #1575 (@sunsakis), rewritten for Twilio.
This commit is contained in:
parent
3d38d85287
commit
07549c967a
16 changed files with 796 additions and 5 deletions
|
|
@ -152,6 +152,14 @@ For native Anthropic auth, Hermes prefers Claude Code's own credential files whe
|
|||
| `SIGNAL_HOME_CHANNEL_NAME` | Display name for the Signal home channel |
|
||||
| `SIGNAL_IGNORE_STORIES` | Ignore Signal stories/status updates |
|
||||
| `SIGNAL_ALLOW_ALL_USERS` | Allow all Signal users without an allowlist |
|
||||
| `TWILIO_ACCOUNT_SID` | Twilio Account SID (shared with telephony skill) |
|
||||
| `TWILIO_AUTH_TOKEN` | Twilio Auth Token (shared with telephony skill) |
|
||||
| `TWILIO_PHONE_NUMBER` | Twilio phone number in E.164 format (shared with telephony skill) |
|
||||
| `SMS_WEBHOOK_PORT` | Webhook listener port for inbound SMS (default: `8080`) |
|
||||
| `SMS_ALLOWED_USERS` | Comma-separated E.164 phone numbers allowed to chat |
|
||||
| `SMS_ALLOW_ALL_USERS` | Allow all SMS senders without an allowlist |
|
||||
| `SMS_HOME_CHANNEL` | Phone number for cron job / notification delivery |
|
||||
| `SMS_HOME_CHANNEL_NAME` | Display name for the SMS home channel |
|
||||
| `EMAIL_ADDRESS` | Email address for the Email gateway adapter |
|
||||
| `EMAIL_PASSWORD` | Password or app password for the email account |
|
||||
| `EMAIL_IMAP_HOST` | IMAP hostname for the email adapter |
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
title: "Messaging Gateway"
|
||||
description: "Chat with Hermes from Telegram, Discord, Slack, WhatsApp, Signal, Email, Home Assistant, or your browser — architecture and setup overview"
|
||||
description: "Chat with Hermes from Telegram, Discord, Slack, WhatsApp, Signal, SMS, Email, Home Assistant, or your browser — architecture and setup overview"
|
||||
---
|
||||
|
||||
# Messaging Gateway
|
||||
|
||||
Chat with Hermes from Telegram, Discord, Slack, WhatsApp, Signal, Email, Home Assistant, or your browser. The gateway is a single background process that connects to all your configured platforms, handles sessions, runs cron jobs, and delivers voice messages.
|
||||
Chat with Hermes from Telegram, Discord, Slack, WhatsApp, Signal, SMS, Email, Home Assistant, or your browser. The gateway is a single background process that connects to all your configured platforms, handles sessions, runs cron jobs, and delivers voice messages.
|
||||
|
||||
For the full voice feature set — including CLI microphone mode, spoken replies in messaging, and Discord voice-channel conversations — see [Voice Mode](/docs/user-guide/features/voice-mode) and [Use Voice Mode with Hermes](/docs/guides/use-voice-mode-with-hermes).
|
||||
|
||||
|
|
@ -21,6 +21,7 @@ flowchart TB
|
|||
wa[WhatsApp]
|
||||
sl[Slack]
|
||||
sig[Signal]
|
||||
sms[SMS]
|
||||
em[Email]
|
||||
ha[Home Assistant]
|
||||
end
|
||||
|
|
@ -35,6 +36,7 @@ flowchart TB
|
|||
wa --> store
|
||||
sl --> store
|
||||
sig --> store
|
||||
sms --> store
|
||||
em --> store
|
||||
ha --> store
|
||||
store --> agent
|
||||
|
|
@ -129,6 +131,7 @@ Configure per-platform overrides in `~/.hermes/gateway.json`:
|
|||
TELEGRAM_ALLOWED_USERS=123456789,987654321
|
||||
DISCORD_ALLOWED_USERS=123456789012345678
|
||||
SIGNAL_ALLOWED_USERS=+155****4567,+155****6543
|
||||
SMS_ALLOWED_USERS=+155****4567,+155****6543
|
||||
EMAIL_ALLOWED_USERS=trusted@example.com,colleague@work.com
|
||||
|
||||
# Or allow
|
||||
|
|
@ -288,6 +291,7 @@ Each platform has its own toolset:
|
|||
| WhatsApp | `hermes-whatsapp` | Full tools including terminal |
|
||||
| Slack | `hermes-slack` | Full tools including terminal |
|
||||
| Signal | `hermes-signal` | Full tools including terminal |
|
||||
| SMS | `hermes-sms` | Full tools including terminal |
|
||||
| Email | `hermes-email` | Full tools including terminal |
|
||||
| Home Assistant | `hermes-homeassistant` | Full tools + HA device control (ha_list_entities, ha_get_state, ha_call_service, ha_list_services) |
|
||||
|
||||
|
|
@ -298,5 +302,6 @@ Each platform has its own toolset:
|
|||
- [Slack Setup](slack.md)
|
||||
- [WhatsApp Setup](whatsapp.md)
|
||||
- [Signal Setup](signal.md)
|
||||
- [SMS Setup (Twilio)](sms.md)
|
||||
- [Email Setup](email.md)
|
||||
- [Home Assistant Integration](homeassistant.md)
|
||||
|
|
|
|||
175
website/docs/user-guide/messaging/sms.md
Normal file
175
website/docs/user-guide/messaging/sms.md
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
---
|
||||
sidebar_position: 8
|
||||
title: "SMS (Twilio)"
|
||||
description: "Set up Hermes Agent as an SMS chatbot via Twilio"
|
||||
---
|
||||
|
||||
# SMS Setup (Twilio)
|
||||
|
||||
Hermes connects to SMS through the [Twilio](https://www.twilio.com/) API. People text your Twilio phone number and get AI responses back — same conversational experience as Telegram or Discord, but over standard text messages.
|
||||
|
||||
:::info Shared Credentials
|
||||
The SMS gateway shares credentials with the optional [telephony skill](/docs/reference/skills-catalog). If you've already set up Twilio for voice calls or one-off SMS, the gateway works with the same `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN`, and `TWILIO_PHONE_NUMBER`.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Twilio account** — [Sign up at twilio.com](https://www.twilio.com/try-twilio) (free trial available)
|
||||
- **A Twilio phone number** with SMS capability
|
||||
- **A publicly accessible server** — Twilio sends webhooks to your server when SMS arrives
|
||||
- **aiohttp** — `pip install 'hermes-agent[sms]'`
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Get Your Twilio Credentials
|
||||
|
||||
1. Go to the [Twilio Console](https://console.twilio.com/)
|
||||
2. Copy your **Account SID** and **Auth Token** from the dashboard
|
||||
3. Go to **Phone Numbers → Manage → Active Numbers** — note your phone number in E.164 format (e.g., `+15551234567`)
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Configure Hermes
|
||||
|
||||
### Interactive setup (recommended)
|
||||
|
||||
```bash
|
||||
hermes gateway setup
|
||||
```
|
||||
|
||||
Select **SMS (Twilio)** from the platform list. The wizard will prompt for your credentials.
|
||||
|
||||
### Manual setup
|
||||
|
||||
Add to `~/.hermes/.env`:
|
||||
|
||||
```bash
|
||||
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
TWILIO_AUTH_TOKEN=your_auth_token_here
|
||||
TWILIO_PHONE_NUMBER=+15551234567
|
||||
|
||||
# Security: restrict to specific phone numbers (recommended)
|
||||
SMS_ALLOWED_USERS=+15559876543,+15551112222
|
||||
|
||||
# Optional: set a home channel for cron job delivery
|
||||
SMS_HOME_CHANNEL=+15559876543
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Configure Twilio Webhook
|
||||
|
||||
Twilio needs to know where to send incoming messages. In the [Twilio Console](https://console.twilio.com/):
|
||||
|
||||
1. Go to **Phone Numbers → Manage → Active Numbers**
|
||||
2. Click your phone number
|
||||
3. Under **Messaging → A MESSAGE COMES IN**, set:
|
||||
- **Webhook**: `https://your-server:8080/webhooks/twilio`
|
||||
- **HTTP Method**: `POST`
|
||||
|
||||
:::tip Exposing Your Webhook
|
||||
If you're running Hermes locally, use a tunnel to expose the webhook:
|
||||
|
||||
```bash
|
||||
# Using cloudflared
|
||||
cloudflared tunnel --url http://localhost:8080
|
||||
|
||||
# Using ngrok
|
||||
ngrok http 8080
|
||||
```
|
||||
|
||||
Set the resulting public URL as your Twilio webhook.
|
||||
:::
|
||||
|
||||
The webhook port defaults to `8080`. Override with:
|
||||
|
||||
```bash
|
||||
SMS_WEBHOOK_PORT=3000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Start the Gateway
|
||||
|
||||
```bash
|
||||
hermes gateway
|
||||
```
|
||||
|
||||
You should see:
|
||||
|
||||
```
|
||||
[sms] Twilio webhook server listening on port 8080, from: +1555***4567
|
||||
```
|
||||
|
||||
Text your Twilio number — Hermes will respond via SMS.
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `TWILIO_ACCOUNT_SID` | Yes | Twilio Account SID (starts with `AC`) |
|
||||
| `TWILIO_AUTH_TOKEN` | Yes | Twilio Auth Token |
|
||||
| `TWILIO_PHONE_NUMBER` | Yes | Your Twilio phone number (E.164 format) |
|
||||
| `SMS_WEBHOOK_PORT` | No | Webhook listener port (default: `8080`) |
|
||||
| `SMS_ALLOWED_USERS` | No | Comma-separated E.164 phone numbers allowed to chat |
|
||||
| `SMS_ALLOW_ALL_USERS` | No | Set to `true` to allow anyone (not recommended) |
|
||||
| `SMS_HOME_CHANNEL` | No | Phone number for cron job / notification delivery |
|
||||
| `SMS_HOME_CHANNEL_NAME` | No | Display name for the home channel (default: `Home`) |
|
||||
|
||||
---
|
||||
|
||||
## SMS-Specific Behavior
|
||||
|
||||
- **Plain text only** — Markdown is automatically stripped since SMS renders it as literal characters
|
||||
- **1600 character limit** — Longer responses are split across multiple messages at natural boundaries (newlines, then spaces)
|
||||
- **Echo prevention** — Messages from your own Twilio number are ignored to prevent loops
|
||||
- **Phone number redaction** — Phone numbers are redacted in logs for privacy
|
||||
|
||||
---
|
||||
|
||||
## Security
|
||||
|
||||
**The gateway denies all users by default.** Configure an allowlist:
|
||||
|
||||
```bash
|
||||
# Recommended: restrict to specific phone numbers
|
||||
SMS_ALLOWED_USERS=+15559876543,+15551112222
|
||||
|
||||
# Or allow all (NOT recommended for bots with terminal access)
|
||||
SMS_ALLOW_ALL_USERS=true
|
||||
```
|
||||
|
||||
:::warning
|
||||
SMS has no built-in encryption. Don't use SMS for sensitive operations unless you understand the security implications. For sensitive use cases, prefer Signal or Telegram.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Messages not arriving
|
||||
|
||||
1. Check your Twilio webhook URL is correct and publicly accessible
|
||||
2. Verify `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` are correct
|
||||
3. Check the Twilio Console → **Monitor → Logs → Messaging** for delivery errors
|
||||
4. Ensure your phone number is in `SMS_ALLOWED_USERS` (or `SMS_ALLOW_ALL_USERS=true`)
|
||||
|
||||
### Replies not sending
|
||||
|
||||
1. Check `TWILIO_PHONE_NUMBER` is set correctly (E.164 format with `+`)
|
||||
2. Verify your Twilio account has SMS-capable numbers
|
||||
3. Check Hermes gateway logs for Twilio API errors
|
||||
|
||||
### Webhook port conflicts
|
||||
|
||||
If port 8080 is already in use, change it:
|
||||
|
||||
```bash
|
||||
SMS_WEBHOOK_PORT=3001
|
||||
```
|
||||
|
||||
Update the webhook URL in Twilio Console to match.
|
||||
Loading…
Add table
Add a link
Reference in a new issue