OpenClaw工具拆解之tts+web_search
一、tts 工具
1.1 工具概述
功能:文本转语音(Text-to-Speech)
核心特性:
-
• 支持多种语音提供商 -
• 自动交付音频文件 -
• 支持渠道特定格式 -
• 静默回复支持(避免重复消息)
1.2 Schema 定义
位置:第 113095 行
constTtsToolSchema = Type.Object({
text: Type.String({ description: "Text to convert to speech." }),
channel: Type.Optional(Type.String({ description: "Optional channel id to pick output format (e.g. telegram)." }))
});
1.3 完整执行代码
位置:第 113099 行
functioncreateTtsTool(opts) {
return {
label: "TTS",
name: "tts",
displaySummary: "Convert text to speech and return audio.",
description: `Convert text to speech. Audio is delivered automatically from the tool result — reply with ${SILENT_REPLY_TOKEN} after a successful call to avoid duplicate messages.`,
parameters: TtsToolSchema,
execute: async (_toolCallId, args) => {
const params = args;
// 1. 解析文本(必填)
const text = readStringParam$1(params, "text", { required: true });
// 2. 解析渠道(可选)
const channel = readStringParam$1(params, "channel");
// 3. 执行文本转语音
const result = awaittextToSpeech({
text,
cfg: opts?.config ?? loadConfig(),
channel: channel ?? opts?.agentChannel
});
// 4. 返回结果
if (result.success && result.audioPath) {
return {
content: [{
type: "text",
text: "Generated audio reply."
}],
details: {
audioPath: result.audioPath,
provider: result.provider,
media: {
mediaUrl: result.audioPath,
...result.voiceCompatible ? { audioAsVoice: true } : {}
}
}
};
}
// 5. 失败结果
return {
content: [{
type: "text",
text: result.error ?? "TTS conversion failed"
}],
details: { error: result.error }
};
}
};
}
1.4 执行流程图
tts 工具调用
↓
1. 解析文本(必填)
↓
2. 解析渠道(可选)
↓
3. 调用 textToSpeech 函数
├─ 加载配置
├─ 选择提供商
├─ 调用 API
└─ 保存音频文件
↓
4. 返回结果
├─ 成功 → 返回音频路径
└─ 失败 → 返回错误信息
↓
5. 自动交付音频
1.5 返回结果格式
成功:
{
"content":[{
"type":"text",
"text":"Generated audio reply."
}],
"details":{
"audioPath":"/tmp/tts-abc123.mp3",
"provider":"elevenlabs",
"media":{
"mediaUrl":"/tmp/tts-abc123.mp3",
"audioAsVoice":true
}
}
}
失败:
{
"content":[{
"type":"text",
"text":"TTS conversion failed"
}],
"details":{
"error":"API key not configured"
}
}
1.6 静默回复
// 成功调用 TTS 后,使用静默回复避免重复消息
// SILENT_REPLY_TOKEN = "NO_REPLY"
// 大模型应该回复:
NO_REPLY
// 这样渠道不会发送重复消息,因为音频已经自动交付
1.7 使用示例
用户:用语音回复"你好,我是阿财"
大模型返回:
{
"tool_call":{
"name":"tts",
"arguments":{
"text":"你好,我是阿财"
}
}
}
执行结果:
{
"content":[{
"type":"text",
"text":"Generated audio reply."
}],
"details":{
"audioPath":"/tmp/tts-abc123.mp3",
"provider":"elevenlabs",
"media":{
"mediaUrl":"/tmp/tts-abc123.mp3",
"audioAsVoice":true
}
}
}
大模型回复:
NO_REPLY
二、web_search 工具
2.1 工具概述
功能:网络搜索
核心特性:
-
• 支持多种搜索提供商(DuckDuckGo/Tavily 等) -
• 支持运行时提供商配置 -
• 支持沙盒模式 -
• 返回搜索结果(标题/URL/摘要)
2.2 Schema 定义
web_search 的 Schema 是动态解析的,取决于配置的提供商。
2.3 完整执行代码
位置:第 113760 行
functioncreateWebSearchTool(options) {
// 1. 解析运行时提供商
const runtimeProviderId = options?.runtimeWebSearch?.selectedProvider ??
options?.runtimeWebSearch?.providerConfigured;
// 2. 解析搜索定义
const resolved = resolveWebSearchDefinition({
...options,
preferRuntimeProviders: Boolean(runtimeProviderId) &&
!resolveBundledWebSearchPluginId$1(runtimeProviderId)
});
// 3. 如果没有解析到提供商,返回 null(工具不可用)
if (!resolved) returnnull;
// 4. 返回工具定义
return {
label: "Web Search",
name: "web_search",
description: resolved.definition.description,
parameters: resolved.definition.parameters,
execute: async (_toolCallId, args) =>
jsonResult(await resolved.definition.execute(args))
};
}
2.4 提供商解析流程
// 1. 检查运行时配置
const runtimeProviderId = options?.runtimeWebSearch?.selectedProvider ??
options?.runtimeWebSearch?.providerConfigured;
// 2. 解析搜索定义
const resolved = resolveWebSearchDefinition({
...options,
preferRuntimeProviders: Boolean(runtimeProviderId) &&
!resolveBundledWebSearchPluginId$1(runtimeProviderId)
});
// 3. resolveWebSearchDefinition 函数会:
// - 检查配置的提供商
// - 加载提供商定义(description/parameters/execute)
// - 验证 API 密钥
// - 返回完整的工具定义
2.5 支持的提供商
|
|
|
|
| DuckDuckGo |
|
|
| Tavily |
|
|
| Firecrawl |
|
|
| Brave |
|
|
|
|
|
2.6 执行流程图
web_search 工具调用
↓
1. 解析运行时提供商
↓
2. 解析搜索定义
├─ 检查配置的提供商
├─ 加载提供商定义
├─ 验证 API 密钥
└─ 返回工具定义
↓
3. 执行搜索
├─ 调用提供商 API
├─ 解析结果
└─ 返回搜索结果
↓
4. 返回结果
2.7 返回结果格式
DuckDuckGo 成功:
{
"results":[
{
"title":"网页标题",
"url":"https://example.com",
"snippet":"摘要内容..."
},
...
]
}
Tavily 成功:
{
"results":[
{
"title":"网页标题",
"url":"https://example.com",
"content":"详细内容...",
"score":0.95
},
...
],
"query":"搜索关键词",
"total":10
}
失败:
{
"error":"API key not configured for provider: tavily"
}
2.8 使用示例
用户:搜索 OpenClaw 文档
大模型返回:
{
"tool_call":{
"name":"web_search",
"arguments":{
"query":"OpenClaw documentation"
}
}
}
执行结果:
{
"results":[
{
"title":"OpenClaw Documentation",
"url":"https://docs.openclaw.ai",
"snippet":"Official documentation for OpenClaw..."
},
{
"title":"OpenClaw GitHub",
"url":"https://github.com/openclaw/openclaw",
"snippet":"OpenClaw source code and examples..."
}
]
}
三、关键机制对比
3.1 功能定位
|
|
|
|
| 用途 |
|
|
| 输出 |
|
|
| 提供商 |
|
|
3.2 配置要求
|
|
|
|
| API Key |
|
|
| 渠道配置 |
|
|
| 运行时配置 |
|
|
3.3 返回结果
|
|
|
|
| 媒体交付 |
|
|
| 静默回复 |
|
|
| 结果数量 |
|
|
四、相关工具
4.1 web_fetch
位置:第 113588 行
functioncreateWebFetchTool(options) {
// 抓取网页内容
// 支持 Firecrawl 集成
// 返回 Markdown 或纯文本
}
4.2 工具组合使用
// 1. 搜索信息
const searchResults = awaitweb_search({ query: "..." });
// 2. 抓取网页内容
const content = awaitweb_fetch({ url: searchResults.results[0].url });
// 3. 转换为语音
awaittts({ text: content });
五、配置示例
5.1 TTS 配置
# openclaw.yaml
tts:
provider:elevenlabs
apiKey:"${ELEVENLABS_API_KEY}"
voice:"Rachel"
model:"eleven_monolingual_v1"
5.2 Web Search 配置
# openclaw.yaml
tools:
web:
search:
provider:duckduckgo# 或 tavily/brave/google
# tavily:
# apiKey: "${TAVILY_API_KEY}"
# brave:
# apiKey: "${BRAVE_API_KEY}"
夜雨聆风