mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-18 04:41:56 +00:00
Cross-checked 75 docs pages under user-guide/messaging/, developer-guide/,
guides/, and integrations/ against the live registries and gateway code.
messaging/
- index.md: API Server toolset is hermes-api-server (was 'hermes (default)');
Google Chat slug is hermes-google_chat (underscore — plugin name uses _).
- google_chat.md: drop bogus 'pip install hermes-agent[google_chat]' (no such
extra); list the actual deps (google-cloud-pubsub, google-api-python-client,
google-auth, google-auth-oauthlib).
- qqbot.md: config namespace is platforms.qqbot (was platforms.qq, which is
silently ignored by the adapter); QQ_STT_BASE_URL is not read directly —
baseUrl lives under platforms.qqbot.extra.stt.
- teams-meetings.md: 'hermes teams-pipeline' is plugin-gated (teams_pipeline
plugin must be enabled), not a built-in subcommand.
- sms.md: example log line 0.0.0.0:8080 -> 127.0.0.1:8080 (default
SMS_WEBHOOK_HOST).
- open-webui.md: API_SERVER_* are env vars, not YAML keys — write them to
per-profile .env, not 'hermes config set' (same pattern fixed in
api-server.md last round). Also bumped example ports to 8650+ to dodge the
default webhook (8644)/wecom-callback (8645)/msgraph-webhook (8646)
collision.
developer-guide/
- architecture.md: tool/toolset counts (61/52 -> 70+/~28); LOC stamps for
run_agent.py, cli.py, hermes_cli/main.py, setup.py, mcp_tool.py,
gateway/run.py replaced with 'large file' to stop drifting.
- agent-loop.md: same LOC drift (~13,700 -> 'a large file (15k+ lines)').
- gateway-internals.md: '14+ external messaging platforms' -> '20+'; gateway
platform tree updated (qqbot is a sub-package, not qqbot.py; added
yuanbao.py, feishu_comment.py, msgraph_webhook.py); 'gateway/builtin_hooks/
(always active)' was wrong — it's an empty extension point and
_register_builtin_hooks() is a no-op stub.
- acp-internals.md: drop fictional 'message_callback' from the bridged-
callbacks list; clarify thinking_callback is currently set to None.
- provider-runtime.md: provider list was missing AWS Bedrock, Azure Foundry,
NVIDIA NIM, xAI, Arcee, GMI Cloud, StepFun, Qwen OAuth, Xiaomi, Ollama
Cloud, LM Studio, Tencent TokenHub. Fallback section described only the
legacy single-pair model — corrected to the canonical list-form
fallback_providers chain.
- environments.md: parsers list missing llama4_json and the deepseek_v31
alias; both register via @register_parser.
- browser-supervisor.md: drop reference to scripts/browser_supervisor_e2e.py
which doesn't exist in-repo.
- contributing.md: tinker-atropos is a git submodule — note that
'git submodule update --init' is required if cloning without
--recurse-submodules.
guides/
- operate-teams-meeting-pipeline.md: cron flags were all wrong — schedule is
positional (not --schedule), the script-only flag is --no-agent (not
--script-only), and there's no --command flag. Replaced with a real example
that creates the script under ~/.hermes/scripts/ and uses the actual flags.
Also replaced fictional 'hermes cron show <name>' with 'hermes cron status'.
- automation-templates.md: 'cron create --skills "a,b"' doesn't work —
the flag is --skill (singular, repeatable). Fixed all 5 occurrences via AST
rewrite.
- minimax-oauth.md: 'hermes auth add minimax-oauth --region cn' silently
fails because --region isn't registered on the auth-add argparse spec.
Pointed users at the minimax-cn provider (or MINIMAX_CN_API_KEY env) for
China-region access.
- cron-script-only.md: 'hermes send' is fictional — replaced the comparison-
table mention with a webhook-subscription pointer; also fixed the dead link
to /guides/pipe-script-output (page doesn't exist).
- cron-troubleshooting.md: 'hermes serve' isn't a real subcommand. Pointed
at 'hermes gateway' (foreground) / 'hermes gateway start' (service).
- local-ollama-setup.md: 'agent.api_timeout' is not a config key. The right
knob is the HERMES_API_TIMEOUT env var.
- python-library.md: run_conversation() return dict has only final_response
and messages — task_id is stored on the agent instance, not echoed back.
- use-mcp-with-hermes.md: '--args /c "npx -y …"' wraps the npx command in
one quoted string, so cmd.exe gets a single arg instead of the multi-token
command line it needs. Removed the surrounding quotes — argparse nargs='*'
collects each token correctly.
integrations/
- providers.md: Bedrock guardrail YAML keys were 'id'/'version' (don't exist);
actual keys are guardrail_identifier/guardrail_version (matches DEFAULT_CONFIG
and the run_agent.py reader). GMI default base URL (api.gmi.ai/v1 ->
api.gmi-serving.com/v1) and portal URL (inference.gmi.ai -> www.gmicloud.ai)
refreshed. Fallback section rewritten to lead with the canonical
fallback_providers list form (was leading with the legacy fallback_model
single dict); supported-providers list extended to include azure-foundry,
alibaba-coding-plan, lmstudio.
index.md
- '68 built-in tools' -> '70+'; '15+ platforms' was both inconsistent with
integrations/index.md ('19+') and undercounted — bumped to 20+ and added
Weixin/QQ Bot/Yuanbao/Google Chat to the list.
Validation: 'npm run build' clean (exit 0); broken-link count unchanged at
155 (same as round-1 post-skill-regen baseline). 24 files, +132/-89.
203 lines
6.4 KiB
Markdown
203 lines
6.4 KiB
Markdown
---
|
|
sidebar_position: 8
|
|
sidebar_label: "SMS (Twilio)"
|
|
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.
|
|
:::
|
|
|
|
**Set `SMS_WEBHOOK_URL` to the same URL you configured in Twilio.** This is required for Twilio signature validation — the adapter will refuse to start without it:
|
|
|
|
```bash
|
|
# Must match the webhook URL in your Twilio Console
|
|
SMS_WEBHOOK_URL=https://your-server:8080/webhooks/twilio
|
|
```
|
|
|
|
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 127.0.0.1:8080, from: +1555***4567
|
|
```
|
|
|
|
If you see `Refusing to start: SMS_WEBHOOK_URL is required`, set `SMS_WEBHOOK_URL` to the public URL configured in your Twilio Console (see Step 3).
|
|
|
|
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 (also used for webhook signature validation) |
|
|
| `TWILIO_PHONE_NUMBER` | Yes | Your Twilio phone number (E.164 format) |
|
|
| `SMS_WEBHOOK_URL` | Yes | Public URL for Twilio signature validation — must match the webhook URL in your Twilio Console |
|
|
| `SMS_WEBHOOK_PORT` | No | Webhook listener port (default: `8080`) |
|
|
| `SMS_WEBHOOK_HOST` | No | Webhook bind address (default: `0.0.0.0`) |
|
|
| `SMS_INSECURE_NO_SIGNATURE` | No | Set to `true` to disable signature validation (local dev only — **not for production**) |
|
|
| `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
|
|
|
|
### Webhook signature validation
|
|
|
|
Hermes validates that inbound webhooks genuinely originate from Twilio by verifying the `X-Twilio-Signature` header (HMAC-SHA1). This prevents attackers from injecting forged messages.
|
|
|
|
**`SMS_WEBHOOK_URL` is required.** Set it to the public URL configured in your Twilio Console. The adapter will refuse to start without it.
|
|
|
|
For local development without a public URL, you can disable validation:
|
|
|
|
```bash
|
|
# Local dev only — NOT for production
|
|
SMS_INSECURE_NO_SIGNATURE=true
|
|
```
|
|
|
|
### User allowlists
|
|
|
|
**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.
|