Feishu / Lark
Hermes Agent 可作为功能完整的 bot 接入 Feishu 和 Lark。接入后,你可以在私聊和群聊中与 agent 对话,在 home chat 中接收 cron 结果,并按标准网关流程收发文本、图片、音频和文件附件。
该集成支持两种连接模式:
websocket:推荐;Hermes 主动建立出站连接,无需公网 webhook 端点webhook:适合你已经有可访问的 HTTP 入口,希望由 Feishu/Lark 主动推送事件的场景
Hermes 的行为方式
| Context | Behavior |
|---|---|
| Direct messages | Hermes 会回复每一条消息。 |
| Group chats | 只有在群里显式 @ bot 时 Hermes 才会回复。 |
| Shared group chats | 默认按用户隔离共享群聊中的会话历史。 |
该共享群行为由 config.yaml 控制:
group_sessions_per_user: true
如果你明确希望整个群共享一段会话,可改为 false。
第 1 步:创建 Feishu / Lark App
推荐:扫码创建(一条命令完成)
hermes gateway setup
选择 Feishu / Lark,然后用 Feishu 或 Lark 手机端扫描二维码。Hermes 会自动创建一个权限配置正确的 bot 应用,并保存凭据。
备选:手动设置
- 打开开发者控制台:
- Feishu: https://open.feishu.cn/
- Lark: https://open.larksuite.com/
- 创建新应用
- 在 Credentials & Basic Info 中复制 App ID 与 App Secret
- 为应用启用 Bot 能力
- 运行
hermes gateway setup,选择 Feishu / Lark 并按提示输入这些凭据
请妥善保管 App Secret。任何获得该密钥的人都可以冒充你的应用。
第 2 步:选择连接模式
推荐:WebSocket 模式
如果 Hermes 运行在你的笔记本、工作站或私有服务器上,建议使用 WebSocket 模式;它无需公网 URL。官方 Lark SDK 会自动维护一条持久出站 WebSocket,并负责重连。
FEISHU_CONNECTION_MODE=websocket
要求: 需安装 websockets Python 包。SDK 会在内部处理连接生命周期、心跳和自动重连。
可选:Webhook 模式
如果你已经拥有可访问的 HTTP 入口,也可以选择 webhook 模式:
FEISHU_CONNECTION_MODE=webhook
此模式下,Hermes 会启动一个 aiohttp HTTP 服务,并在以下路径暴露 Feishu webhook:
/feishu/webhook
可自定义绑定地址与路径:
FEISHU_WEBHOOK_HOST=127.0.0.1 # default: 127.0.0.1
FEISHU_WEBHOOK_PORT=8765 # default: 8765
FEISHU_WEBHOOK_PATH=/feishu/webhook # default: /feishu/webhook
当 Feishu 发送 URL 验证挑战(type: url_verification)时,适配器会自动应答。
第 3 步:配置 Hermes
Option A: Interactive Setup
hermes gateway setup
Option B: Manual Configuration
把以下内容加入 ~/.hermes/.env:
FEISHU_APP_ID=cli_xxx
FEISHU_APP_SECRET=secret_xxx
FEISHU_DOMAIN=feishu
FEISHU_CONNECTION_MODE=websocket
# Optional but strongly recommended
FEISHU_ALLOWED_USERS=ou_xxx,ou_yyy
FEISHU_HOME_CHANNEL=oc_xxx
FEISHU_DOMAIN 可取:
feishu:中国区 Feishulark:国际版 Lark
第 4 步:启动网关
hermes gateway
然后从 Feishu/Lark 给 bot 发一条消息,确认连接已生效。
Home Chat
你可以在任意 Feishu/Lark 聊天中使用 /set-home 把它标记为 home channel,用于接收 cron 结果和跨平台通知。
你也可以手动配置:
FEISHU_HOME_CHANNEL=oc_xxx
安全
用户 allowlist
生产环境建议设置 Feishu Open ID allowlist:
FEISHU_ALLOWED_USERS=ou_xxx,ou_yyy
如果不设置,任何能触达 bot 的用户都可能使用它。在群聊中,消息处理前会使用发送者的 open_id 进行校验。
Webhook Encryption Key
在 webhook 模式下,建议设置加密 key,以启用入站 webhook 签名验证:
FEISHU_ENCRYPT_KEY=your-encrypt-key
当设置后,适配器会使用以下算法验证每个 webhook 请求:
SHA256(timestamp + nonce + encrypt_key + body)
Verification Token
还可以额外设置 verification token,校验 webhook payload 中的 token 字段:
FEISHU_VERIFICATION_TOKEN=your-verification-token
FEISHU_ENCRYPT_KEY 与 FEISHU_VERIFICATION_TOKEN 可以一起使用,形成双重防护。
Group Message Policy
FEISHU_GROUP_POLICY 环境变量控制 Hermes 在群聊中的行为:
FEISHU_GROUP_POLICY=allowlist # default
| Value | Behavior |
|---|---|
open | 对任意群里的任意用户 @ bot 都会响应 |
allowlist | 只有 FEISHU_ALLOWED_USERS 中的用户 @ bot 时才响应 |
disabled | 完全忽略所有群消息 |
无论哪种模式,群聊中都必须显式 @ bot(或 @all)后才会处理;私聊不受此限制。
Bot Identity for @Mention Gating
为了在群里精确判断是否 @ 到 bot,适配器需要知道 bot 的身份。你可以显式提供:
FEISHU_BOT_OPEN_ID=ou_xxx
FEISHU_BOT_USER_ID=xxx
FEISHU_BOT_NAME=MyBot
如果都没有设置,适配器会在启动时尝试通过 Application Info API 自动发现 bot 名称。为此,你需要授予 admin:app.info:readonly 或 application:application:self_manage scope。
Interactive Card Actions
当用户点击 bot 发出的交互式卡片按钮时,适配器会把这些动作转换为合成的 /card 命令事件:
- 按钮点击会变成:
/card button {"key": "value", ...} - 卡片定义中的
valuepayload 会以 JSON 形式附带进来 - 卡片动作会在 15 分钟窗口内去重,防止重复处理
这也是危险命令审批在 Feishu/Lark 中的实现方式:当 agent 需要执行危险命令时,它会发一张带有 Allow Once / Session / Always / Deny 按钮的交互卡片,用户点击按钮后,审批结果就会通过 card action 回调传回 agent。
Required Feishu App Configuration
交互卡片需要在 Feishu 开发者后台完成三项设置,少任何一项都可能在点击按钮时出现 200340 错误:
- 在 Event Subscriptions 中订阅
card.action.trigger - 在 App Features > Bot 中启用 Interactive Card
- 若使用 webhook 模式,在 Message Card Request URL 中配置与事件 webhook 相同的地址
Document Comment Intelligent Reply
除了聊天外,适配器还支持在 Feishu/Lark 文档评论中对 @mention 作答。当用户在文档评论中 @ bot 时,Hermes 会读取文档内容与评论上下文,并在线程中回复。
它基于 drive.notice.comment_add_v1 事件工作,处理流程包括:
- 并行拉取文档内容和评论时间线
- 在单独的评论会话中运行 agent,并只启用
feishu_doc与feishu_drive工具集 - 把回复按 4000 字符分块,并作为 threaded replies 回发
- 为每个文档缓存 1 小时的会话上下文,便于后续追问延续上下文
3-Tier Access Control
文档评论回复采用显式授权模式,没有默认 allow-all。权限按以下顺序匹配:
- 精确文档规则
- 通配符规则
- 顶层默认规则
每条规则可以使用两种策略:
allowlist:静态用户 / tenant 列表pairing:静态列表 + 运行时批准存储,适合逐步放量
规则文件位于 ~/.hermes/feishu_comment_rules.json,pairing 授权存放于 ~/.hermes/feishu_comment_pairing.json。它们支持基于 mtime 的热加载,无需重启网关。
媒体支持
入站(接收)
适配器会接收并缓存以下媒体:
| Type | Extensions | How it's processed |
|---|---|---|
| Images | .jpg, .jpeg, .png, .gif, .webp, .bmp | 通过 Feishu API 下载并缓存 |
| Audio | .ogg, .mp3, .wav, .m4a, .aac, .flac, .opus, .webm | 下载并缓存;小型文本文件会自动抽取内容 |
| Video | .mp4, .mov, .avi, .mkv, .webm, .m4v, .3gp | 下载并缓存为文档 |
| Files | .pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx 等 | 下载并缓存为文档 |
富文本(post)消息中的内嵌图片和文件附件也会被提取。
出站(发送)
| Method | What it sends |
|---|---|
send | 文本或 rich post 消息 |
send_image / send_image_file | 原生图片消息 |
send_document | 文件附件 |
send_voice | 音频文件附件 |
send_video | 原生视频消息 |
send_animation | GIF 会降级为文件附件 |
Markdown Rendering and Post Fallback
当出站文本包含 Markdown(标题、加粗、列表、代码块、链接等)时,适配器会优先将其作为 Feishu post 消息发送。若 Feishu API 拒绝该 post payload,适配器会自动回退为纯文本发送,以确保消息一定送达。
Processing Status Reactions
在 agent 工作期间,bot 会在你的消息上显示 Typing reaction。回复完成后会清除;如果处理失败,则改为 CrossMark。
可通过 FEISHU_REACTIONS=false 关闭。
Burst Protection and Batching
适配器内置了防抖和合并逻辑,以避免短时间内的消息洪峰压垮 agent:
- 文本消息会按 quiet period 合并成一个批次再送入 agent
- 多个媒体附件也会按 burst 合并成一个事件
- 同一聊天内部仍按顺序串行处理,以保持会话连贯性
Rate Limiting (Webhook Mode)
在 webhook 模式下,适配器会按 IP 做限流:
- Window: 60 秒滑动窗口
- Limit: 每个
(app_id, path, IP)组合 120 次请求 / 窗口 - Tracking cap: 最多跟踪 4096 个 key,避免内存无限增长
超限请求会返回 HTTP 429。
WebSocket Tuning
使用 websocket 模式时,可在 config.yaml 中调整重连和 ping:
platforms:
feishu:
extra:
ws_reconnect_interval: 120
ws_ping_interval: 30
Per-Group Access Control
除了全局 FEISHU_GROUP_POLICY 外,你还可以在 config.yaml 的 group_rules 中按群精细配置:
platforms:
feishu:
extra:
default_group_policy: "open"
admins:
- "ou_admin_open_id"
group_rules:
"oc_group_chat_id_1":
policy: "allowlist"
allowlist:
- "ou_user_open_id_1"
"oc_group_chat_id_2":
policy: "admin_only"
支持的策略包括 open、allowlist、blacklist、admin_only 和 disabled。
Deduplication
入站消息会基于 message ID 做 24 小时 TTL 去重。去重状态会持久化到 ~/.hermes/feishu_seen_message_ids.json。
All Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
FEISHU_APP_ID | ✅ | — | Feishu/Lark App ID |
FEISHU_APP_SECRET | ✅ | — | Feishu/Lark App Secret |
FEISHU_DOMAIN | — | feishu | feishu(中国区)或 lark(国际版) |
FEISHU_CONNECTION_MODE | — | websocket | websocket 或 webhook |
FEISHU_ALLOWED_USERS | — | (empty) | 逗号分隔的 open_id allowlist |
FEISHU_HOME_CHANNEL | — | — | cron / 通知输出 chat ID |
FEISHU_ENCRYPT_KEY | — | (empty) | webhook 签名验证 key |
FEISHU_VERIFICATION_TOKEN | — | (empty) | webhook payload 验证 token |
FEISHU_GROUP_POLICY | — | allowlist | 群消息策略 |
FEISHU_BOT_OPEN_ID | — | (empty) | bot 的 open_id |
FEISHU_BOT_USER_ID | — | (empty) | bot 的 user_id |
FEISHU_BOT_NAME | — | (empty) | bot 显示名称 |
FEISHU_WEBHOOK_HOST | — | 127.0.0.1 | webhook 绑定地址 |
FEISHU_WEBHOOK_PORT | — | 8765 | webhook 端口 |
FEISHU_WEBHOOK_PATH | — | /feishu/webhook | webhook 路径 |
Troubleshooting
| Problem | Fix |
|---|---|
lark-oapi not installed | 安装 SDK:pip install lark-oapi |
websockets not installed; websocket mode unavailable | 安装 websockets |
aiohttp not installed; webhook mode unavailable | 安装 aiohttp |
FEISHU_APP_ID or FEISHU_APP_SECRET not set | 设置环境变量或通过 hermes gateway setup 配置 |
| 另一个本地实例正在使用同一个 app_id | 同一个 app_id 同时只能被一个 Hermes 实例使用 |
| 群里不回复 | 确认已 @ bot,并检查 FEISHU_GROUP_POLICY 与 allowlist |
Webhook rejected: invalid verification token | 检查 FEISHU_VERIFICATION_TOKEN |
Webhook rejected: invalid signature | 检查 FEISHU_ENCRYPT_KEY |
| Post 消息被降级成纯文本 | 这是正常回退行为,可查看日志了解具体原因 |
| bot 收不到图片 / 文件 | 给 Feishu app 授予 im:message 和 im:resource scope |
| bot 身份自动发现失败 | 授予 admin:app.info:readonly scope,或手动设置 FEISHU_BOT_OPEN_ID / FEISHU_BOT_NAME |
| 点击审批按钮时报 200340 | 在开发者后台启用 Interactive Card 并配置 Card Request URL |
Webhook rate limit exceeded | 同一 IP 在 1 分钟内超过 120 个请求,通常意味着配置错误或发生循环 |
Toolset
Feishu / Lark 使用 hermes-feishu 平台预设,包含与 Telegram 等消息平台相同的核心工具。