Skip to content

Daiyimo/openclaw-napcat

Repository files navigation

OpenClaw QQ 插件(适配 openclaw-docker)

通过 OneBot v11 协议(NapCat)将 QQ 接入 OpenClaw AI 框架。


架构概览

┌─────────────────────────────────────────────────────────────────┐
│                        OpenClaw 容器/进程                         │
│                                                                 │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │  @openclaw/qq 插件                                         │  │
│  │                                                           │  │
│  │  gateway/            outbound/          admin-commands     │  │
│  │  ┌────────────┐     ┌─────────────┐    ┌─────────────┐   │  │
│  │  │ connection │     │  send-text   │    │ /ping /logs │   │  │
│  │  │ inbound    │     │  send-media  │    │ /groups ... │   │  │
│  │  │ lifecycle  │     └─────────────┘    └─────────────┘   │  │
│  │  └────────────┘                                           │  │
│  │       ↑ 消息事件          ↓ 发送指令                        │  │
│  │  ┌─────────────────────────────────────────────────────┐  │  │
│  │  │         OneBotClient (client.ts)                     │  │  │
│  │  │   正向WS ←→ 反向WS Server ←→ HTTP API (带重试)       │  │  │
│  │  └─────────────────────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────────────────┘  │
│                          ↕                                       │
└──────────────────────────┼──────────────────────────────────────┘
                           │ OneBot v11 协议
┌──────────────────────────┼──────────────────────────────────────┐
│  NapCat 容器/进程         │                                      │
│  HTTP :3000  ←───────────┘ (发送消息)                            │
│  WS Client   ────────────→ :3002 (反向WS,接收事件)              │
└─────────────────────────────────────────────────────────────────┘

消息处理流水线:

入站消息 → 去重 → 黑白名单 → 静默关键词 → 频控
  → 管理命令拦截 → 触发检测(@/关键词/旁观) → AI 派发
    → 回复防抖合并 → 分片/TTS/Markdown → 发送

功能

  • 多通道连接:正向 WebSocket / 反向 WebSocket / HTTP API 三通道互备
  • 灵活触发:@机器人、关键词、戳一戳、旁观模式(AI 自主决定是否发言)
  • 消息防抖:AI 连续输出自动合并为一条消息,避免轰炸
  • 跨会话投递[TO:group:群号] 前缀或 /sendto 命令发送到任意目标
  • 配置热重载/reload 即时生效,无需重启
  • 群路由按需刷新/groups 命令手动注册群路由,解决 cron 投递问题
  • HTTP 重试:指数退避自动重试,5xx/网络错误不丢消息
  • 智能表情:15 种关键词场景自动贴表情
  • 管理命令/ping /status /version /logs /reload /groups /sendto /mute /kick /temperature
  • 安全管控:Token 鉴权、群组白名单、用户黑名单、入站频控、静默关键词
  • Docker 部署curl | bash 一键安装,跨服务器远程一键升级

特色功能

/groups — 群路由按需刷新

机器人加入了新群但 cron 投递报错"找不到会话"?发 /groups 即可:

/groups
→ ✅ 已刷新 5 个群路由,cron 投递现在可用

原理:调用 getGroupList() 拉取所有已加入群,为每个群注册 session 路由。无需重启容器。

友军识别(Bot-to-Bot Recognition)

多个 bot 在同一群会产生循环对话?开启 ignoreSenderBot(默认 true),bot 消息会被自动过滤:

四层检测机制:

  1. 手动白名单knownBotIds):最高优先级,适用于不支持签名的 bot
  2. sender.bot 字段:OneBot v11 标准字段,部分 bot 框架会设置
  3. 自维护缓存:通过签名自动发现并缓存(持久化到 ~/.openclaw/napcat-qq/data/known-bots-<accountId>.json),后续无需任何标记也能识别
  4. 签名检测(in-band,仅 visible / zero-width 模式启用):见下表
  5. (v1.9.2 移除) 协议层握手:因 OneBot json 段在 QQ 客户端渲染为可见卡片消息,会启动广播 spam。接收侧仍保留作防御性兜底。

冷启动历史回填:bot 启动时拉取每个群最近 30 条历史,扫描文本签名,自动回填 known-bots-store。解决"对方 bot 之前发过签名,本 bot 启动后才入群"的不对称时序问题。

友军抑制:检测到其他 bot 活跃后,本 bot 会静默 botSuppressionMs 毫秒(默认 120 秒)

{
  "ignoreSenderBot": true,
  "botSuppressionMs": 120000,
  "knownBotIds": [123456789, 987654321],
  "botSignatureStyle": "visible"
}
# Docker 环境变量
QQ_IGNORE_SENDER_BOT: "true"
QQ_BOT_SUPPRESSION_MS: "120000"
QQ_KNOWN_BOT_IDS: "123456789,987654321"  # 手动 bot 白名单
QQ_BOT_SIGNATURE_STYLE: visible           # 默认:[BOT:xxx] 文本签名

签名样式对比(v1.9.2+):

样式 格式 用户文本 启动 spam 适用场景
visible(默认) [BOT:12345678] 拼到消息末尾 ❌ 可见 ✅ 无 跨框架 bot 兼容,可靠
zero-width 零宽字符 U+200B/U+200C ✅ 不可见 ✅ 无 美观优先,99% 场景有效
none 无任何文本标记 ✅ 干净 ✅ 无 仅靠 sender.bot / knownBotIds / cache

v1.9.0/1.9.1 删除说明:早先的 metadata 模式(用 OneBot json 段握手)被完全移除——json 段在 QQ 客户端会渲染为可见卡片消息,导致启动时向所有群广播 spam 卡片。

私聊不追加签名。账号断开重连时持久化 cache 跨重启保留,新加入的群通过冷启动回填自动发现历史中的 bot。

回复格式硬约束(v1.9.1+)

防止 reasoning 类模型(Claude with extended thinking / o1 / o3 等)把 CoT 混到回复里。

# Docker 环境变量
QQ_RESPONSE_GUIDELINES: ""  # 不设置 = 使用默认硬约束;设 "" = 关闭约束;设自定义文本 = 替换默认

默认约束摘要:

  • 不输出内部推理 / 用户行为分析 / 英文 meta 注释
  • 群聊 50 字以内,信息密度优先
  • 不"八股"结构(不用首先/其次/最后)
  • 语言跟用户
  • 多 bot 共存不复读其他 bot
  • 旁听没想法的回复 [SILENT]

完整内容见 src/constants.tsDEFAULT_RESPONSE_GUIDELINES

旁观模式(Passive Mode)

AI 监听群聊所有消息,自主判断是否参与对话,无需 @:

推荐:使用 temperature 快速调节

{
  "passiveMode": {
    "enabled": true,
    "temperature": 50
  }
}

temperature 是 0–100 的整数,控制主动程度:0=几乎不插话,50=均衡(默认),100=很活跃。等价于手动设置 cooldownMs / minIntervalMs / botSuppressionMs 三个毫秒参数。

也可继续使用细粒度参数:

{
  "passiveMode": {
    "enabled": true,
    "cooldownMs": 10000,
    "minIntervalMs": 30000,
    "botSuppressionMs": 120000,
    "systemPrompt": "你是一个观察者,仅在值得发言时回复,否则输出 [SILENT]"
  }
}
  • cooldownMs:实质回复后的冷却时间(默认 10 秒)
  • minIntervalMs:最小触发间隔,含 [SILENT] 响应(默认 30 秒),防止 AI 被频繁调用
  • botSuppressionMs:友军识别抑制时长(默认 120 秒),检测到其他 bot 回复后静默
  • temperature:主动回复温度(0–100),设置后覆盖上述三个毫秒参数

群组白名单

Bot 只在指定群聊中响应,其他群自动忽略:

QQ_ALLOWED_GROUPS: "123456789,987654321"   # 逗号分隔的群号,留空=所有群
{ "allowedGroups": [123456789, 987654321] }

静默关键词过滤

群里有其他 bot 指令(如 ww签到)会误触发?配置 silentKeywords 直接屏蔽:

QQ_SILENT_KEYWORDS: "ww,签到,打卡"   # 包含任一关键词的消息直接丢弃

消息防抖合并

AI 连续输出多条碎片消息时,自动等待并合并为一条发送:

{ "deliverDebounce": { "enabled": true, "windowMs": 1500, "maxWaitMs": 8000 } }

休眠模式

夜间不想被 bot 打扰?配置 sleepMode 让 bot 在指定时段自动休眠,仅响应 @ 和关键词触发:

{ "sleepMode": { "enabled": true, "startHour": 23, "endHour": 7 } }
# Docker 环境变量
QQ_SLEEP_MODE_ENABLED: "true"
QQ_SLEEP_MODE_START_HOUR: "23"
QQ_SLEEP_MODE_END_HOUR: "7"
  • startHour / endHour:使用服务器本地时间,支持跨午夜(如 23→7 表示晚上 11 点到早上 7 点)
  • 休眠期间:@机器人 + 关键词触发 → 正常响应;被动模式/旁观模式/名字触发 → 全部静默
  • 私聊不受影响

跨会话投递

AI 回复中使用 [TO:group:群号]内容 可发送到任意群/用户,绕过 session 限制。管理员也可用 /sendto group:群号 内容 手动发送。


Docker 部署

环境要求:openclaw >= 2026.7.1;Node.js >=22.22.3 <23 || >=24.15.0 <25 || >=25.9.0

排障提示:openclaw 2026.7.1 起引入 crash-loop breaker——gateway 多次不干净启动后,频道不会自动启动(日志出现 channel autostart suppressed by crash-loop breaker),需手动执行 channels.start 恢复。

docker-compose.yml 完整示例(点击展开)
services:
  # ── NapCat:QQ 协议端 ──────────────────────────────────────
  napcat:
    image: mlikiowa/napcat-docker:latest
    container_name: napcat
    volumes:
      - ./napcat-data:/app/napcat/config
    ports:
      - "6099:6099"       # WebUI(首次扫码登录)
      - "3000:3000"       # HTTP API
    restart: unless-stopped

  # ── OpenClaw + QQ 插件 ─────────────────────────────────────
  openclaw:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw
    user: "0:0"
    depends_on:
      - napcat
    ports:
      - "18789:18789"     # OpenClaw WebUI
      - "3002:3002"       # 反向 WS(NapCat 连入)
    volumes:
      - ./openclaw-data:/home/node/.openclaw
    environment:
      HOME: /home/node
      TZ: Asia/Shanghai
      OPENCLAW_GATEWAY_BIND: lan
      OPENCLAW_GATEWAY_TOKEN: <你的gateway-token>
      OPENCLAW_EXTRA_EXTENSIONS_DIR: /home/node/.openclaw/extensions
      # ── NapCat 连接 ─────────────────────────────────────
      QQ_HTTP_URL: http://napcat:3000
      QQ_REVERSE_WS_PORT: "3002"
      QQ_ACCESS_TOKEN: <你的napcat-token>
      # ── 权限 ────────────────────────────────────────────
      QQ_ADMINS: "123456789"           # 管理员 QQ 号,多个用逗号分隔
      QQ_REQUIRE_MENTION: "true"       # 群聊是否需要 @ 触发
      QQ_ALLOWED_GROUPS: ""            # 群组白名单,逗号分隔,留空=所有群
      QQ_BLOCKED_USERS: ""             # 用户黑名单,逗号分隔
      # ── 友军识别 ─────────────────────────────────────────
      QQ_IGNORE_SENDER_BOT: "true"     # 过滤 sender.bot=true 的消息
      QQ_BOT_SUPPRESSION_MS: "120000"  # 友军抑制时长(ms),0=禁用
      QQ_KNOWN_BOT_IDS: ""             # 手动 bot 白名单,逗号分隔的 QQ 号
      QQ_BOT_SIGNATURE_STYLE: visible  # 签名样式:visible | zero-width
      # ── 行为 ────────────────────────────────────────────
      QQ_SYSTEM_PROMPT: ""             # 自定义系统提示词
      QQ_HISTORY_LIMIT: "5"            # 携带历史消息条数
      QQ_MARKDOWN_MODE: passthrough    # Markdown 处理:passthrough | strip | native
      QQ_RATE_LIMIT_MS: "1000"         # 发送限速(ms)
      QQ_INBOUND_RATE_LIMIT_MS: "0"   # 入站频控(ms),0=禁用
      QQ_KEYWORD_TRIGGERS: ""          # 无需 @ 的触发关键词,逗号分隔
      QQ_SILENT_KEYWORDS: ""           # 静默关键词,命中即丢弃
      QQ_SLEEP_MODE_ENABLED: "false"   # 休眠模式,默认关闭
      QQ_SLEEP_MODE_START_HOUR: "23"   # 休眠开始小时(0-23)
      QQ_SLEEP_MODE_END_HOUR: "7"      # 休眠结束小时(0-23)
      # ── 旁观模式 ─────────────────────────────────────────
      QQ_PASSIVE_MODE_ENABLED: "false" # 是否启用旁观模式
      QQ_PASSIVE_MODE_COOLDOWN_MS: "10000"      # 实质回复冷却(ms)
      QQ_PASSIVE_MODE_MIN_INTERVAL_MS: "30000"  # 最小触发间隔(ms)
      QQ_PASSIVE_MODE_TEMPERATURE: "50"         # 主动回复温度(0-100),覆盖三个毫秒参数
    restart: unless-stopped

配置说明:

环境变量 必填 说明
OPENCLAW_GATEWAY_TOKEN OpenClaw 网关 Token,用于 WebUI 鉴权
QQ_HTTP_URL NapCat HTTP API 地址
QQ_REVERSE_WS_PORT 反向 WS 监听端口
QQ_ACCESS_TOKEN NapCat 鉴权 Token(需与 NapCat 侧一致)
QQ_ADMINS 管理员 QQ 号
QQ_ALLOWED_GROUPS 群组白名单,留空=所有群
QQ_IGNORE_SENDER_BOT 过滤其他 bot 消息,默认 true
QQ_KNOWN_BOT_IDS 手动 bot 白名单(QQ 号),适用于不支持签名的 bot
QQ_BOT_SIGNATURE_STYLE 签名样式:visible(默认)或 zero-width
QQ_PASSIVE_MODE_ENABLED 旁观模式,默认 false
QQ_PASSIVE_MODE_TEMPERATURE 主动回复温度(0–100),覆盖三个毫秒参数

NapCat 侧配置onebot11_<QQ号>.json):

{
  "network": {
    "httpServers": [{
      "enable": true, "port": 3000, "host": "0.0.0.0",
      "messagePostFormat": "array", "token": "<同 QQ_ACCESS_TOKEN>"
    }],
    "websocketClients": [{
      "enable": true, "url": "ws://openclaw:3002",
      "messagePostFormat": "array", "token": "<同 QQ_ACCESS_TOKEN>",
      "reconnectInterval": 5000
    }]
  }
}

首次部署:

docker compose up -d
docker exec -it openclaw sh -c \
  "curl -fsSL https://raw.githubusercontent.com/Daiyimo/openclaw-napcat/main/scripts/docker-install.sh | bash"
docker compose restart openclaw
docker exec -it openclaw openclaw onboard   # 配置 AI 模型
docker compose restart openclaw

远程一键升级(跨服务器)

已有实例的升级,在宿主机上执行一行命令即可:

curl -fsSL https://raw.githubusercontent.com/Daiyimo/openclaw-napcat/main/scripts/remote-upgrade.sh | bash

国内加速(raw.githubusercontent.com 被墙时):

curl -fsSL https://ghfast.top/https://raw.githubusercontent.com/Daiyimo/openclaw-napcat/main/scripts/remote-upgrade.sh | bash

自定义容器名或数据目录:

CONTAINER_NAME=my-bot DATA_DIR=/my/data curl -fsSL ... | bash

升级流程:下载源码 → 备份 → 容器内编译 → 部署 → 重启。失败自动回滚。


详细部署指南见 docs/DOCKER.md


快速配置(非 Docker)

~/.openclaw/openclaw.json 中添加:

{
  "channels": {
    "napcat": {
      "reverseWsPort": 3002,
      "httpUrl": "http://<NapCat地址>:3000",
      "accessToken": "你的Token",
      "admins": [你的QQ号]
    }
  }
}

Cron 定时任务

OpenClaw 的 cron 系统支持定时执行任务并投递结果到 QQ 群。NapCat 插件提供两种投递模式:

模式 说明 适用场景
default OpenClaw announce 投递(走 message tool → napcat 插件) 简单文本消息
napcat 直接调用 NapCat HTTP API 发送(delivery=none,cron 内部 curl) 需要可靠群发、避免 message tool 路由问题

交互式创建

在 OpenClaw 容器内执行:

node scripts/new-cron.cjs

按提示输入任务名、cron 表达式,选择投递模式。

修复现有任务

如果已有 cron 任务出现投递失败(Channel napcat is unavailable for message actions),执行:

node scripts/fix-cron.cjs

该脚本会自动将所有 NapCat 相关 cron 任务修复为 delivery=none + curl 直发模式,并注入完整的 HA Token。

手动修复(单任务)

openclaw cron edit <job-id> \
  --no-deliver \
  --command-argv '["sh","-lc","curl -s -X POST http://napcat:3000/send_group_msg ..."]' \
  --command-env HA_TOKEN=<你的完整token>

查看 cron 列表

openclaw cron list
# 或 JSON 格式
openclaw cron list --json

常用配置项

配置项 类型 默认值 说明
reverseWsPort number - 反向 WS 监听端口
httpUrl string - NapCat HTTP API 地址
accessToken string - 鉴权 Token
admins number[] [] 管理员 QQ 号
requireMention boolean true 群聊是否需要 @ 触发
allowedGroups number[] [] 群组白名单(空=全部)
blockedUsers number[] [] 用户黑名单
ignoreSenderBot boolean true 过滤其他 bot 消息,防止循环对话
knownBotIds number[] [] 手动 bot 白名单,适用于不支持签名的 bot
botSignatureStyle string "visible" 签名样式:visible(默认,[BOT:xxx] 文本签名)/ zero-width / none
debug boolean false 开启消息处理流水线的详细诊断日志(@mention / bot 过滤 / 表情),排查问题时临时开启
botSuppressionMs number 120000 友军抑制时长(ms),0=禁用
keywordTriggers string[] [] 无需 @ 的触发关键词
silentKeywords string[] [] 静默关键词(命中即丢弃)
historyLimit number 5 携带历史消息条数
rateLimitMs number 1000 发送限速(ms)
passiveMode object - 旁观模式配置,支持 temperature(0–100)快速调节
deliverDebounce object - 消息防抖配置
sleepMode object - 休眠模式:夜间静默,仅 @和关键词触发

完整配置见 docs/CONFIG.md


文档


License

MIT

About

适用于openclaw的napcat插件

Resources

Stars

42 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors