最近在配置 OpenClaw 的 Discord 通道时,很多人都会卡在同一个点:
- 我明明收到了 heartbeat
- 但为什么没有“按 session_id 推送到对应频道”?
这个问题本身就很典型。因为这里混了两层系统:Discord Gateway 层和 OpenClaw 应用层。
这篇我把整个关系一次讲清楚,并结合我现在的实际用法(多频道分区 + 独立 Session)给出可直接落地的配置。
更新时间:2026-02-10
先把名词对齐:Server、Guild、Channel、Thread、DM
在 Discord 里:
- Server 就是 Guild
- Guild 下面有多个 Channel(文本频道)
- Channel 里还可能有 Thread(子线程)
- DM 是和用户的私聊,不属于 Guild
在 OpenClaw 里,消息并不是直接“绑在 Discord UI 结构”上,而是映射成 Session Key:
- DM 常见会进 main(默认)或 per-channel-peer(可配置)
- Guild Channel 通常按
agent:<agentId>:discord:channel:<channelId>隔离 - Thread 默认继承父频道规则,除非你显式单独配置
这就是第一层核心:Discord 是消息来源,OpenClaw 用 Session Key 管理上下文。
你看到的这段配置,具体代表什么
你给的片段:
"guilds": {
"GUILD_ID_REDACTED": {
"requireMention": false,
"tools": {
"allow": ["read", "exec", "web_fetch"],
"deny": []
},
"users": ["USER_ID_REDACTED"],
"channels": {
"CHANNEL_ID_CODE_LAB": {
"allow": true,
"requireMention": false
},
"CHANNEL_ID_BRAINSTORM": {
"allow": true,
"requireMention": false
}
}
}
}
上面示例已做脱敏处理,真实环境请替换为你自己的 ID。
它的含义是:
GUILD_ID_REDACTED:你的 Guild IDusers:允许触发机器人能力的用户白名单channels:允许交互的频道白名单requireMention: false:该范围内不用 @bot 也可触发tools.allow:在这个范围内可用的工具白名单
这块解决的是“谁能在什么频道触发什么能力”,不是 heartbeat 发送目标。
为什么 heartbeat 不会按 session_id 自动推到 Discord
这里最容易误解。
Heartbeat 相关其实有两种:
- Discord Gateway heartbeat(op1/op11)
- OpenClaw heartbeat(定时 agent turn)
Discord Gateway 的 session_id 是给断线恢复(Resume)用的,不是业务消息路由键。
OpenClaw heartbeat 是否外发、发到哪,取决于:
agents.defaults.heartbeat.session:运行上下文在哪个 Sessionagents.defaults.heartbeat.target:发哪个渠道(discord/last/none)agents.defaults.heartbeat.to:发给谁(例如channel:<id>或user:<id>)
一句话:
session决定“在哪里思考”target + to决定“往哪里发消息”
你当前这种“分区使用”思路是对的
从你截图看,你已经在做很实用的分区:
- 常规区:
#rules、#极省客 - AI 代理区(独立 Session):
#code-lab、#brainstorm、#moltbook-feed
这种结构特别适合 OpenClaw:
#code-lab:实操、可执行任务,开放read/exec/web_fetch#brainstorm:偏讨论,建议减少高风险工具#moltbook-feed:可做通知/订阅汇总,少交互多广播
你可以继续沿这个方向,把“频道职责”写死成策略,而不是靠临时 prompt 管。
一套更稳的配置模板(可直接改)
{
"session": {
"dmScope": "per-channel-peer"
},
"channels": {
"discord": {
"token": "${DISCORD_BOT_TOKEN}",
"heartbeat": {
"showOk": true,
"showAlerts": true
},
"guilds": {
"GUILD_ID_REDACTED": {
"requireMention": false,
"users": ["USER_ID_REDACTED"],
"tools": {
"allow": ["read", "exec", "web_fetch"],
"deny": []
},
"channels": {
"CHANNEL_ID_CODE_LAB": { "allow": true, "requireMention": false },
"CHANNEL_ID_BRAINSTORM": { "allow": true, "requireMention": false }
}
}
}
}
},
"agents": {
"defaults": {
"heartbeat": {
"every": "30m",
"session": "agent:YOUR_AGENT_ID:heartbeat",
"target": "discord",
"to": "channel:YOUR_CHANNEL_ID"
}
}
}
}
这份配置做了三件事:
- DM 不再全部挤进 main(降低上下文串线)
- heartbeat 用独立 session 跑(不污染日常对话)
- heartbeat 固定发
#code-lab(或你指定的频道)
一键命令版(不想手改 JSON)
openclaw config set agents.defaults.heartbeat.target "discord"
openclaw config set agents.defaults.heartbeat.to "channel:YOUR_CHANNEL_ID"
openclaw config set channels.discord.heartbeat.showOk true --json
openclaw config set session.dmScope "per-channel-peer"
openclaw config set agents.defaults.heartbeat.session "agent:YOUR_AGENT_ID:heartbeat"
openclaw system event --text "heartbeat test" --mode now
如果想静默运行不发外部消息:
openclaw config set agents.defaults.heartbeat.target "none"
Bot 添加与权限,一次说全
1) 在 Discord Developer Portal 建 Bot
- 创建 Application
- 新建 Bot
- 复制 Bot Token
2) 打开必要 Intents
至少包括:
- Guild Messages
- Direct Messages
- Message Content(多数文本场景需要)
3) OAuth2 邀请到目标 Guild
常见权限:
- View Channels
- Send Messages
- Read Message History
-(可选)Manage Messages / Add Reactions
建议最小权限原则,不要一开始就给 Administrator。
4) OpenClaw 侧最小配置
channels.discord.token或环境变量DISCORD_BOT_TOKENchannels.discord.guilds.<guildId>.channels.<channelId>.allow=true- 如需免 @ 触发,把
requireMention=false
5) 快速验证
openclaw channels status --probeopenclaw doctor- 在目标频道发一条最短消息,看是否入队并有回复
常见故障与定位顺序
现象:Bot 在线但频道不回复
优先查:
- 频道权限(View/Send/History)
guilds/channels/users白名单是否命中- 是否被
requireMention拦住
现象:Heartbeat 明明执行了,但频道没看到
优先查:
target是否是nonetarget=last时 last 目标是否可解析- 是否仅返回
HEARTBEAT_OK且showOk=false - heartbeat 运行 session 和你观察的会话是不是同一个
现象:上下文串线
优先查:
session.dmScope是否仍是main- heartbeat 是否复用了 main session
- 频道是否应该拆成独立 session 但没拆
一个实用的频道治理建议
如果你已经有多频道分区,建议再加一层“通道职责表”:
#code-lab:允许 exec,产出代码和命令#brainstorm:禁 exec,仅讨论方案#moltbook-feed:只接收 heartbeat/订阅消息
这样你后面做自动化时,就能把“工具权限、消息路由、会话隔离”保持一致,不会越跑越乱。