乐于分享
好东西不私藏

OpenClaw工具拆解之tts+web_search

OpenClaw工具拆解之tts+web_search

一、tts 工具

1.1 工具概述

功能:文本转语音(Text-to-Speech)
核心特性

  • • 支持多种语音提供商
  • • 自动交付音频文件
  • • 支持渠道特定格式
  • • 静默回复支持(避免重复消息)

1.2 Schema 定义

位置:第 113095 行

constTtsToolSchema = Type.Object({
textType.String({ description"Text to convert to speech." }),
channelType.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.`,
parametersTtsToolSchema,
executeasync (_toolCallId, args) => {
const params = args;

// 1. 解析文本(必填)
const text = readStringParam$1(params, "text", { requiredtrue });

// 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 ? { audioAsVoicetrue } : {}
                        }
                    }
                };
            }

// 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,
preferRuntimeProvidersBoolean(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,
executeasync (_toolCallId, args) => 
jsonResult(await resolved.definition.execute(args))
    };
}

2.4 提供商解析流程

// 1. 检查运行时配置
const runtimeProviderId = options?.runtimeWebSearch?.selectedProvider ?? 
                          options?.runtimeWebSearch?.providerConfigured;

// 2. 解析搜索定义
const resolved = resolveWebSearchDefinition({
    ...options,
preferRuntimeProvidersBoolean(runtimeProviderId) && 
                           !resolveBundledWebSearchPluginId$1(runtimeProviderId)
});

// 3. resolveWebSearchDefinition 函数会:
//    - 检查配置的提供商
//    - 加载提供商定义(description/parameters/execute)
//    - 验证 API 密钥
//    - 返回完整的工具定义

2.5 支持的提供商

提供商
说明
API Key
DuckDuckGo
无需 API key
不需要
Tavily
AI 优化搜索
需要
Firecrawl
网页抓取 + 搜索
需要
Brave
Brave Search API
需要
Google
Custom Search API
需要

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 功能定位

特性
tts
web_search
用途
文本转语音
网络搜索
输出
音频文件
搜索结果
提供商
ElevenLabs 等
DuckDuckGo/Tavily 等

3.2 配置要求

特性
tts
web_search
API Key
需要
取决于提供商
渠道配置
可选
不需要
运行时配置
不支持
支持

3.3 返回结果

特性
tts
web_search
媒体交付
自动
不支持
静默回复
推荐
不需要
结果数量
1 个音频
N 个搜索结果

四、相关工具

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}"