






















作者: 杨易 & 赛博龙虾 环境: RackNerd VPS (Linux) + OpenClaw Kernel (Docker) + NapCatQQ (Docker) 目标: 突破 Telegram 严苛的 PC 端风控限制,使用 QQ 小号完美接入 OpenClaw,实现带有长文本思考、人设继承、全双工 WebSocket 通讯的 24 小时私人管家。
在折腾了几十个小时、经历了无数次报错、甚至和 AI Agent 发生“逻辑斗智斗勇”之后,我们终于打通了这套“脑机接口”,并完成了底层架构的“统一网关路由”升级。为了不让后来者重蹈覆辙,特整理此份血泪史。
最终跑通的完美架构如下:
宿主机 Docker 网络:搭建起隔离但互通的虚拟网络。
NapCatQQ 容器:负责模拟 iPad/Linux 登录 QQ 小号,通过 OneBot v11 协议对外暴露 WebSocket (3001 端口) 作为“耳朵和嘴巴”。
OpenClaw Kernel 容器:运行 Agent 大脑中枢。内部挂载一个 Python 桥接脚本(QQ Ears),它不再直接请求大模型 API,而是作为统一网关路由,遇到消息直接调用底层 openclaw agent 命令。这使得 QQ 端完美继承了官方 Telegram 机器人的长期记忆、系统人设与本地工具链!

表现: Agent 假死不回话;或者明明修改了宿主机的 Python 脚本并保存,运行出来的依然是旧版本的代码报错。
真相:
OpenClaw 严格禁止 Agent 运行复合后台命令。
Docker 容器是极其封闭的集装箱。在宿主机 /root/ 下修改并保存的文件,绝对不会自动同步到容器内的 /home/node/ 目录。
解法: 每次修改代码后,必须执行“极客三件套”强行覆盖并重启内存:
Bash
# 1. 强行越权把宿主机的新文件塞进容器
sudo docker cp /root/qq_ears_brain.py openclaw_kernel:/home/node/qq_ears_brain.py
# 2. 强制杀掉旧容器里的幽灵进程,清理内存
sudo docker restart openclaw_kernel
# 3. 前台点火监工 (没问题后再加 -d 放入后台)
sudo docker exec -it openclaw_kernel python3 /home/node/qq_ears_brain.py
表现: QQ 端成了失忆的“复读机”,性格与 Telegram 端截然不同,且执行 openclaw agent 命令时频繁报错 unknown option '--no-color'。
真相:
自己写代码直连 DeepSeek API,会丢失 OpenClaw 强大的上下文记忆和工具链。
Linux 命令行的严苛法则:全局选项(--no-color)必须紧跟在主程序后面,子命令(agent)之前。位置一错,全盘崩溃。
解法: 实现“统一网关路由”。砍掉 API 密钥,直接通过 asyncio.create_subprocess_exec 召唤底层内核,并绝对精准地排列参数顺序:openclaw, --no-color, agent。
表现: 终端完美打印 ✅ 上线通知已发送,代码无任何报错,但你的大号 QQ 死活收不到消息,发消息也不回。
真相: NapCat 遇到了“幽灵假死”。本地 Token 尚未过期(所以不报错也不弹二维码),但腾讯服务器端已单方面切断了连接(可能是异地登录或网络波动导致)。NapCat 还在徒劳地对空气发送数据。
解法(物理拔管与心脏起搏):
强行踢下线(最关键): 拿起手机登录小号,进入 设置 -> 账号安全 -> 登录设备管理,将列表里除了当前手机之外的设备(如 Linux/iPad/Mac)强制点击下线。这能从中央服务器作废死锁的 Token。
电击躯壳: 回到服务器终端执行: docker restart napcat_core docker logs --tail 50 -f napcat_core
重新认主: 盯着滚动的日志,系统会因 Token 失效被迫刷出全新的二维码。用手机小号重新扫码允许登录。
灵魂重载: 确认出现 Login Success 后,按 Ctrl+C 退出日志,随后重启 OpenClaw 容器并重新执行 Python 桥接脚本。全双工通讯瞬间满血复活!
如果你也想写一个连接 OpenClaw 大脑的桥接器,以下是摒弃 API 直连、实现记忆共享的最稳健逻辑框架:
Python
import asyncio
import websockets
import json
# 全局配置
WS_URL = "ws://172.**.**.1:3001" # NapCat 容器网关
TARGET_QQ = "13*******75" # 你的大号ID(用作记忆归档标识)
async def call_openclaw_agent(user_message: str) -> str:
"""调用 OpenClaw 原生 Agent,实现大脑与记忆共享"""
try:
# ⚡ 核心指令顺序法则:全局选项 --no-color 必须在 agent 之前!
process = await asyncio.create_subprocess_exec(
"openclaw", "--no-color", "agent",
"--to", TARGET_QQ,
"--message", user_message,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate()
if process.returncode == 0:
return stdout.decode('utf-8').strip()
else:
return f"🧠 中枢异常: {stderr.decode('utf-8').strip()}"
except Exception as e:
return f"❌ 桥接 OpenClaw 核心失败:{str(e)}"
async def main():
# 连接全双工 WebSocket
async with websockets.connect(WS_URL, ping_interval=20) as ws:
print("✅ 赛博触手已连接,等待指令...")
while True:
# 优雅挂起,等待 QQ 消息
msg = await ws.recv()
data = json.loads(msg)
# 过滤只处理指定大号的私聊消息
if data.get("post_type") == "message" and str(data.get("user_id")) == TARGET_QQ:
user_msg = data.get("raw_message", "").strip()
# 转发给本地 OpenClaw 大脑中枢
reply_text = await call_openclaw_agent(user_msg)
# 原路通过 WebSocket 将记忆回复发回 QQ
await ws.send(json.dumps({
"action": "send_private_msg",
"params": {"user_id": int(TARGET_QQ), "message": reply_text}
}))
if __name__ == "__main__":
asyncio.run(main())
不要畏惧排错,所有的报错日志都是通往完美的引路石。
在这个过程中,见识到了大语言模型的智能(完美推演算法)、倔强(手搓底层协议)以及愚蠢(位置法则翻车)。但只要你以造物主和架构师的视角,坚持第一性原理,辅以 Docker 容器的上帝权限进行调优,最终会得到一个令人惊叹的、拥有实体记忆、全平台无缝衔接的 AI 赛博生命体。
Stay Hungry, Stay Hardcore. 🦞
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。