openclaw 的 sag 技能:用 ElevenLabs TTS 让 Agent 在本地"开口说话"
skills/sag/SKILL.md 是 openclaw 内置的一项语音合成技能:它教会 Agent 调用社区 CLI 工具 sag,把文本交给 ElevenLabs 云端 TTS 引擎合成语音并在本机直接播放,交互方式仿照 macOS 经典的 say 命令体验。本文以此技能文档为主线,结合仓库中 docs/tools/tts.md、docs/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为第三方 tapsteipete/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_KEY(const 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。
五、发音与朗读控制:改拼写 > 归一化 > 语言偏置
合成语音最容易翻车的是"发音不对"。技能文档给出一套从手动到自动的处理次序:
- 首选人工修正(First fix: respell):直接改拼写,例如
"key-note"加连字符分节、调整大小写来引导发音。这是最可控的手段,优先于任何自动化开关。 - 数字 / 单位 / URL 交给归一化:使用
--normalize auto让引擎自动把123、5kg、https://...朗读成自然语言;若归一化会破坏专有名词(人名、品牌名),则改用--normalize off。 - 语言偏置(language bias):用
--lang en|de|fr|...(可扩展到其他 ISO 语言码)指导归一化选择正确的语言发音规则——同一串数字在不同语言里的读法截然不同,此参数告诉引擎"按哪种语言去读"。
这套思路在 openclaw 内置通道中亦有对应物:ElevenLabs provider 支持 applyTextNormalization(auto|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_ID或SAG_VOICE_ID(两者任选其一,CLI 均支持)。 - 命令行覆盖:
-v <voice>,既可用音色 ID,也可用已配置的音色别名。 - openclaw 的 Clawd 助手默认音色:
lj2rcrvANS3gaWWnczSX,可直接写-v Clawd使用该别名。
对照内置通道,docs/tools/tts.md 中 ElevenLabs 的默认 speakerVoiceId 为 pMsXgVXv3BLzUgSXRplE,说明两套体系默认音色不同、但都支持显式指定。实践建议:在长输出前先用 sag voices 或一次短朗读确认音色效果,再投入长文本合成。
八、在对话中给用户"语音回复":Agent 的操作范式
这是 sag 技能面向 openclaw Agent 场景的核心用法:当用户要求"用语音回答"(例如"用疯狂科学家的声音说""用语音解释一下"),Agent 应生成音频并随消息发送。技能文档给出了完整流程:
# 生成音频文件
sag -v Clawd -o /tmp/voice-reply.mp3 "Your message here"
# 然后在回复中引用该文件:
# MEDIA:/tmp/voice-reply.mp3
拆解这段指令:
-v Clawd:锁定为 Clawd 默认音色(保持回复声音的一致人格)。-o /tmp/voice-reply.mp3:把合成结果写成文件,而不是直接扬声器播放——因为回复要通过聊天通道送达用户,必须落盘后才能作为媒体附件发送。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.auto、tts.provider、persona、[[tts:...]]指令等机制实现自动化的语音外呼,例如把长回复摘要成 1500 字以内再合成、按通道能力输出 Opus 语音条或 MP3 附件。
换言之,技能文档里的"voice reply"约定(生成文件 → MEDIA: 引用)正是为了兼容这套媒体发送链路。若追求更高自动化,可把 sag 技能保留为"即时表演型语音",同时用 tts.auto: "tagged" 让模型通过 [[tts:text]] 段落按需触发内置合成——两种方式都以 skills/sag/SKILL.md 中的音色/模型/表现力经验为文本侧的基础。
十、使用边界与提示词纪律
综合技能全文,值得固化成操作纪律的要点包括:
- 没有
sag二进制就没有技能:先brew install steipete/tap/sag,再谈调用。 - API Key 是硬门槛:优先
ELEVENLABS_API_KEY,其次SAG_API_KEY。 - 长文本前先验声:用
sag voices与短句试听,确认音色和说话人。 - 读错先改拼写,再考虑
--normalize off保护专有名词、--lang校正语言偏置。 - 区分引擎代际:默认
eleven_v3无 SSML<break>,用[pause]系标记;v2/v2.5 才支持<break time="..."/>,且<phoneme>在sag中不可用。 - 语气标签放在行首,并与停顿标记组合使用;"疯狂科学家/平静/戏剧化"三种人设分别对应
[excited]+短停顿、[whispers]+慢节奏、克制地使用[sings]/[shouts]。 - 聊天语音回复必须
-o落盘 +MEDIA:引用,不能只靠本地播放完成用户请求。
按照以上纪律,一个 openclaw Agent 可以稳定复现"用 Clawd 的声音、带恰当语气、把任意文本变成一段可发送的语音",这正是 skills/sag/SKILL.md 交给模型的全部能力契约。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00