首页
/ openclaw 的 sag 技能:用 ElevenLabs TTS 让 Agent 在本地"开口说话"

openclaw 的 sag 技能:用 ElevenLabs TTS 让 Agent 在本地"开口说话"

2026-09-06 19:23:12作者:翟萌耘Ralph

skills/sag/SKILL.md 是 openclaw 内置的一项语音合成技能:它教会 Agent 调用社区 CLI 工具 sag,把文本交给 ElevenLabs 云端 TTS 引擎合成语音并在本机直接播放,交互方式仿照 macOS 经典的 say 命令体验。本文以此技能文档为主线,结合仓库中 docs/tools/tts.mddocs/tools/skills.md 以及 ElevenLabs 语音插件源码,完整讲解 sag 的安装、鉴权、常用子命令、模型选型、发音控制、语气标签(audio tags),以及 Agent 如何在聊天中以音频形式回复用户。

一、先读懂这份 SKILL.md:技能如何被 Agent 使用

openclaw 中,"技能(skill)"本质上是放在 <技能根目录>/<名字>/SKILL.md 的 Markdown 指令文件:YAML frontmatter 声明元信息,正文告诉模型"何时、如何调用某个工具"。sag 技能位于 skills/sag/SKILL.md,其 frontmatter 完整定义了技能的"准入门槛":

---
name: sag
description: "ElevenLabs text-to-speech with mac-style say UX."
homepage: https://sag.sh
metadata:
  {
    "openclaw":
      {
        "emoji": "🔊",
        "requires": { "bins": ["sag"], "env": ["ELEVENLABS_API_KEY"] },
        "primaryEnv": "ELEVENLABS_API_KEY",
        "install":
          [
            {
              "id": "brew",
              "kind": "brew",
              "formula": "steipete/tap/sag",
              "bins": ["sag"],
              "label": "Install sag (brew)",
            },
          ],
      },
  }
---

这段元数据揭示了技能加载的关键逻辑(完整机制见 docs/tools/skills.md):

  • name: sag:技能的唯一名称,也是会话中的斜杠命令名;Agent 允许列表(allowlist)同样按此名称匹配。
  • requires.bins: ["sag"]宿主机 PATH 上必须存在 sag 可执行文件,技能才会被加载进系统提示词。这是硬性门槛——没有二进制,技能对 Agent 完全不可见。
  • requires.env: ["ELEVENLABS_API_KEY"]:进程或配置中必须存在该环境变量,否则技能同样会被过滤掉。
  • primaryEnv: ELEVENLABS_API_KEY:声明主鉴权变量名,与 skills.entries.<name>.apiKey 配置联动。
  • install:给出面向 macOS 技能界面的 Homebrew 安装描述,formula 为第三方 tap steipete/tap/sag
  • emoji: "🔊":技能在 macOS Skills 界面中展示的图标。

也就是说,Agent 并非"看到文档就调用",而是只有在本机已装好 sag 且配好 API Key 时,这份指令才会进入模型视野。若需全局禁用/启用,可在 ~/.openclaw/openclaw.json 中通过 skills.entries 覆盖,例如 docs/tools/skills.md 中出现的配置片段 sag: { enabled: false }

二、安装与鉴权:ELEVENLABS_API_KEY 是唯一必须项

安装二进制

根据 frontmatter 中的 brew 安装说明,安装命令为:

brew install steipete/tap/sag

安装完成后确认 sag 已在 PATH 中(which sag),否则技能门控不通过。若在无 Homebrew 的 Linux 容器中,也可参考该 tap 的源码自行构建安装,但需保证可执行文件名为 sag 且位于 PATH

配置 API Key

技能文档明确:API Key 必须提供,两种取值来源:

  • ELEVENLABS_API_KEY优先,也即 frontmatter 中的 primaryEnv
  • SAG_API_KEY(CLI 同时支持的备选变量)

之所以仓库把 ELEVENLABS_API_KEY 作为规范变量,是因为它是 openclaw 全局约定:ElevenLabs 语音插件同样以该变量为默认来源。在 extensions/elevenlabs/config-compat.ts 中可看到插件直接读取 ELEVENLABS_API_KEYconst ELEVENLABS_API_KEY_ENV = "ELEVENLABS_API_KEY"),而 docs/tools/tts.md 的字段参考也注明 ElevenLabs provider 的 apiKey "Falls back to ELEVENLABS_API_KEY or XI_API_KEY"。因此对 openclaw 场景,建议统一导出 ELEVENLABS_API_KEY,一份凭证同时服务技能与内置 TTS 通道:

export ELEVENLABS_API_KEY="你的_ElevenLabs_API_Key"

技能文档强调的另一点:面向长文本输出前,先确认音色与说话人匹配,避免用错 voice 合成大段内容后返工。

三、快速上手:macOS say 式的极简语音交互

技能文档给出了四条快速开始命令,覆盖"整段朗读、指定音色朗读、列出音色、查看提示词技巧"四个最常用场景:

命令 作用
sag "Hello there" 最简用法:直接合成并本机播放默认语音
sag speak -v "Roger" "Hello" 用指定音色(-v)合成指定文本
sag voices 列出当前账号可用的音色清单
sag prompting 查看模型特有的提示词/标记技巧说明

其中 sag "文本" 的无参数形式正是"mac-style say UX"的核心体验:像 macOS say 一样,把文本直接变成声音。而 sag speak 子命令则暴露更多控制项(如 -v 选音色、-o 指定输出文件,见后文 Agent 语音回复一节)。

四、模型选型:Expressive / Multilingual / Flash 三种取舍

技能文档给出了三个模型档位及定位,这是 sag 默认行为的关键:

档位 模型 ID 定位
默认(default) eleven_v3 富有表现力(expressive),是 CLI 默认引擎
稳定(stable) eleven_multilingual_v2 多语言稳定性更好,适合跨语言内容
快速(fast) eleven_flash_v2_5 低延迟,适合对实时性敏感的交互

与 openclaw 内置 ElevenLabs TTS provider 相对照,能看出设计取舍:内置通道的默认模型是 eleven_multilingual_v2(见 docs/tools/tts.md 字段参考),且历史上 eleven_turbo_v2 / eleven_turbo_v2_5 这类旧 id 会被规整为对应的 flash 模型;而 sag CLI 作为面向语音表现力的本地工具,把 eleven_v3 设为默认。使用建议是:日常对白用默认 eleven_v3,追求多语言或"不出错"的正式朗读切到 eleven_multilingual_v2,需要低延迟交互时再换 eleven_flash_v2_5

五、发音与朗读控制:改拼写 > 归一化 > 语言偏置

合成语音最容易翻车的是"发音不对"。技能文档给出一套从手动到自动的处理次序:

  1. 首选人工修正(First fix: respell):直接改拼写,例如 "key-note" 加连字符分节、调整大小写来引导发音。这是最可控的手段,优先于任何自动化开关。
  2. 数字 / 单位 / URL 交给归一化:使用 --normalize auto 让引擎自动把 1235kghttps://... 朗读成自然语言;若归一化会破坏专有名词(人名、品牌名),则改用 --normalize off
  3. 语言偏置(language bias):用 --lang en|de|fr|...(可扩展到其他 ISO 语言码)指导归一化选择正确的语言发音规则——同一串数字在不同语言里的读法截然不同,此参数告诉引擎"按哪种语言去读"。

这套思路在 openclaw 内置通道中亦有对应物:ElevenLabs provider 支持 applyTextNormalizationauto|on|off)与 languageCode(两位 ISO 639-1 码)两个字段(见 docs/tools/tts.md),与 sag--normalize / --lang 一一呼应。

v3 与 v2/v2.5 的能力差异(务必区分)

技能文档特别标注了引擎代际差异,写文本前必须先确认当前模型:

  • v3(默认)不支持 SSML <break> 标签。停顿改用行内标记 [pause][short pause][long pause]
  • v2 / v2.5:支持 SSML <break time="1.5s" /> 这类显式时长停顿;但 <phoneme> 音素标签在 sag 中并未开放,不要依赖它修正发音,遇到读错的名字请走"改拼写"路线。

这条差异直接影响成稿习惯:同一段带停顿的文案,在默认模型上要用方括号标记,切到稳定模型后才有真正的 SSML 可用。

六、v3 语气标签(Audio Tags):让朗读"有情绪"

eleven_v3 的核心卖点是表现力。技能文档列出其支持的行首语气标签(put at the entrance of a line,即标签必须放在台词行开头):

  • 音量/方式类:[whispers][shouts][sings]
  • 情绪反应类:[laughs][starts laughing][sighs][exhales]
  • 态度/语气类:[sarcastic][curious][excited][crying][mischievously]

技能文档给出的最小示例:

sag "[whispers] keep this quiet. [short pause] ok?"

一句台词里可以组合"语气标签 + 停顿标记"做出节奏与情绪层次。要注意:文档明确这些是 v3 的能力,使用时应确保当前模型确实是 eleven_v3

七、音色选择:环境变量默认值与 -v 覆盖

技能文档给出的音色配置链路为:

  • 默认音色来自环境变量:ELEVENLABS_VOICE_IDSAG_VOICE_ID(两者任选其一,CLI 均支持)。
  • 命令行覆盖:-v <voice>,既可用音色 ID,也可用已配置的音色别名。
  • openclaw 的 Clawd 助手默认音色:lj2rcrvANS3gaWWnczSX可直接写 -v Clawd 使用该别名。

对照内置通道,docs/tools/tts.md 中 ElevenLabs 的默认 speakerVoiceIdpMsXgVXv3BLzUgSXRplE,说明两套体系默认音色不同、但都支持显式指定。实践建议:在长输出前先用 sag voices 或一次短朗读确认音色效果,再投入长文本合成。

八、在对话中给用户"语音回复":Agent 的操作范式

这是 sag 技能面向 openclaw Agent 场景的核心用法:当用户要求"用语音回答"(例如"用疯狂科学家的声音说""用语音解释一下"),Agent 应生成音频并随消息发送。技能文档给出了完整流程:

# 生成音频文件
sag -v Clawd -o /tmp/voice-reply.mp3 "Your message here"

# 然后在回复中引用该文件:
# MEDIA:/tmp/voice-reply.mp3

拆解这段指令:

  1. -v Clawd:锁定为 Clawd 默认音色(保持回复声音的一致人格)。
  2. -o /tmp/voice-reply.mp3:把合成结果写成文件,而不是直接扬声器播放——因为回复要通过聊天通道送达用户,必须落盘后才能作为媒体附件发送。
  3. MEDIA:/tmp/voice-reply.mp3:openclaw 的媒体内联协议,Agent 在回复正文中以此路径标记音频附件,客户端/通道据此把文件作为语音消息呈现。

这正好把 sag 的两个使用面打通了:本地即时播放用默认参数直接读;聊天回复则必须 -o 落盘 + MEDIA: 引用。

不同"人设"的声音写法

技能文档针对常见语音人设给出了一组文本侧的操作提示:

  • 疯狂科学家(Crazy scientist):多用 [excited] 标签、戏剧性停顿 [short pause]、变化强调强度,制造高能不稳感。
  • 平静(Calm):多用 [whispers],或放慢节奏(减少短句密度、用更长停顿)。
  • 戏剧化(Dramatic):克制地穿插 [sings][shouts],避免全程高情绪导致听感疲劳。

这些提示本质是把"表现力控制"下沉到台词文本层——对 ElevenLabs 这类云端引擎,怎么写台词,直接决定怎么被读出

九、从技能到通道:与 openclaw TTS 体系的衔接

sag 技能解决的是"Agent 主动合成并发送音频"这一显式意图场景;而 openclaw 还内置了从 provider 到通道的整套 TTS 管线,二者定位互补:

  • sag 走外部 CLI + ElevenLabs API,输出由 Agent 手动控制(文本、音色、语气标签、落盘路径全部显式指定),适合单次、有表现力要求的即兴语音回复
  • 内置 TTS(见 docs/tools/tts.md)以 tts.autotts.provider、persona、[[tts:...]] 指令等机制实现自动化的语音外呼,例如把长回复摘要成 1500 字以内再合成、按通道能力输出 Opus 语音条或 MP3 附件。

换言之,技能文档里的"voice reply"约定(生成文件 → MEDIA: 引用)正是为了兼容这套媒体发送链路。若追求更高自动化,可把 sag 技能保留为"即时表演型语音",同时用 tts.auto: "tagged" 让模型通过 [[tts:text]] 段落按需触发内置合成——两种方式都以 skills/sag/SKILL.md 中的音色/模型/表现力经验为文本侧的基础。

十、使用边界与提示词纪律

综合技能全文,值得固化成操作纪律的要点包括:

  1. 没有 sag 二进制就没有技能:先 brew install steipete/tap/sag,再谈调用。
  2. API Key 是硬门槛:优先 ELEVENLABS_API_KEY,其次 SAG_API_KEY
  3. 长文本前先验声:用 sag voices 与短句试听,确认音色和说话人。
  4. 读错先改拼写,再考虑 --normalize off 保护专有名词、--lang 校正语言偏置。
  5. 区分引擎代际:默认 eleven_v3 无 SSML <break>,用 [pause] 系标记;v2/v2.5 才支持 <break time="..."/>,且 <phoneme>sag 中不可用。
  6. 语气标签放在行首,并与停顿标记组合使用;"疯狂科学家/平静/戏剧化"三种人设分别对应 [excited]+短停顿、[whispers]+慢节奏、克制地使用 [sings]/[shouts]
  7. 聊天语音回复必须 -o 落盘 + MEDIA: 引用,不能只靠本地播放完成用户请求。

按照以上纪律,一个 openclaw Agent 可以稳定复现"用 Clawd 的声音、带恰当语气、把任意文本变成一段可发送的语音",这正是 skills/sag/SKILL.md 交给模型的全部能力契约。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
916
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388