Telephony
在不修改核心工具的前提下,为 Hermes 赋予电话能力。可以申请并持久化一个 Twilio 号码,发送和接收 SMS/MMS,直接拨打电话,以及通过 Bland.ai 或 Vapi 进行 AI 驱动的外呼。
技能元数据
| 来源 | 可选 — 使用 hermes skills install official/productivity/telephony 安装 |
| 路径 | optional-skills/productivity/telephony |
| 版本 | 1.0.0 |
| 作者 | Nous Research |
| 许可证 | MIT |
| 标签 | telephony, phone, sms, mms, voice, twilio, bland.ai, vapi, calling, texting |
| 相关技能 | maps, google-workspace, agentmail |
参考:完整的 SKILL.md
以下是该技能被触发时 Hermes 加载的完整技能定义。当技能激活时,Agent 会将其视为指令。
Telephony — 无需修改核心工具即可处理号码、通话和短信
这个可选技能为 Hermes 提供了实用的电话能力,同时将电话功能排除在核心工具列表之外。
它附带一个辅助脚本 scripts/telephony.py,可以:
- 将提供商凭证保存到
~/.hermes/.env - 搜索并购买一个 Twilio 电话号码
- 记住该拥有的号码,以便后续会话使用
- 从拥有的号码发送 SMS / MMS
- 轮询该号码的入站短信,无需 webhook 服务器
- 使用 TwiML
<Say>或<Play>直接进行 Twilio 通话 - 将拥有的 Twilio 号码导入 Vapi
- 通过 Bland.ai 或 Vapi 进行 AI 外呼
解决的问题
此技能旨在覆盖用户实际需要的电话任务:
- 外呼
- 发短信
- 拥有一个可复用的 Agent 号码
- 稍后检查发送到该号码的消息
- 在会话之间保留该号码及相关 ID
- 为入站短信轮询和其他自动化提供面向未来的电话身份
它不会将 Hermes 变成一个实时的入站电话网关。入站短信通过轮询 Twilio REST API 处理。这对于许多工作流(包括通知和某些一次性验证码获取)来说已经足够,且无需添加核心 webhook 基础设施。
安全规则 — 必须遵守
- 在拨打电话或发送短信之前,务必先确认。
- 切勿拨打紧急号码。
- 切勿将电话功能用于骚扰、垃圾信息、冒充他人或任何非法行为。
- 将第三方电话号码视为敏感操作数据:
- 不要将其保存到 Hermes 记忆
- 除非用户明确要求,否则不要将其包含在技能文档、摘要或后续笔记中
- 可以持久化Agent 拥有的 Twilio 号码,因为这是用户配置的一部分。
- 不保证 VoIP 号码能用于所有第三方双因素认证流程。请谨慎使用,并明确告知用户预期。
决策树 — 该用哪个服务?
请使用以下逻辑,而不是硬编码的提供商路由:
1) "我希望 Hermes 拥有一个真实的电话号码"
使用 Twilio。
原因:
- 购买和保留号码的最简单途径
- 最佳的 SMS / MMS 支持
- 最简单的入站 SMS 轮询方案
- 未来接入入站 webhook 或呼叫处理的最清晰路径
使用场景:
- 稍后接收短信
- 发送部署告警 / cron 通知
- 为 Agent 维护一个可复用的电话身份
- 后续尝试基于电话的身份验证流程
2) "我现在只需要最简单的出站 AI 电话呼叫"
使用 Bland.ai。
原因:
- 设置最快
- 一个 API 密钥即可
- 无需先自行购买/导入号码
权衡:
- 灵活性较低
- 语音质量尚可,但不是最佳
3) "我想要最好的对话式 AI 语音质量"
使用 Twilio + Vapi。
原因:
- Twilio 提供你拥有的号码
- Vapi 提供更好的对话式 AI 呼叫质量和更多的语音/模型灵活性
推荐流程:
- 购买/保存一个 Twilio 号码
- 将其导入 Vapi
- 保存返回的
VAPI_PHONE_NUMBER_ID - 使用
ai-call --provider vapi
4) "我想用自定义预录语音消息拨打电话"
使用带有公共音频 URL 的 Twilio 直接呼叫。
原因:
- 播放自定义 MP3 的最简单方式
- 与 Hermes
text_to_speech配合良好,再加上公共文件托管或隧道
文件和持久化状态
该技能在两个位置持久化电话状态:
~/.hermes/.env
用于长期有效的提供商凭证和拥有的号码 ID,例如:
TWILIO_ACCOUNT_SIDTWILIO_AUTH_TOKENTWILIO_PHONE_NUMBERTWILIO_PHONE_NUMBER_SIDBLAND_API_KEYVAPI_API_KEYVAPI_PHONE_NUMBER_IDPHONE_PROVIDER(AI 呼叫提供商:bland 或 vapi)
~/.hermes/telephony_state.json
用于仅技能自身使用、且应在会话间持久化的状态,例如:
- 记住的默认 Twilio 号码 / SID
- 记住的 Vapi 电话号码 ID
- 用于收件箱轮询检查点的最后一条入站消息 SID/日期
这意味着:
- 下次加载该技能时,
diagnose可以告诉你已配置了哪个号码 twilio-inbox --since-last --mark-seen可以从上一个检查点继续
定位辅助脚本
安装此技能后,按如下方式定位脚本:
SCRIPT="$(find ~/.hermes/skills -path '*/telephony/scripts/telephony.py' -print -quit)"
如果 SCRIPT 为空,则表示该技能尚未安装。
安装
这是一个官方可选技能,请从技能中心安装:
hermes skills search telephony
hermes skills install official/productivity/telephony
提供商设置
Twilio — 拥有的号码、SMS/MMS、直接呼叫、入站 SMS 轮询
在以下地址注册:
然后将凭证保存到 Hermes:
python3 "$SCRIPT" save-twilio ACXXXXXXXXXXXXXXXXXXXXXXXXXXXX your_auth_token_here
搜索可用号码:
python3 "$SCRIPT" twilio-search --country US --area-code 702 --limit 5
购买并记住一个号码:
python3 "$SCRIPT" twilio-buy "+17025551234" --save-env
列出已拥有的号码:
python3 "$SCRIPT" twilio-owned
稍后将其中一个设为默认号码:
python3 "$SCRIPT" twilio-set-default "+17025551234" --save-env
# 或
python3 "$SCRIPT" twilio-set-default PNXXXXXXXXXXXXXXXXXXXXXXXXXXXX --save-env
Bland.ai — 最简单的出站 AI 通话
注册地址:
保存配置:
python3 "$SCRIPT" save-bland your_bland_api_key --voice mason
Vapi — 更好的对话语音质量
注册地址:
先保存 API 密钥:
python3 "$SCRIPT" save-vapi your_vapi_api_key
将你拥有的 Twilio 号码导入 Vapi,并保留返回的电话号码 ID:
python3 "$SCRIPT" vapi-import-twilio --save-env
如果你已经知道 Vapi 的电话号码 ID,可以直接保存:
python3 "$SCRIPT" save-vapi your_vapi_api_key --phone-number-id vapi_phone_number_id_here
诊断当前状态
随时检查技能已掌握的信息:
python3 "$SCRIPT" diagnose
在后续会话中恢复工作时,请先运行此命令。
常见工作流
A. 购买一个 Agent 号码并后续继续使用
- 保存 Twilio 凭据:
python3 "$SCRIPT" save-twilio AC... auth_token_here
- 搜索号码:
python3 "$SCRIPT" twilio-search --country US --area-code 702 --limit 10
- 购买号码并保存到
~/.hermes/.env及状态中:
python3 "$SCRIPT" twilio-buy "+17025551234" --save-env
- 下次会话时,运行:
python3 "$SCRIPT" diagnose
这将显示已记住的默认号码和收件箱检查点状态。
B. 从 Agent 号码发送短信
python3 "$SCRIPT" twilio-send-sms "+15551230000" "Your deployment completed successfully."
带附件:
python3 "$SCRIPT" twilio-send-sms "+15551230000" "Here is the chart." --media-url "https://example.com/chart.png"
C. 稍后检查入站短信(无需 Webhook 服务器)
轮询默认 Twilio 号码的收件箱:
python3 "$SCRIPT" twilio-inbox --limit 20
仅显示上次检查点之后到达的消息,并在阅读完毕后推进检查点:
python3 "$SCRIPT" twilio-inbox --since-last --mark-seen
这是对“下次加载技能时如何访问号码收到的消息?”这一问题的核心回答。
D. 使用内置 TTS 发起直接 Twilio 通话
python3 "$SCRIPT" twilio-call "+15551230000" --message "Hello! This is Hermes calling with your status update." --voice Polly.Joanna
E. 使用预录/自定义语音消息进行通话
这是复用 Hermes 现有 text_to_speech 支持的主要路径。
在以下场景使用:
- 你希望通话使用 Hermes 配置的 TTS 语音,而非 Twilio 的
<Say> - 你希望进行单向语音传递(简报、提醒、笑话、状态更新)
- 你不需要实时对话式通话
请单独生成或托管音频,然后:
--- END DOCUMENT CHUNK ---
python3 "$SCRIPT" twilio-call "+155****0000" --audio-url "https://example.com/briefing.mp3"
推荐的 Hermes TTS → Twilio Play 工作流程:
- 使用 Hermes
text_to_speech生成音频。 - 将生成的 MP3 文件设置为可公开访问。
- 使用
--audio-url发起 Twilio 通话。
示例 Agent 流程:
- 让 Hermes 用
text_to_speech创建消息音频 - 如果需要,通过临时静态主机/隧道/对象存储 URL 暴露文件
- 使用
twilio-call --audio-url ...通过电话发送
MP3 的合适托管选项:
- 临时公共对象/存储 URL
- 指向本地静态文件服务器的短期隧道
- 电话提供商可以直接获取的任何现有 HTTPS URL
重要提示:
- Hermes TTS 非常适合预录的外呼消息
- Bland/Vapi 更适合实时对话式 AI 通话,因为它们自己处理实时电话音频栈
- 这里并未将 Hermes STT/TTS 单独用作全双工电话对话引擎;那需要比本技能所介绍的更重的流式/webhook 集成
F. 通过 Twilio 直接呼叫导航电话树/IVR
如果需要在通话接通后按键,请使用 --send-digits。
Twilio 将 w 解释为短暂等待。
python3 "$SCRIPT" twilio-call "+18005551234" --message "正在连接至账单部门。" --send-digits "ww1w2w3"
这在转接给人工或发送简短状态消息之前,用于到达特定菜单分支时非常有用。
G. 使用 Bland.ai 进行外呼 AI 电话
python3 "$SCRIPT" ai-call "+15551230000" "致电牙科诊所,预约周二下午的洗牙服务;如果周二没有空位,则询问周三或周四。" --provider bland --voice mason --max-duration 3
检查状态:
python3 "$SCRIPT" ai-status <call_id> --provider bland
通话完成后向 Bland 询问分析问题:
python3 "$SCRIPT" ai-status <call_id> --provider bland --analyze "预约是否确认?,日期和时间是什么?,是否有特殊说明?"
H. 使用 Vapi 通过自有号码进行外呼 AI 电话
- 将你的 Twilio 号码导入 Vapi:
python3 "$SCRIPT" vapi-import-twilio --save-env
- 发起通话:
python3 "$SCRIPT" ai-call "+15551230000" "你正在致电预订两人晚餐,时间为晚上 7:30。如果该时间不可用,请询问晚上 6:30 到 8:30 之间最近的时间。" --provider vapi --max-duration 4
- 检查结果:
python3 "$SCRIPT" ai-status <call_id> --provider vapi
建议的 Agent 流程
当用户要求拨打电话或发送短信时:
- 通过决策树确定适合的路径。
- 如果配置状态不明确,运行
diagnose。 - 收集完整的任务细节。
- 在拨号或发送短信前与用户确认。
- 使用正确的命令。
- 如果需要,轮询结果。
- 总结结果,不要将第三方号码持久化到 Hermes 记忆中。
该技能目前仍不支持的功能
- 实时接听来电
- 基于 webhook 的实时短信推送至 agent loop
- 对任意第三方 2FA 提供商的保证支持
这些功能需要比纯可选技能更复杂的基础设施。
注意事项
- Twilio 试用账户和地区规则可能会限制可呼叫或发送短信的对象。
- 某些服务会拒绝使用 VoIP 号码进行 2FA。
twilio-inbox通过轮询 REST API 实现,并非即时推送。- Vapi 外呼仍依赖于拥有有效的导入号码。
- Bland 最简单,但音质不一定最好。
- 不要将任意第三方电话号码存储在 Hermes 内存中。
验证清单
完成设置后,你应该能够仅凭此技能完成以下所有操作:
diagnose显示提供商就绪状态和已记忆的状态- 搜索并购买一个 Twilio 号码
- 将该号码持久化到
~/.hermes/.env - 从拥有的号码发送短信
- 稍后轮询该号码的接收短信
- 发起直接 Twilio 呼叫
- 通过 Bland 或 Vapi 发起 AI 呼叫
参考链接
- Twilio 电话号码:https://www.twilio.com/docs/phone-numbers/api
- Twilio 消息服务:https://www.twilio.com/docs/messaging/api/message-resource
- Twilio 语音:https://www.twilio.com/docs/voice/api/call-resource
- Vapi 文档:https://docs.vapi.ai/
- Bland.ai:https://app.bland.ai/