微信 Telegram Discord 平台集成实战 —— 平台认证、Intent 配置、常见问题排查、消息收发
简介
在上一篇中,我们全面了解了 Hermes Agent 的 Gateway 多平台架构。架构是骨架,但真正的"血肉"在于与各个平台的具体集成。
今天,我们将进入实战环节,手把手教你将 Hermes Agent 接入三个最主流的消息平台:
- 微信(WeChat) —— 中文用户最多的即时通讯平台
- Telegram —— 全球流行的加密通讯平台,Bot API 极其成熟
- Discord —— 开发者和游戏社区首选的协作平台
每个平台都有其独特的认证方式、消息格式、权限模型和限制条件。本文将带你:
- 完成平台认证:从零开始创建 Bot、获取 Token、配置权限
- 配置 Intent(意图):精确控制 Agent 在什么场景下响应什么消息
- 排查常见问题:连接失败、消息丢失、权限不足、限流退避
- 实现消息收发:从简单文本到富媒体交互的完整代码示例
目标:读完本文后,你能独立完成三大平台的接入,并具备排查和解决问题的能力。
目录
微信(WeChat)平台集成
1.1 平台认证配置
微信平台的接入方式有几种,我们主要介绍最常用的 个人号 Bot 方案(基于 itchat/ComWeChatBot 协议):
# ~/.hermes/adapters/wechat/config.yaml
adapter:
name: "wechat"
version: "2.3.0"
# 认证配置
auth:
# 方式一:扫码登录(个人号)
login_method: "qr_scan"
qr_callback: "console" # console | webhook | file
# 方式二:企业微信应用(推荐生产环境)
# login_method: "enterprise"
# corp_id: "ww1234567890"
# agent_id: "1000002"
# corp_secret: "${WECHAT_CORP_SECRET}"
# 方式三:微信公众号
# login_method: "official"
# app_id: "wx1234567890"
# app_secret: "${WECHAT_APP_SECRET}"
# token: "${WECHAT_VERIFY_TOKEN}"
# 功能配置
features:
text: true
image: true
voice: true
video: false # 个人号暂不支持
file: true
sticker: true
red_packet: false # 红包不支持
# 安全配置
security:
# 白名单模式:只有这些用户/群才能与 Agent 交互
whitelist:
users:
- "wxid_abc123"
- "wxid_def456"
groups:
- "room_xyz789"
# 黑名单模式
blacklist:
users: []
groups: []
# 敏感词过滤
blocked_keywords:
- "密码"
- "token"
- "密钥"启动与扫码
# 启动微信适配器
hermes gateway adapters start wechat
# 输出:
# ═══════════════════════════════════════════════
# WeChat Adapter Starting
# ═══════════════════════════════════════════════
#
# [1/3] 初始化连接...
# ✓ WebSocket 已连接
#
# [2/3] 等待登录...
# 请使用微信扫描下方二维码登录:
#
# ┌──────────────────────────┐
# │ │
# │ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
# │ ▓▓ ▓▓ │
# │ ▓▓ ▓▓▓▓▓▓ ▓▓ │
# │ ▓▓ ▓▓ ▓▓ ▓▓ │
# │ ▓▓ ▓▓▓▓▓▓ ▓▓ │
# │ ▓▓ ▓▓ │
# │ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
# │ │
# └──────────────────────────┘
#
# 或使用手机打开: https://hermes.agent/wx/login/abc123
#
# [3/3] 登录成功!
# ✓ 昵称: Hermes Bot
# ✓ 微信号: hermes_bot_001
# ✓ 好友数: 156
# ✓ 群聊数: 23
#
# ✅ WeChat Adapter 就绪1.2 微信消息收发
// 微信适配器消息处理示例
const wechatAdapter = {
// 接收消息
onMessage(async (msg) => {
// msg 结构
/*
{
type: "text" | "image" | "voice" | "video" | "file" | "sticker",
from: "wxid_abc123",
to: "hermes_bot_001",
chat: "wxid_abc123", // 私聊 = from, 群聊 = room_id
isGroup: false,
content: "帮我写一个冒泡排序",
timestamp: 1716393600,
// 图片/文件特有字段
mediaUrl: "https://...",
fileSize: 102400,
}
*/
// 处理文本消息
if (msg.type === "text") {
// 发送给 Agent 处理
const reply = await agent.process({
platform: "wechat",
userId: msg.from,
chatId: msg.chat,
content: msg.content,
isGroup: msg.isGroup
});
// 发送回复
await this.sendReply(msg.chat, reply);
}
// 处理图片消息(OCR 或图像分析)
if (msg.type === "image") {
const analysis = await agent.analyzeImage(msg.mediaUrl);
await this.sendText(msg.chat, analysis.description);
}
}),
// 发送回复
async sendReply(chatId, reply) {
// 微信不支持 Markdown,需要格式化
const formattedText = this.formatForWechat(reply.content);
if (formattedText.length > 2000) {
// 超长消息拆分发送
const chunks = this.splitMessage(formattedText, 2000);
for (const chunk of chunks) {
await this.sendText(chatId, chunk);
await this.delay(500); // 避免发送过快
}
} else {
await this.sendText(chatId, formattedText);
}
// 如果有代码,转为图片发送
if (reply.hasCode) {
const codeImage = await this.codeToImage(reply.code);
await this.sendImage(chatId, codeImage);
}
// 如果有文件
if (reply.files) {
for (const file of reply.files) {
await this.sendFile(chatId, file);
}
}
},
// 微信格式转换
formatForWechat(text) {
return text
.replace(/\*\*(.+?)\*\*/g, '【$1】') // **bold** → 【bold】
.replace(/\*(.+?)\*/g, '$1') // *italic* → italic
.replace(/`(.+?)`/g, '「$1」') // `code` → 「code」
.replace(/^#\s+(.+)$/gm, '=== $1 ===') // # heading → === heading ===
.replace(/^##\s+(.+)$/gm, '-- $1 --') // ## heading → -- heading --
.replace(/^###\s+(.+)$/gm, '· $1 ·'); // ### heading → · heading ·
}
};Telegram 平台集成
2.1 创建 Telegram Bot
步骤一:通过 BotFather 创建 Bot
1. 在 Telegram 中搜索 @BotFather
2. 发送 /newbot
3. 按提示输入 Bot 名称和用户名(必须以 bot 结尾)
4. 获取 Bot Token(格式:123456789:ABCdefGHIjklMNOpqrsTUVwxyz)
5. 保存 Token,后续配置需要用到步骤二:配置 Bot 权限
# 通过 BotFather 设置
/setdescription - 设置 Bot 描述
/setabouttext - 设置 About 信息
/setuserpic - 设置 Bot 头像
/setcommands - 设置 Bot 命令列表
# 推荐命令列表:
start - 开始对话
help - 查看帮助
status - 查看 Agent 状态
clear - 清空当前对话上下文
skills - 查看已加载的技能步骤三:配置 Hermes
# ~/.hermes/adapters/telegram/config.yaml
adapter:
name: "telegram"
version: "2.1.0"
# 认证配置
auth:
bot_token: "${TELEGRAM_BOT_TOKEN}"
# 或使用环境变量
# bot_token_env: "TELEGRAM_BOT_TOKEN"
# 连接方式
connection:
method: "webhook" # webhook | long_polling
# Webhook 配置(推荐生产环境)
webhook:
url: "https://your-domain.com/hermes/telegram/webhook"
secret_token: "${TELEGRAM_WEBHOOK_SECRET}"
max_connections: 40
# Long Polling 配置(适合开发/内网)
long_polling:
timeout: 30 # 秒
allowed_updates:
- "message"
- "edited_message"
- "callback_query"
# 功能配置
features:
text: true
image: true
voice: true # 语音转文字
video: true
file: true
sticker: true
location: true
contact: true
poll: true
inline_keyboard: true # 内联按钮
# Markdown 支持
formatting:
parse_mode: "MarkdownV2" # Markdown | MarkdownV2 | HTML
# MarkdownV2 需要转义的字符
escape_chars: "_*[]()~`>#+-=|{}.!"
# Bot 行为
bot:
# 只响应 @提及的消息
mention_only_in_groups: true
# 自动删除 Bot 消息(减少刷屏)
auto_delete:
enabled: false
delay: 60 # 秒
# 打字指示器
typing_indicator: true
# 消息长度限制
max_message_length: 40962.2 Telegram 消息收发
// Telegram 适配器消息处理
const telegramAdapter = {
async onMessage(msg) {
/*
Telegram 消息结构:
{
message_id: 123,
from: { id: 12345, username: "alice", first_name: "Alice" },
chat: { id: -100987654, type: "supergroup", title: "Dev Group" },
date: 1716393600,
text: "@hermes_bot 帮我写一个冒泡排序",
entities: [
{ type: "mention", offset: 0, length: 12 }
],
reply_to_message: { ... }, // 如果是回复消息
}
*/
// 检查是否被 @提及(群聊)
if (msg.chat.type !== "private") {
const mentions = msg.entities?.filter(e => e.type === "mention") || [];
const isMentioned = mentions.some(m =>
msg.text.substring(m.offset, m.offset + m.length) === "@hermes_bot"
);
if (!isMentioned && !msg.reply_to_message?.from?.is_bot) {
return; // 未被 @提及且不回复 Bot,忽略
}
}
// 处理消息
const cleanContent = this.cleanContent(msg.text, msg.entities);
const reply = await agent.process({
platform: "telegram",
userId: String(msg.from.id),
userName: msg.from.username || msg.from.first_name,
chatId: String(msg.chat.id),
chatName: msg.chat.title,
isGroup: msg.chat.type !== "private",
content: cleanContent
});
// 发送回复(支持 MarkdownV2)
await this.sendMarkdown(msg.chat.id, reply.content);
// 如果有代码
if (reply.hasCode) {
await this.sendCode(msg.chat.id, reply.code, reply.language);
}
},
// 清理提及后的内容
cleanContent(text, entities) {
let clean = text;
const mentions = entities?.filter(e => e.type === "mention") || [];
for (const m of mentions) {
clean = clean.replace(text.substring(m.offset, m.offset + m.length), '').trim();
}
return clean || text;
},
// 发送 Markdown 消息
async sendMarkdown(chatId, text) {
// 转义 MarkdownV2 特殊字符
const escaped = this.escapeMarkdownV2(text);
await fetch(`https://api.telegram.org/bot${TOKEN}/sendMessage`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: chatId,
text: escaped,
parse_mode: 'MarkdownV2',
disable_web_page_preview: true
})
});
},
// 发送代码块
async sendCode(chatId, code, language = '') {
const text = `\`\`\`${language}\n${code}\n\`\`\``;
const escaped = this.escapeMarkdownV2(text);
await fetch(`https://api.telegram.org/bot${TOKEN}/sendMessage`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: chatId,
text: escaped,
parse_mode: 'MarkdownV2'
})
});
},
// MarkdownV2 转义
escapeMarkdownV2(text) {
return text.replace(/([_*\[\]()~`>#+\-=|{}.!])/g, '\\$1');
},
// 发送内联按钮
async sendWithButtons(chatId, text, buttons) {
/*
buttons = [
[
{ text: "确认", callback_data: "confirm" },
{ text: "取消", callback_data: "cancel" }
]
]
*/
await fetch(`https://api.telegram.org/bot${TOKEN}/sendMessage`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: chatId,
text: this.escapeMarkdownV2(text),
parse_mode: 'MarkdownV2',
reply_markup: {
inline_keyboard: buttons
}
})
});
}
};Discord 平台集成
3.1 创建 Discord Bot
步骤一:创建应用和 Bot
1. 访问 https://discord.com/developers/applications
2. 点击 "New Application",输入名称
3. 进入 "Bot" 标签页
4. 点击 "Add Bot"
5. 复制 Token(只显示一次!)
6. 配置 Privileged Gateway Intents:
✅ MESSAGE CONTENT INTENT
✅ SERVER MEMBERS INTENT(可选)
✅ PRESENCE INTENT(可选)步骤二:邀请 Bot 到服务器
1. 进入 "OAuth2" → "URL Generator"
2. 选择 Scopes:
✅ bot
✅ applications.commands(斜杠命令)
3. 选择 Bot Permissions:
✅ Send Messages
✅ Embed Links
✅ Attach Files
✅ Read Message History
✅ Add Reactions
✅ Manage Messages(可选)
✅ Use External Emojis
4. 复制生成的 URL,在浏览器中打开
5. 选择要添加的服务器步骤三:配置 Hermes
# ~/.hermes/adapters/discord/config.yaml
adapter:
name: "discord"
version: "2.0.0"
# 认证配置
auth:
bot_token: "${DISCORD_BOT_TOKEN}"
client_id: "${DISCORD_CLIENT_ID}"
# Gateway Intents(必须与 Dev Portal 中启用的一致)
intents:
- "Guilds" # 基本服务器事件
- "GuildMessages" # 消息事件
- "MessageContent" # 消息内容(需要 Privileged Intent)
- "GuildMembers" # 成员事件(可选)
# 功能配置
features:
text: true
image: true
voice: true # 语音频道
file: true
embeds: true # 富文本嵌入
buttons: true # 交互按钮
select_menus: true # 下拉选择
threads: true # 线程
slash_commands: true # 斜杠命令
# 斜杠命令配置
slash_commands:
- name: "hermes"
description: "向 Hermes Agent 提问"
options:
- name: "question"
type: "STRING"
description: "你的问题"
required: true
- name: "status"
description: "查看 Agent 状态"
- name: "clear"
description: "清空对话上下文"
- name: "skills"
description: "查看当前加载的技能"
# Bot 行为
bot:
# 活动状态(显示在 Bot 名字下方)
presence:
status: "online" # online | idle | dnd | invisible
activity:
type: "Watching" # Playing | Streaming | Listening | Watching | Competing
name: "your questions"
# 频道白名单
channel_whitelist: [] # 留空表示所有频道
# 仅响应 @提及
mention_only: true
# 删除触发消息(减少刷屏)
delete_trigger: false3.2 Discord 消息收发
// Discord 适配器消息处理
const discordAdapter = {
async onMessage(msg) {
/*
Discord 消息结构:
{
id: "123456789",
channel_id: "456789",
guild_id: "789012",
author: { id: "345678", username: "alice", discriminator: "1234" },
content: "@Hermes 帮我写一个冒泡排序",
mentions: [{ id: "bot_id", username: "Hermes" }],
attachments: [...],
embeds: [...],
reference: { message_id: "..." }, // 回复
}
*/
// 忽略 Bot 自己的消息
if (msg.author.bot) return;
// 检查 @提及
if (!msg.mentions?.some(m => m.id === this.botId)) {
return;
}
const cleanContent = msg.content
.replace(/<@!?\d+>/g, '') // 移除 @提及
.trim();
if (!cleanContent) return;
const reply = await agent.process({
platform: "discord",
userId: msg.author.id,
userName: msg.author.username,
chatId: msg.channel_id,
guildId: msg.guild_id,
isGroup: !!msg.guild_id,
content: cleanContent
});
// 发送回复
if (reply.hasCode && reply.code) {
await this.sendEmbedWithCode(msg.channel_id, reply.content, reply.code, reply.language);
} else {
await this.sendText(msg.channel_id, reply.content);
}
},
// 发送 Embed 消息(富文本)
async sendEmbedWithCode(channelId, text, code, language = '') {
await fetch(`https://discord.com/api/v10/channels/${channelId}/messages`, {
method: 'POST',
headers: {
'Authorization': `Bot ${TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: text,
embeds: [{
title: "📝 代码片段",
color: 0x5865F2, // Discord Blurple
fields: [
{
name: `语言: ${language || 'plaintext'}`,
value: `\`\`\`${language}\n${code.substring(0, 1000)}${code.length > 1000 ? '...' : ''}\n\`\`\``
}
],
footer: { text: `代码长度: ${code.length} 字符` },
timestamp: new Date().toISOString()
}]
})
});
},
// 发送带按钮的消息
async sendWithButtons(channelId, text, buttons) {
await fetch(`https://discord.com/api/v10/channels/${channelId}/messages`, {
method: 'POST',
headers: {
'Authorization': `Bot ${TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: text,
components: [{
type: 1, // Action Row
components: buttons.map(btn => ({
type: 2, // Button
label: btn.label,
style: btn.style || 1, // 1=Primary, 2=Secondary, 3=Success, 4=Danger, 5=Link
custom_id: btn.custom_id,
url: btn.url // Link 按钮需要
}))
}]
})
});
}
};Intent 配置详解
什么是 Intent(意图)?
Intent 是 Gateway 的意图识别与响应规则系统。它决定了 Agent 在什么条件下响应消息、如何响应、响应什么内容。
Intent 层次结构
Intent 配置层次:
│
├── 全局 Intent(global)
│ ├── 适用于所有平台
│ └── 基础过滤规则
│
├── 平台 Intent(per-platform)
│ ├── wechat: { ... }
│ ├── telegram: { ... }
│ └── discord: { ... }
│
├── 会话 Intent(per-session)
│ ├── 基于用户偏好
│ └── 基于对话上下文
│
└── 消息 Intent(per-message)
├── 基于消息内容
└── 基于消息类型Intent 配置文件
# ~/.config/hermes/intents.yaml
intents:
# 全局默认意图
global:
# 响应模式
response_mode: "mention" # always | mention | keyword | never
# 关键词触发
keywords:
- "@hermes"
- "hermes"
- "问"
# 忽略模式(正则)
ignore_patterns:
- "^/.*$" # 以 / 开头的命令
- "^\." # 以 . 开头
- "^ping$" # ping 测试
# 最大消息长度
max_content_length: 2000
# 自动回复阈值(匹配度低于此值不回复)
confidence_threshold: 0.6
# 微信意图
wechat:
# 群聊中只响应 @提及
groups:
response_mode: "mention"
# 但管理员消息始终响应
admin_whitelist:
- "wxid_admin1"
- "wxid_admin2"
# 私聊始终响应
private:
response_mode: "always"
# 特定群的特定规则
group_rules:
"room_tech_group":
response_mode: "keyword"
keywords: ["代码", "bug", "error", "求助"]
prefix_required: true
prefix: "@hermes"
"room_random_chat":
response_mode: "never" # 这个群不响应
# Telegram 意图
telegram:
groups:
response_mode: "mention"
# 回复 Bot 消息时也响应
reply_to_bot: true
private:
response_mode: "always"
# 支持斜杠命令
slash_commands:
"/hermes": "process" # 正常处理
"/clear": "clear_session" # 清空会话
"/status": "show_status" # 显示状态
"/help": "show_help" # 显示帮助
# Discord 意图
discord:
guilds:
response_mode: "mention"
reply_to_bot: true
# 频道级规则
channels:
"channel_help":
response_mode: "always" # 帮助频道始终响应
"channel_random":
response_mode: "never" # 灌水频道不响应
"channel_code_review":
response_mode: "keyword"
keywords: ["review", "检查", "看看"]
# 斜杠命令
slash_commands:
"/hermes": "process"
"/clear": "clear_session"
"/status": "show_status"Intent 运行时行为
消息到达 → Intent 引擎处理流程:
1. 检查全局 ignore_patterns
└── 匹配?→ 忽略消息
2. 检查平台级 response_mode
└── never?→ 忽略
└── always?→ 处理
└── mention?→ 检查是否 @提及
└── keyword?→ 检查是否包含关键词
3. 检查会话级规则(用户偏好、上下文)
└── 用户屏蔽了?→ 忽略
└── 用户 VIP?→ 优先处理
4. 计算置信度
└── 低于 threshold?→ 忽略
└── 高于 threshold?→ 处理
5. 执行动作
└── process → 发送给 Agent
└── clear_session → 清空上下文
└── show_status → 返回状态
└── show_help → 返回帮助
└── log_only → 记录但不回复常见问题排查手册
4.1 连接问题
问题:微信无法登录/扫码后断开
# 诊断命令
hermes gateway adapters diagnose wechat
# 输出排查:
# ═══════════════════════════════════════════
# WeChat 诊断报告
# ═══════════════════════════════════════════
#
# [✓] 网络连接正常
# [✓] WebSocket 端口可达
# [✗] 登录会话已过期
# [✓] Token 格式正确
# [✓] 服务器响应正常
#
# 建议操作:
# 1. 清除登录缓存:hermes gateway adapters reset wechat
# 2. 重新扫码登录:hermes gateway adapters start wechat
# 3. 如果频繁断连,检查是否被微信风控常见原因和解决方案:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 扫码后断连 | 微信安全策略 | 使用新号/降低频率/用企业微信 |
| 登录被拒 | 账号异常 | 检查账号状态,解除限制 |
| 心跳超时 | 网络不稳定 | 检查防火墙、代理设置 |
| 频繁掉线 | 协议更新 | 更新适配器到最新版本 |
问题:Telegram Webhook 设置失败
# 测试 Webhook URL 是否可达
curl -f https://your-domain.com/hermes/telegram/webhook
# 检查 SSL 证书
openssl s_client -connect your-domain.com:443
# 手动设置 Webhook
curl -X POST "https://api.telegram.org/bot${TOKEN}/setWebhook" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-domain.com/hermes/telegram/webhook",
"secret_token": "your-secret",
"max_connections": 40,
"allowed_updates": ["message", "edited_message", "callback_query"]
}'
# 查看当前 Webhook 信息
curl "https://api.telegram.org/bot${TOKEN}/getWebhookInfo"问题:Discord Bot 不响应消息
# 检查 Gateway Intents 是否启用
# 1. 登录 Discord Developer Portal
# 2. 进入 Bot 设置
# 3. 确认以下 Intent 已启用:
# ✅ MESSAGE CONTENT INTENT
# ✅ GUILD_MESSAGES
# 检查 Bot 权限
hermes gateway adapters diagnose discord
# 输出:
# [✓] Bot Token 有效
# [✓] Gateway 连接成功
# [✓] 已加入 3 个服务器
# [✗] MESSAGE CONTENT INTENT 未启用(Dev Portal)
# [✓] Bot 在目标频道有 Send Messages 权限
#
# 建议:在 Dev Portal 启用 MESSAGE CONTENT INTENT 并重新邀请 Bot4.2 消息问题
问题:消息发送失败/超时
# 增加超时配置
gateway:
message:
send_timeout: 30 # 发送超时(秒)
retry_count: 3 # 重试次数
retry_delay: 2 # 重试间隔(秒)
rate_limit:
# Telegram API 限制:每秒 30 条消息
telegram_rps: 25 # 留有余量
# Discord 没有明确限制,但建议控制
discord_rps: 10
# 微信没有 API,但有风控
wechat_rps: 5问题:Markdown 渲染异常
// Telegram MarkdownV2 转义示例
function escapeMarkdownV2(text) {
// 需要转义的字符:_ * [ ] ( ) ~ ` > # + - = | { } . !
return text.replace(/([_*\[\]()~`>#+\-=|{}.!])/g, '\\$1');
}
// Discord Markdown 不需要额外转义(由 SDK 处理)
// 但代码块中的内容需要注意
// 微信纯文本转换
function toWechatText(text) {
return text
.replace(/\*\*(.+?)\*\*/g, '【$1】')
.replace(/\*(.+?)\*/g, '$1')
.replace(/`([^`]+)`/g, '「$1」')
.replace(/^### (.+)$/gm, '· $1 ·')
.replace(/^## (.+)$/gm, '-- $1 --')
.replace(/^# (.+)$/gm, '=== $1 ===')
.replace(/^[-*] (.+)$/gm, '• $1')
.replace(/^\d+\. (.+)$/gm, '$1');
}问题:消息内容被截断
# 各平台消息长度限制
platforms:
wechat:
max_length: 2000 # 单条消息最大字符数
split_strategy: "smart" # 按段落分割
split_delay: 500 # 分割消息之间的延迟(ms)
telegram:
max_length: 4096
split_strategy: "markdown" # 保持 Markdown 完整性分割
split_delay: 300
discord:
max_length: 2000
split_strategy: "code_block" # 代码块优先保持完整
split_delay: 3004.3 权限问题
问题:Bot 无法发送消息到频道
# Discord 权限检查清单
# 1. Bot 角色必须有 "Send Messages" 权限
# 2. 频道覆盖权限不能禁止 Bot 发送消息
# 3. Bot 角色必须高于 "Everyone" 的权限设置
# 4. 如果频道是 NSFW,Bot 也需要相应权限
# Telegram 权限检查
# 1. Bot 必须是群组成员
# 2. 群组管理员需要授予 Bot 发送消息权限
# 3. 如果群组开启了 "Slow Mode",Bot 也受限制问题:Token 失效
# Telegram Token 刷新
# 1. 通过 @BotFather 发送 /revoke
# 2. 获取新 Token
# 3. 更新配置:
hermes config set telegram.bot_token NEW_TOKEN_HERE
# Discord Token 刷新
# 1. Dev Portal → Bot → Reset Token
# 2. 更新配置:
hermes config set discord.bot_token NEW_TOKEN_HERE
# 微信
# 个人号:重新扫码登录
hermes gateway adapters reset wechat
hermes gateway adapters start wechat
# 企业微信:Corp Secret 需要管理员在后台查看4.4 性能问题
问题:响应速度慢
# 诊断响应链路延迟
hermes gateway benchmark
# 输出:
# ═══════════════════════════════════════════
# 响应链路延迟分析
# ═══════════════════════════════════════════
#
# 平台接收 → 路由器: 2ms
# 路由器 → 会话管理: 1ms
# 会话管理 → Agent: 5ms
# Agent 推理: 2800ms ← 瓶颈在这里
# Agent → 格式化: 50ms
# 格式化 → 平台发送: 15ms
# ─────────────────────────────
# 总延迟: 2873ms
#
# 优化建议:
# 1. 使用更快的模型(如 Groq 提供超快推理)
# 2. 启用流式输出(Stream)减少感知延迟
# 3. 使用缓存减少重复计算# 优化配置
gateway:
# 启用流式输出
streaming:
enabled: true
chunk_size: 50 # 每块字符数
min_chunk_interval: 100 # 最小间隔(ms)
# 缓存配置
cache:
enabled: true
ttl: 3600 # 缓存过期时间(秒)
max_size: 1000 # 最大缓存条目数
# 并发控制
concurrency:
max_active_sessions: 10
queue_size: 50
queue_timeout: 60 # 队列超时(秒)消息收发实战
5.1 跨平台统一消息处理
// 统一消息处理器
class UnifiedMessageHandler {
constructor(agent) {
this.agent = agent;
this.platforms = {};
}
// 注册平台适配器
registerPlatform(platformName, adapter) {
this.platforms[platformName] = adapter;
adapter.onMessage(async (rawMsg) => {
const msg = adapter.normalize(rawMsg); // 标准化为 HermesMessage
await this.handleMessage(platformName, msg);
});
}
// 统一消息处理
async handleMessage(platformName, msg) {
console.log(`[${platformName}] 收到消息: ${msg.content.substring(0, 50)}...`);
// 1. Intent 检查
const intentResult = this.checkIntent(platformName, msg);
if (!intentResult.shouldProcess) {
console.log(`[${platformName}] 消息被过滤: ${intentResult.reason}`);
return;
}
// 2. 发送给 Agent 处理
const reply = await this.agent.process({
platform: platformName,
userId: msg.userId,
userName: msg.userName,
chatId: msg.chatId,
content: msg.content,
attachments: msg.attachments,
isGroup: msg.isGroup,
});
// 3. 平台适配输出
const adapter = this.platforms[platformName];
await this.sendPlatformReply(adapter, msg, reply);
}
// 平台适配回复
async sendPlatformReply(adapter, originalMsg, reply) {
const formatted = adapter.formatReply(reply);
// 根据平台特性发送
if (reply.type === 'text') {
await adapter.sendText(originalMsg.chatId, formatted.text);
} else if (reply.type === 'text_with_code') {
await adapter.sendText(originalMsg.chatId, formatted.text);
if (formatted.code) {
await adapter.sendCode(originalMsg.chatId, formatted.code, formatted.language);
}
} else if (reply.type === 'embed') {
await adapter.sendEmbed(originalMsg.chatId, formatted.embed);
}
// 处理文件附件
if (reply.files) {
for (const file of reply.files) {
await adapter.sendFile(originalMsg.chatId, file);
}
}
}
// Intent 检查
checkIntent(platformName, msg) {
const config = this.loadIntentConfig(platformName);
// 黑名单检查
if (config.blacklist?.users?.includes(msg.userId)) {
return { shouldProcess: false, reason: '用户黑名单' };
}
// 白名单检查
if (config.whitelist && !config.whitelist.users?.includes(msg.userId)) {
return { shouldProcess: false, reason: '不在白名单中' };
}
// 响应模式检查
const mode = config.response_mode || 'mention';
if (mode === 'never') {
return { shouldProcess: false, reason: '该频道不响应' };
}
if (mode === 'mention' && !msg.isMentioned) {
return { shouldProcess: false, reason: '未被提及' };
}
if (mode === 'keyword') {
const hasKeyword = config.keywords?.some(kw => msg.content.includes(kw));
if (!hasKeyword) {
return { shouldProcess: false, reason: '未匹配关键词' };
}
}
// 忽略模式检查
const ignoreMatch = config.ignore_patterns?.some(p => new RegExp(p).test(msg.content));
if (ignoreMatch) {
return { shouldProcess: false, reason: '匹配忽略模式' };
}
return { shouldProcess: true };
}
}5.2 富媒体交互示例
微信:代码转图片发送
// 微信代码图片生成
async function sendCodeAsWechatImage(chatId, code, language) {
// 1. 使用 puppeteer 渲染代码为图片
const html = `
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
</head>
<body>
<pre><code class="language-${language}">${escapeHtml(code)}</code></pre>
<script>hljs.highlightAll();</script>
</body>
</html>
`;
// 2. 截图
const imageBuffer = await renderHtmlToImage(html, {
width: 800,
height: 'auto',
padding: 20
});
// 3. 发送到微信
await wechat.sendImage(chatId, imageBuffer);
}Telegram:内联按钮交互
// Telegram 内联按钮 - 代码审查确认
async function sendReviewButtons(chatId, review) {
await telegram.sendWithButtons(chatId, `📋 代码审查完成
文件: ${review.file}
问题: ${review.issues} 个
评分: ⭐ ${review.score}/5
是否自动修复?`, [
[
{ text: "✅ 自动修复", callback_data: `fix:${review.file}` },
{ text: "❌ 跳过", callback_data: `skip:${review.file}` }
],
[
{ text: "📝 查看详情", url: review.detailUrl }
]
]);
}
// 处理按钮回调
telegram.onCallbackQuery(async (query) => {
const [action, file] = query.data.split(':');
if (action === 'fix') {
await agent.fixFile(file);
await telegram.answerCallbackQuery(query.id, { text: "✅ 已自动修复" });
} else if (action === 'skip') {
await telegram.answerCallbackQuery(query.id, { text: "⏭️ 已跳过" });
}
});Discord:Embed 消息展示
// Discord Embed - 任务完成报告
async function sendTaskReport(channelId, task) {
const embed = {
title: "🎉 任务完成",
color: 0x00ff00,
description: `**${task.name}** 已成功完成`,
fields: [
{ name: "执行时间", value: task.duration, inline: true },
{ name: "修改文件", value: String(task.filesModified), inline: true },
{ name: "通过率", value: `${task.passRate}%`, inline: true },
{ name: "输出", value: task.output.substring(0, 1000) }
],
thumbnail: { url: "https://..." },
footer: { text: `由 Hermes Agent 执行 | ${new Date().toLocaleString()}` },
timestamp: new Date().toISOString()
};
await discord.sendEmbed(channelId, embed);
}总结与下篇预告
本文深入三大消息平台(微信、Telegram、Discord)与 Hermes Agent 的集成实战,涵盖了从 Bot 创建、认证配置、Intent 规则到常见问题排查的完整流程。
核心要点回顾:
- 认证是第一步 —— 每个平台都有独特的认证流程,务必妥善保管 Token
- Intent 是核心 —— 精确控制 Agent 的响应行为,避免误触发和不响应
- 格式要适配 —— 微信纯文本、Telegram MarkdownV2、Discord Markdown,各有讲究
- 限制要尊重 —— 各平台都有消息长度、频率等限制,需要妥善处理
- 排查有套路 —— 连接问题、消息问题、权限问题、性能问题,各有诊断方法
三大平台快速对比:
| 维度 | 微信 | Telegram | Discord |
|---|---|---|---|
| 接入难度 | ⭐⭐⭐ | ⭐ | ⭐ |
| Bot API 成熟度 | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 消息格式 | 纯文本 | MarkdownV2 | Markdown |
| 富媒体支持 | 中 | 高 | 高 |
| 群管理 | 部分 | 完整 | 完整 |
| 适合场景 | 国内团队 | 国际团队 | 开发者社区 |
下篇预告
Hermes Agent 企业级部署与运维
在下一篇中,我们将转向生产环境,探讨:
- 🏢 多实例部署架构:负载均衡、高可用、故障转移
- 📊 监控与告警:Prometheus + Grafana 指标采集
- 🔒 安全加固:网络隔离、权限最小化、审计日志
- 💾 数据持久化:会话存储、技能备份、配置管理
- 🚀 CI/CD 流水线:自动化测试、蓝绿部署、回滚策略
敬请期待!
本系列文章持续更新中,欢迎 star 和分享。如有问题,请在评论区留言。