SKILL.md
SKILL.mdBrowse 2 files
3,113 tokens
12,796 bytes
Token encoding: o200k_base
Snapshot 24fd22b
1---2name: telephony3description: Provision Twilio numbers, SMS/MMS, and AI outbound calls.4version: 1.0.05author: Nous Research6license: MIT7platforms: [linux, macos, windows]8metadata:9 hermes:10 tags: [telephony, phone, sms, mms, voice, twilio, bland.ai, vapi, calling, texting]11 related_skills: [maps, google-workspace, agentmail]12 category: productivity13---14 15# Telephony — Numbers, Calls, and Texts without Core Tool Changes16 17This optional skill gives Hermes practical phone capabilities while keeping telephony out of the core tool list.18 19It ships with a helper script, `scripts/telephony.py`, that can:20- save provider credentials into `${HERMES_HOME:-~/.hermes}/.env`21- search for and buy a Twilio phone number22- remember that owned number for later sessions23- send SMS / MMS from the owned number24- poll inbound SMS for that number with no webhook server required25- make direct Twilio calls using TwiML `<Say>` or `<Play>`26- import the owned Twilio number into Vapi27- place outbound AI calls through Bland.ai or Vapi28 29## What this solves30 31This skill is meant to cover the practical phone tasks users actually want:32- outbound calls33- texting34- owning a reusable agent number35- checking messages that arrive to that number later36- preserving that number and related IDs between sessions37- future-friendly telephony identity for inbound SMS polling and other automations38 39It does **not** turn Hermes into a real-time inbound phone gateway. Inbound SMS is handled by polling the Twilio REST API. That is enough for many workflows, including notifications and some one-time-code retrieval, without adding core webhook infrastructure.40 41## Safety rules — mandatory42 431. Always confirm before placing a call or sending a text.442. Never dial emergency numbers.453. Never use telephony for harassment, spam, impersonation, or anything illegal.464. Treat third-party phone numbers as sensitive operational data:47 - do not save them to Hermes memory48 - do not include them in skill docs, summaries, or follow-up notes unless the user explicitly wants that495. It is fine to persist the **agent-owned Twilio number** because that is part of the user's configuration.506. VoIP numbers are **not guaranteed** to work for all third-party 2FA flows. Use with caution and set user expectations clearly.51 52## Decision tree — which service to use?53 54Use this logic instead of hardcoded provider routing:55 56### 1) "I want Hermes to own a real phone number"57Use **Twilio**.58 59Why:60- easiest path to buying and keeping a number61- best SMS / MMS support62- simplest inbound SMS polling story63- cleanest future path to inbound webhooks or call handling64 65Use cases:66- receive texts later67- send deployment alerts / cron notifications68- maintain a reusable phone identity for the agent69- experiment with phone-based auth flows later70 71### 2) "I only need the easiest outbound AI phone call right now"72Use **Bland.ai**.73 74Why:75- quickest setup76- one API key77- no need to first buy/import a number yourself78 79Tradeoff:80- less flexible81- voice quality is decent, but not the best82 83### 3) "I want the best conversational AI voice quality"84Use **Twilio + Vapi**.85 86Why:87- Twilio gives you the owned number88- Vapi gives you better conversational AI call quality and more voice/model flexibility89 90Recommended flow:911. Buy/save a Twilio number922. Import it into Vapi933. Save the returned `VAPI_PHONE_NUMBER_ID`944. Use `ai-call --provider vapi`95 96### 4) "I want to call with a custom prerecorded voice message"97Use **Twilio direct call** with a public audio URL.98 99Why:100- easiest way to play a custom MP3101- pairs well with Hermes `text_to_speech` plus a public file host or tunnel102 103## Files and persistent state104 105The skill persists telephony state in two places:106 107### `${HERMES_HOME:-~/.hermes}/.env`108Used for long-lived provider credentials and owned-number IDs, for example:109- `TWILIO_ACCOUNT_SID`110- `TWILIO_AUTH_TOKEN`111- `TWILIO_PHONE_NUMBER`112- `TWILIO_PHONE_NUMBER_SID`113- `BLAND_API_KEY`114- `VAPI_API_KEY`115- `VAPI_PHONE_NUMBER_ID`116- `PHONE_PROVIDER` (AI call provider: bland or vapi)117 118### `~/.hermes/telephony_state.json`119Used for skill-only state that should survive across sessions, for example:120- remembered default Twilio number / SID121- remembered Vapi phone number ID122- last inbound message SID/date for inbox polling checkpoints123 124This means:125- the next time the skill is loaded, `diagnose` can tell you what number is already configured126- `twilio-inbox --since-last --mark-seen` can continue from the previous checkpoint127 128## Locate the helper script129 130After installing this skill, locate the script like this:131 132```bash133SCRIPT="$(find ~/.hermes/skills -path '*/telephony/scripts/telephony.py' -print -quit)"134```135 136If `SCRIPT` is empty, the skill is not installed yet.137 138## Install139 140This is an official optional skill, so install it from the Skills Hub:141 142```bash143hermes skills search telephony144hermes skills install official/productivity/telephony145```146 147## Provider setup148 149### Twilio — owned number, SMS/MMS, direct calls, inbound SMS polling150 151Sign up at:152- https://www.twilio.com/try-twilio153 154Then save credentials into Hermes:155 156```bash157python "$SCRIPT" save-twilio ACXXXXXXXXXXXXXXXXXXXXXXXXXXXX your_auth_token_here158```159 160Search for available numbers:161 162```bash163python "$SCRIPT" twilio-search --country US --area-code 702 --limit 5164```165 166Buy and remember a number:167 168```bash169python "$SCRIPT" twilio-buy "+17025551234" --save-env170```171 172List owned numbers:173 174```bash175python "$SCRIPT" twilio-owned176```177 178Set one of them as the default later:179 180```bash181python "$SCRIPT" twilio-set-default "+17025551234" --save-env182# or183python "$SCRIPT" twilio-set-default PNXXXXXXXXXXXXXXXXXXXXXXXXXXXX --save-env184```185 186### Bland.ai — easiest outbound AI calling187 188Sign up at:189- https://app.bland.ai190 191Save config:192 193```bash194python "$SCRIPT" save-bland your_bland_api_key --voice mason195```196 197### Vapi — better conversational voice quality198 199Sign up at:200- https://dashboard.vapi.ai201 202Save the API key first:203 204```bash205python "$SCRIPT" save-vapi your_vapi_api_key206```207 208Import your owned Twilio number into Vapi and persist the returned phone number ID:209 210```bash211python "$SCRIPT" vapi-import-twilio --save-env212```213 214If you already know the Vapi phone number ID, save it directly:215 216```bash217python "$SCRIPT" save-vapi your_vapi_api_key --phone-number-id vapi_phone_number_id_here218```219 220## Diagnose current state221 222At any time, inspect what the skill already knows:223 224```bash225python "$SCRIPT" diagnose226```227 228Use this first when resuming work in a later session.229 230## Common workflows231 232### A. Buy an agent number and keep using it later233 2341. Save Twilio credentials:235```bash236python "$SCRIPT" save-twilio AC... auth_token_here237```238 2392. Search for a number:240```bash241python "$SCRIPT" twilio-search --country US --area-code 702 --limit 10242```243 2443. Buy it and save it into `${HERMES_HOME:-~/.hermes}/.env` + state:245```bash246python "$SCRIPT" twilio-buy "+17025551234" --save-env247```248 2494. Next session, run:250```bash251python "$SCRIPT" diagnose252```253This shows the remembered default number and inbox checkpoint state.254 255### B. Send a text from the agent number256 257```bash258python "$SCRIPT" twilio-send-sms "+15551230000" "Your deployment completed successfully."259```260 261With media:262 263```bash264python "$SCRIPT" twilio-send-sms "+15551230000" "Here is the chart." --media-url "https://example.com/chart.png"265```266 267### C. Check inbound texts later with no webhook server268 269Poll the inbox for the default Twilio number:270 271```bash272python "$SCRIPT" twilio-inbox --limit 20273```274 275Only show messages that arrived after the last checkpoint, and advance the checkpoint when you're done reading:276 277```bash278python "$SCRIPT" twilio-inbox --since-last --mark-seen279```280 281This is the main answer to “how do I access messages the number receives next time the skill is loaded?”282 283### D. Make a direct Twilio call with built-in TTS284 285```bash286python "$SCRIPT" twilio-call "+15551230000" --message "Hello! This is Hermes calling with your status update." --voice Polly.Joanna287```288 289### E. Call with a prerecorded / custom voice message290 291This is the main path for reusing Hermes's existing `text_to_speech` support.292 293Use this when:294- you want the call to use Hermes's configured TTS voice rather than Twilio `<Say>`295- you want a one-way voice delivery (briefing, alert, joke, reminder, status update)296- you do **not** need a live conversational phone call297 298Generate or host audio separately, then:299 300```bash301python "$SCRIPT" twilio-call "+155****0000" --audio-url "https://example.com/briefing.mp3"302```303 304Recommended Hermes TTS -> Twilio Play workflow:305 3061. Generate the audio with Hermes `text_to_speech`.3072. Make the resulting MP3 publicly reachable.3083. Place the Twilio call with `--audio-url`.309 310Example agent flow:311- Ask Hermes to create the message audio with `text_to_speech`312- If needed, expose the file with a temporary static host / tunnel / object storage URL313- Use `twilio-call --audio-url ...` to deliver it by phone314 315Good hosting options for the MP3:316- a temporary public object/storage URL317- a short-lived tunnel to a local static file server318- any existing HTTPS URL the phone provider can fetch directly319 320Important note:321- Hermes TTS is great for prerecorded outbound messages322- Bland/Vapi are better for **live conversational AI calls** because they handle the real-time telephony audio stack themselves323- Hermes STT/TTS alone is not being used here as a full duplex phone conversation engine; that would require a much heavier streaming/webhook integration than this skill is trying to introduce324 325### F. Navigate a phone tree / IVR with Twilio direct calling326 327If you need to press digits after the call connects, use `--send-digits`.328Twilio interprets `w` as a short wait.329 330```bash331python "$SCRIPT" twilio-call "+18005551234" --message "Connecting to billing now." --send-digits "ww1w2w3"332```333 334This is useful for reaching a specific menu branch before handing off to a human or delivering a short status message.335 336### G. Outbound AI phone call with Bland.ai337 338```bash339python "$SCRIPT" ai-call "+15551230000" "Call the dental office, ask for a cleaning appointment on Tuesday afternoon, and if they do not have Tuesday availability, ask for Wednesday or Thursday instead." --provider bland --voice mason --max-duration 3340```341 342Check status:343 344```bash345python "$SCRIPT" ai-status <call_id> --provider bland346```347 348Ask Bland analysis questions after completion:349 350```bash351python "$SCRIPT" ai-status <call_id> --provider bland --analyze "Was the appointment confirmed?,What date and time?,Any special instructions?"352```353 354### H. Outbound AI phone call with Vapi on your owned number355 3561. Import your Twilio number into Vapi:357```bash358python "$SCRIPT" vapi-import-twilio --save-env359```360 3612. Place the call:362```bash363python "$SCRIPT" ai-call "+15551230000" "You are calling to make a dinner reservation for two at 7:30 PM. If that is unavailable, ask for the nearest time between 6:30 and 8:30 PM." --provider vapi --max-duration 4364```365 3663. Check result:367```bash368python "$SCRIPT" ai-status <call_id> --provider vapi369```370 371## Suggested agent procedure372 373When the user asks for a call or text:374 3751. Determine which path fits the request via the decision tree.3762. Run `diagnose` if configuration state is unclear.3773. Gather the full task details.3784. Confirm with the user before dialing or texting.3795. Use the correct command.3806. Poll for results if needed.3817. Summarize the outcome without persisting third-party numbers to Hermes memory.382 383## What this skill still does not do384 385- real-time inbound call answering386- webhook-based live SMS push into the agent loop387- guaranteed support for arbitrary third-party 2FA providers388 389Those would require more infrastructure than a pure optional skill.390 391## Pitfalls392 393- Twilio trial accounts and regional rules can restrict who you can call/text.394- Some services reject VoIP numbers for 2FA.395- `twilio-inbox` polls the REST API; it is not instant push delivery.396- Vapi outbound calling still depends on having a valid imported number.397- Bland is easiest, but not always the best-sounding.398- Do not store arbitrary third-party phone numbers in Hermes memory.399 400## Verification checklist401 402After setup, you should be able to do all of the following with just this skill:403 4041. `diagnose` shows provider readiness and remembered state4052. search and buy a Twilio number4063. persist that number to `${HERMES_HOME:-~/.hermes}/.env`4074. send an SMS from the owned number4085. poll inbound texts for the owned number later4096. place a direct Twilio call4107. place an AI call via Bland or Vapi411 412## References413 414- Twilio phone numbers: https://www.twilio.com/docs/phone-numbers/api415- Twilio messaging: https://www.twilio.com/docs/messaging/api/message-resource416- Twilio voice: https://www.twilio.com/docs/voice/api/call-resource417- Vapi docs: https://docs.vapi.ai/418- Bland.ai: https://app.bland.ai/419 Discovery context
Discovered by repository scan. No exact path reference found in the snapshot’s root AGENTS.md.