OpenClaw的热度还是没有下去,看来我还能蹭一波,不过今天还是带来一点有意思的东西,那就是把OpenClaw接入到虾哥的小智AI。
不同于手机APP和电脑程序接入OpenClaw,运行在开发板上的小智AI有它自己的特点。它自身的产品形态就适合自然语言对话,倾向于更为自然的交流,我们都有过这样的经历,当你和朋友聊天聊到了一些精彩的内容,你滔滔不绝妙语连珠,但是回头想把它用文字记录下来的时候你会发现怎么写怎么别扭,只能在文字上添油加醋,最后还是会留下许多遗憾,甚至你笔下的自己都不像自己。所以更为自然的交流包含了真实的自己。
现在流行“养龙虾”也就是调教OpenClaw,希望OpenClaw更懂你,那么最重要的一点就是你把最真实的自己交给龙虾,为此,小智AI这种对话盒子的形态可能更适合帮助你养龙虾。所以这次使用小智AI对接OpenClaw其实还是挺有意思的。
那么这件有意思的事情需要我们准备什么东西呢:一个ESP32开发板及配件(网上有现成的可以直接购买)、一台电脑,还有就是你用起来顺手的vibe coding工具。
这个事情涉及到固件编写及烧录、小智服务端程序编写、OpenClaw的channel插件编写。看上去是不是很复杂,不用担心,其实固件、小智服务端程序、channel插件我都已经编写完毕上传到了GitHub上,你要做的只是下载安装,把它们配置起来就好了。
不过这里还是要说明下整个软件系统的工作流程,以便大家能够很好的理解它的原理,一旦出了问题大家也能自行解决。
整条链路可以理解成一个接力赛:
ESP32 小智终端负责采集语音,发给服务端。xiaozhi-server负责把语音变成文字,再把文字转交给 OpenClaw。myapp-channel插件负责把 OpenClaw 和xiaozhi-server连起来。OpenClaw负责真正的智能体处理,也就是“理解问题、思考、生成回答”。- 回答再一路返回给
xiaozhi-server,由它转成语音。 - 最终语音再发回
ESP32 小智终端播放出来。
说白了:
小智负责听和说,xiaozhi-server 负责搬运和转换,OpenClaw 负责思考。
一张图先看懂

如果把它拟人化一点:
- 小智终端像一个“麦克风 + 音箱”
xiaozhi-server像一个“翻译官 + 调度员”- OpenClaw 像一个“大脑”
myapp-channel像一根“专线电话”
我们一步一步来实现。
第一部分 先从终端开始 完成固件修改和烧录
终端硬件可以从淘宝购买,我买到硬件如下图所示,是一个组装好的小智AI硬件形态。

虾哥小智AI固件是开源的,为此我们可以随意修改固件,不过不用担心,这种修改很简单,就是把小智AI连接虾哥服务器的地址改成我们自己服务器的地址,这一步仅仅需要修改几行代码。
接下来就是下载固件源码–修改源码–编译–烧录,整个过程虾哥有文档说明很详细,大家可以参考这个链接(Windows搭建 ESP IDF 5.5.3开发环境以及编译小智 – 飞书云文档),这里我只把关键步骤描述下:
1.下载固件
我使用git命令,将源码克隆到本地目录(建议目录路径中不要有中文和空格)
git clone https://github.com/78/xiaozhi-esp32.git
2.下载编译环境ESP-IDF
地址:https://dl.espressif.com/dl/esp-idf/,下载完成后双击安装包,一路下一步即可。

3.进入IDF环境
双击桌面上的PowerShell会自动导入IDF环境,电脑安装了Windows Terminal(win11自带,win10可以搜索store打开商店安装)的可以直接打开终端,终端的+号可以直接运行IDF环境

4.在IDF环境中进入工作目录
在刚才打开的PowerShell中使用cd命令进入到刚才GitHub克隆下来的项目的目录里。
5.修改固件源码
先修改固件源码。由于虾哥的文档中有提到“最新的1.6.2版本已经取消了从menuconfig配置websocket接口的源码,最新源码是从OTA接口接收websocket的api接口,无法自己设置,需要切换到1.6.0或者以下才可以”,所以这里我们也不切换到1.6.0了,直接修改固件源码里负责和小智AI后台服务通讯的模块,屏蔽OTA的代码,将链接方式默认为WebSocket,并且将WebSocket连接地址改为你的服务器地址,我这里用的是内网服务器,所以我改成了192.168.2.3。
一共修改了两个文件:
第一个文件是 application.cc

找到以下代码,将这段代码改为一行:
if (ota_->HasMqttConfig()) {
protocol_ = std::make_unique<MqttProtocol>();
} else if (ota_->HasWebsocketConfig()) {
protocol_ = std::make_unique<WebsocketProtocol>();
} else {
ESP_LOGW(TAG, "No protocol specified in the OTA config, using MQTT");
protocol_ = std::make_unique<MqttProtocol>();
}
修改为:
protocol_ = std::make_unique<WebsocketProtocol>();
第二个文件是 protocols/websocket_protocol.cc

将以下代码:
std::string url = settings.GetString("url");
改为自己的服务器地址,这里要写自己实际的地址:
std::string url = "ws://192.168.2.3:8080";
6. 编译准备及编译
确认在PowerShell中已经进入了项目根目录,确认自己板子的型号,默认的编译芯片是ESP32的,所以自己的板子是S3的话一定要输入以下命令把芯片设置为S3
idf.py set-target esp32s3

开始编译,再次输入 idf.py build 进行编译:
idf.py build
7. 烧录到设备中
确认你的ESP32设备已经连接到了计算机,编译完成后输入 idf.py build flash monitor 进行下载和显示日志。
idf.py build flash monitor
至此硬件部分的操作就完成了,现在可以打开开发板,唤醒小智,如果显示“链接中….”,而且一直连不上,那么恭喜你,刷机成功了。接下来就是完成小智后台服务的搭建。
第二部分 开发和部署小智后台服务端
前文已经说了,小智后台服务类似一个桥,将小智和OpenClaw连接起来,而且完成语音到文字和文字到语音的转换。
理论上这里需要你自己开发属于自己的小智后台服务端,你可能有各种各样的想法,想让小智变得更智能,响应速度更快,因为并非所有的请求都要发送到OpenClaw,这个“桥”上你可以增加各种逻辑。
但是我们现在的目的是把项目跑通,最主要的就是完成小智和OpenClaw的连接,在本文中提供了一个最小的但是开箱可用小智后台服务端程序。
在虾哥的GitHub上当然也介绍了一个优秀的第三方小智后台服务,如果你有时间,并且想让小智获得更多的能力,你可以基于这些第三方的小智后台服务进行二次开发。
但是如果你仅仅是想将小智连接到OpenClaw而且不想编写任何代码,那么你可以尝试下我的这个轻量级的小智后台服务。我已经把它放到了GitHub上,地址是:
https://github.com/frogchou/xiaozhi-openclaw
这里还是要说明下这个小智后台服务的原理和结构,如果后期你想修改它,这个说明可以帮你少走弯路。当然前期你可以选择直接用它而不进行任何修改。
如果把整个系统比作一条路,那么 xiaozhi-server 就是中间那座桥。
它前面连接的是 ESP32 小智终端,后面连接的是 OpenClaw。小智终端负责“听”和“说”,OpenClaw 负责“思考”,而 xiaozhi-server 负责把两边顺畅地接起来。
通俗一点说,它主要做四件事:
- 接收小智终端上传的语音音频流
- 把语音转成文字
- 把文字转交给 OpenClaw 获取回复
- 把 OpenClaw 返回的文字再转成语音,发回小智终端播放
所以它不是“大脑”,更像一个语音交互的“调度中心”。
也可以顺手补一句更口语化的总结:
小智终端负责采集和播放,OpenClaw 负责生成答案,xiaozhi-server 负责把这整套流程真正跑起来。
xiaozhi-server 的目录结构
xiaozhi-server 的目录不复杂,核心主要分成 4 部分:
core/
放核心流程,比如 WebSocket 服务入口、设备会话管理、消息处理流程。services/
放具体服务逻辑,比如语音识别、文字转语音、OpenClaw bridge 通信。utils/
放工具代码,比如音频转换、日志处理。config.py/.env
放运行配置,比如端口、OpenAI 参数、OpenClaw bridge 参数。
大致结构如下:
xiaozhi-server/
├── main.py # 程序启动入口
├── config.py # 配置读取
├── .env / .env.example # 环境变量配置
├── requirements.txt # Python 依赖
├── core/
│ ├── server.py # WebSocket 服务入口
│ ├── session.py # 设备会话和一轮对话处理
│ └── protocol.py # 小智终端通信协议编解码
├── services/
│ ├── asr.py # ASR / LLM / TTS 相关逻辑
│ ├── openclaw_bridge.py # 与 OpenClaw 的桥接通信
│ └── openclaw_channel.py # 旧方案残留文件
└── utils/
├── audio_converter.py # 音频格式转换
└── logger.py # 日志工具
xiaozhi-server 的主要功能
从功能上看,xiaozhi-server 主要承担了下面这些角色:
1. 设备接入层
它通过 WebSocket 和小智终端保持连接,接收终端上传的音频帧,并把最终语音结果再推回终端。
2. 语音处理层
它会先把终端发来的音频帧整理成标准音频,再做 ASR,把“声音”变成“文字”。
3. AI 调度层
拿到文字以后,它不会自己生成回答,而是通过 myapp-channel 对应的桥接协议,把请求发给 OpenClaw。
4. 语音返回层
OpenClaw 返回文本回答后,它会再做 TTS,把文字重新变成语音音频包,再发回小智终端播放。
运行方式可以这样写:
xiaozhi-server 是怎么运行的
xiaozhi-server 是一个 Python 项目,启动方式比较直接。
1. 安装依赖
pip install -r requirements.txt
2. 配置环境变量
主要配置写在 .env 里,例如:
- 服务监听地址和端口
- OpenAI 的 ASR / TTS 配置
- OpenClaw bridge 的路径和 token
其他的配置可以保持默认。
3. 启动服务
python main.py
启动后,它会监听一个 WebSocket 服务端口,等待两类连接:
- 小智终端的设备连接
- OpenClaw myapp-channel 插件建立的 bridge 长连接
如果你想在博文里再更顺一点,可以加一小段“项目定位”:
以上就是 xiaozhi-server 也就是小智后台服务的整个介绍,如果你按照以上的步骤操作完毕了,那么小智后台服务已经可以正常的运行了,测试方法也很简单,那就是用你的开发板,这时你唤醒小智,那么它应该显示“链接中…”,这里只需稍等,就会进入“聆听中…”,如果出现这个提示,那么就证明小智后台服务运行正常。
第三部分 开发并安装自己的OpenClaw channel
那么接下来,就要开发自己的channel,这方面我属实不是专家,只是翻阅了下官方文档,大致了解了一下它的原理,然后使用vibe coding让AI帮我写了一个channel,这个channel和小智后台服务之间使用WebSocket维持了一个长连接,channel内部的实现完全是AI生成的,当然它目前是可用的,这部分代码我也上传到了GitHub,如果你和我一样不想折腾,那么你可以尝试下我的这个channel插件,它的安装和配置也很简单。GitHub的地址如下:
https://github.com/frogchou/xiaozhi-openclaw
但是在开始之前,你最好还是先了解下什么是channel,为此我还是进行了一下说明。看完说明后可能更有助于你安装我开发的这个channel插件。
在 OpenClaw 里,channel 可以理解成“消息入口”和“消息出口”。
它的作用,就是把外部世界的消息,接进 OpenClaw;再把 OpenClaw 生成的回复,送回外部世界。
如果把 OpenClaw 想成一个 AI 大脑,那 channel 就像它的“耳朵”和“嘴巴”。
比如常见的 Telegram、Slack、Discord 这类接入方式,本质上都是不同的 channel。
它们虽然面对的平台不同,但做的事情其实类似:
- 接收外部消息
- 把消息转换成 OpenClaw 能理解的格式
- 交给 OpenClaw 的 agent 处理
- 再把处理结果发送回原来的平台
所以,channel 的本质其实就是一层“适配器”。
它把外部平台的协议、身份、会话、消息结构,翻译成 OpenClaw 内部统一的处理方式。这样 OpenClaw 不需要关心消息到底来自 Telegram、Slack,还是你自己写的系统。
为什么我要自己开发一个 myapp-channel
我这里的场景并不是 Telegram 或 Slack,而是一套自己的语音对话系统:
- 前端是
ESP32 小智终端 - 中间是
xiaozhi-server - 后面是
OpenClaw
这时候就有一个现实问题:
xiaozhi-server 发来的消息,OpenClaw 默认并不认识。
OpenClaw 能处理的是“标准 channel 消息”,而不是任意一个外部服务随便发过来的 JSON。所以,要想让 xiaozhi-server 和 OpenClaw 正式打通,就需要自己做一个自定义 channel。
这就是 myapp-channel 的由来。
myapp-channel 的作用是什么
myapp-channel 的作用可以概括成一句话:
把 xiaozhi-server 发来的桥接消息,翻译成 OpenClaw 能处理的标准消息,再把 OpenClaw 的回复翻译回去。
它在整条链路里,承担的是“桥接适配器”的角色。
具体来说,它做了几件事:
1. 主动连接 xiaozhi-server
因为 OpenClaw 运行在容器里,外部不方便直接访问它,所以最终采用的是反向思路:
不是让 xiaozhi-server 主动调用 OpenClaw,而是让 myapp-channel 主动连到 xiaozhi-server 暴露出来的 WebSocket bridge。
这样一来,OpenClaw 就像主动拉了一根长期在线的通信线出去。
2. 接收 reply.request
当 xiaozhi-server 拿到用户语音识别后的文本时,会通过 bridge 发来一条 reply.request 消息。
myapp-channel 收到后,会把这条消息解析出来。
3. 转换成 OpenClaw 内部消息
这一步很关键。
外部消息和 OpenClaw 内部消息不是一回事。myapp-channel 会把诸如:
- 用户是谁
- 当前会话是谁
- 消息正文是什么
- 这是哪个 channel
- 该归属哪个 SessionKey
这些信息整理好,转成 OpenClaw 内部标准上下文。
4. 交给 OpenClaw 的 agent 处理
整理完成后,myapp-channel 会把消息真正送进 OpenClaw,让 agent 去完成理解、推理和回复生成。
5. 把结果回传给 xiaozhi-server
等 OpenClaw 生成回复后,myapp-channel 再把它包装成 reply.response,通过同一条 WebSocket 长连接发回 xiaozhi-server。
于是,xiaozhi-server 就能继续做 TTS,把文字转成语音,再播放给小智终端。
myapp-channel 在整个系统里的位置
整条链路可以这样理解:
ESP32 小智终端
↓
xiaozhi-server
↓
myapp-channel
↓
OpenClaw
↓
myapp-channel
↓
xiaozhi-server
↓
ESP32 小智终端
如果说 xiaozhi-server 是连接硬件和 AI 的那座桥,那么 myapp-channel 就是这座桥和 OpenClaw 之间的“桥头转换器”。它不负责语音识别,不负责语音合成,也不负责真正的 AI 推理。
它只做一件事:
让 OpenClaw 能以“原生 channel”的方式接收并处理来自这套语音系统的消息。
myapp-channel 的安装和配置方式
myapp-channel 本质上是一个 OpenClaw 自定义 channel 插件。安装方式并不复杂,核心分成两步:
- 把插件目录放到 OpenClaw 的扩展目录里
- 在
openclaw.json里配置channels.myapp-channel
1. 安装插件
先把插件复制到 OpenClaw 的扩展目录:
mkdir -p ~/.openclaw/extensions
cp -R myapp-channel ~/.openclaw/extensions/
安装完成后,目录结构大致如下:
~/.openclaw/extensions/myapp-channel/
├── index.ts
├── openclaw.plugin.json
└── README.md
如果我是通过打包好的压缩包分发,也可以先解压:
tar -xzf myapp-channel-0.1.0.tar.gz
cp -R myapp-channel-0.1.0/myapp-channel ~/.openclaw/extensions/
2. 配置 OpenClaw
然后在 OpenClaw 的配置文件 openclaw.json 中加入 myapp-channel 这一段:
{
"channels": {
"myapp-channel": {
"enabled": true,
"bridgeUrl": "ws://192.168.2.3:8080/openclaw-bridge",
"bridgeToken": "replace-with-random-token",
"botName": "OpenClaw",
"timeoutMs": 120000,
"reconnectMs": 3000
}
}
}
这里需要注意 bridgeUrl 和 bridgeToken。
bridgeUrl 是 OpenClaw 要主动连接的 WebSocket bridge 地址。比如这里的:ws://192.168.2.3:8080/openclaw-bridge 意思就是:让 OpenClaw 插件主动去连接部署在这台机器上的 xiaozhi-server。
bridgeToken 桥接认证 token。插件连接 xiaozhi-server 时,会把这个 token 带过去。xiaozhi-server 也会校验这个 token,只有一致才允许建立连接。所以这个值必须和 xiaozhi-server 里的配置保持一致。
3. xiaozhi-server 这一侧也要同步配置
因为 myapp-channel 走的是 WebSocket bridge,所以 xiaozhi-server 这一侧也要配对应参数,找到 xiaozhi-server 服务的 .env 文件,修改里面的配置,例如:
OPENCLAW_BRIDGE_PATH=/openclaw-bridge
OPENCLAW_BRIDGE_TOKEN=replace-with-random-token
OPENCLAW_BRIDGE_REQUEST_TIMEOUT_SECONDS=120
这里最重要的是:
- OPENCLAW_BRIDGE_PATH
- OPENCLAW_BRIDGE_TOKEN
它们必须和 OpenClaw 侧配置对应起来。
4. 配置完成后怎么生效
改完插件文件或者 openclaw.json 之后,需要重启 OpenClaw gateway。也就是说,myapp-channel 不是“热更新立即生效”的那种模式,通常需要重启 OpenClaw 才会重新加载插件和配置。
5. 启动后怎么判断有没有配置成功
如果配置正确,OpenClaw 启动日志里通常会出现类似信息:
[myapp-channel] connecting bridge to ws://192.168.2.3:8080/openclaw-bridge?token=...
[myapp-channel] bridge connected
这表示:
- 插件已经被 OpenClaw 成功加载
- 插件已经开始主动连接 bridge
- 和 xiaozhi-server 的长连接已经建立成功
如果你看到这两行,那么恭喜你,基本就说明安装和配置已经通了。
第四部分 整体测试
这是最开心的部分了,就是完成整体测试。
下面按“启动顺序 + 检查点”的方式来跑一遍,基本能把问题定位在具体环节。
启动前检查
- 终端固件里的 WebSocket 地址已经改成你的
ws://...:8080(跟 xiaozhi-server 对外地址一致)。 xiaozhi-server的.env里已经配置好 ASR / TTS(以及 bridge 的 path/token)。- OpenClaw 已经配置并启用
myapp-channel,bridgeUrl/bridgeToken与 xiaozhi-server 保持一致。
启动顺序
- 启动 OpenClaw(gateway),确认日志里
myapp-channel能正常加载(至少没有报错)。 - 启动
xiaozhi-server,确认它监听的端口正常,并且 bridge 路径已经挂起来(例如/openclaw-bridge)。 - 给 ESP32 上电,观察屏幕:一般会从“链接中…”进入“聆听中…”。
端到端测试
- 唤醒小智,说一句简单的话,比如“你好,你是谁?”。
- 在
xiaozhi-server侧看日志:应该能看到 ASR 的文本结果,以及发往 bridge 的reply.request。 - 在 OpenClaw 侧看日志:应该能看到 myapp-channel 收到请求并返回回复。
- 回到设备端:应该能听到 TTS 播放的回答。
常见问题排查
- 设备一直“链接中…”:优先检查固件里的
ws://地址、端口、防火墙/局域网可达性。 myapp-channel连不上 bridge:检查bridgeUrl是否能从 OpenClaw 容器访问到 xiaozhi-server(尤其是内网 IP、容器网络),以及bridgeToken是否一致。- 能识别文字但不说话:检查 TTS 配置、音频设备、以及 xiaozhi-server 的 TTS 返回是否报错。
- 延迟很大:把 OpenClaw / ASR / TTS 的日志打开,看卡在 ASR、LLM 还是 TTS。
以上就是这是整个小智AI接入Openclaw的过程。