飞书/Lark 集成
AgentHub 把飞书/Lark 作为协作入口:机器人消息、事件订阅、交互卡片,以及 H5/工作台入口。产品登录和账号绑定仍归 TokenDance ID。
身份边界
不要把飞书 OAuth 描述成 AgentHub 产品登录。飞书用户标识只代表协作上下文。TokenDance ID 仍是身份权威,并负责账号绑定。
集成边界
flowchart LR
Client["飞书/Lark 客户端"] --> App["AgentHub 机器人、卡片、H5"]
App --> Gateway["Feishu Integration Gateway"]
Gateway --> Hub["AgentHub Hub Server"]
Hub --> ID["TokenDance ID"]
ID --> Binding["飞书账号绑定"]
飞书应用应聚焦协作入口:
- 接收单聊消息和群聊 @;
- 发送机器人回复和任务卡片;
- 处理卡片按钮回调;
- 在 H5/工作台中打开 AgentHub;
- 把身份和绑定交给 TokenDance ID。
生产入口
生产环境应保留 HTTPS Webhook Gateway 作为稳定事件入口。建议把消息事件和卡片动作分成独立路由:
POST /integrations/feishu/events
POST /integrations/feishu/card-actions
Webhook 入口负责 URL challenge、签名/加密校验、事件去重、token 缓存、消息解析和快速确认。耗时的 AgentHub 工作应异步入队。
SDK 长连接适合企业自建应用开发和内部测试,但不应成为唯一的生产入口,也不适合作为未来跨租户事件路径的唯一方案。
应用设置清单
声明飞书/Lark 集成可供用户测试前,先按这张清单检查。真实 app id、secret、tenant id、callback token 和审批截图不要进入公开仓库。
| 步骤 | 公开安全要求 | 需要留存的证据 |
|---|---|---|
| 应用模型 | 选择企业自建应用或明确获批的部署形态 | 私有实现说明,包含 owner 和租户范围 |
| 机器人入口 | 开启单聊和群聊 @ 的机器人消息能力 | 私有运维文档中的截图或租户配置证据 |
| 事件订阅 | MVP 只订阅 im.message.receive_v1 和 card.action.trigger | 事件订阅清单和审批 owner |
| URL challenge | Webhook 在业务逻辑前返回平台 challenge body | 脱敏 request id 和成功时间 |
| 签名与加密 | 解析事件前完成 token/signature 校验和 payload 解密 | 单元/集成测试结果;公开文档不贴原始 payload |
| Scope | 只申请 MVP 必需的 bot/message/card/H5 scope | Scope review 记录,并明确拒绝宽泛读取权限 |
| 幂等 | 从 event_id、message_id 或 action id 派生幂等键 | 重试测试不会创建重复 Hub task |
| 队列交接 | 快速确认,然后异步入队 AgentHub 工作 | callback ack 和 queue enqueue 的耗时证据 |
| 账号绑定 | 未绑定用户收到 TokenDance ID 绑定卡片 | 脱敏卡片截图和 binding-state audit 记录 |
| 失败 UX | unknown command、unauthorized action、queue failure、binding failure 都有卡片 | 使用合成 id 的失败态截图 |
必要事件
MVP 事件集合应保持克制:
| 事件 | 用途 | 处理方式 |
|---|---|---|
im.message.receive_v1 | 单聊消息和群聊 @ 机器人消息 | 用 message_id 做消息事件去重;只解析命令和必要上下文。 |
card.action.trigger | 交互卡片动作 | 3 秒内响应;耗时工作入队;不要依赖 HTTP 重定向。 |
群聊默认只响应 @ 机器人。除非产品需求和安全审查明确通过,否则不要申请读取全群消息的敏感权限。
公开安全 Payload 示例
URL challenge 应在业务逻辑前完成,并返回平台要求的 challenge body。示例只展示形状:
{
"type": "url_verification",
"challenge": "challenge_string"
}
{
"challenge": "challenge_string"
}
消息事件示例:
{
"schema": "2.0",
"header": {
"event_id": "evt_123",
"event_type": "im.message.receive_v1",
"tenant_key": "tenant_123"
},
"event": {
"message": {
"message_id": "msg_123",
"chat_id": "chat_123",
"message_type": "text",
"content": "{\"text\":\"@AgentHub review docs\"}"
},
"sender": {
"sender_id": {
"open_id": "ou_xxx",
"union_id": "on_xxx"
}
}
}
}
卡片动作示例:
{
"schema": "2.0",
"header": {
"event_id": "evt_card_123",
"event_type": "card.action.trigger"
},
"event": {
"operator": {
"open_id": "ou_xxx"
},
"action": {
"value": {
"action": "approve_run",
"taskId": "task_123",
"approvalId": "approval_123"
}
}
}
}
快速确认响应应轻量,耗时任务入队:
{
"ok": true,
"queued": true,
"requestId": "req_123"
}
如果用户未绑定 TokenDance ID,返回绑定卡片,而不是创建 Hub task:
{
"card": {
"title": "绑定 TokenDance ID",
"actions": [
{
"type": "button",
"label": "继续绑定",
"url": "https://id.example.invalid/bind/feishu?state=opaque_state"
}
]
}
}
这些示例不得替代真实平台签名、加密、challenge 和卡片 schema 校验。实现时以飞书/Lark 官方文档和 AgentHub 所属仓库的 schema 为准。
MVP 验收标准
飞书/Lark MVP 不是"机器人能收到消息"就算完成。至少要满足以下条件:
| 区域 | 验收标准 |
|---|---|
| App 类型 | 企业自建应用或获批部署形态已写入私有实现计划 |
| 权限范围 | 只申请必要的 bot/message/card/H5 scope;宽泛读取权限有明确安全审查 |
| 事件订阅 | im.message.receive_v1 和 card.action.trigger 已开启并验证 |
| Challenge response | URL verification 在业务逻辑前返回预期 challenge body |
| 签名/加密 | token、signature 和 encrypted payload 校验在事件解析前执行 |
| 去重 | message event 用 message_id 去重;card action 用 event 或 action id 去重 |
| Queue handoff | 耗时 AgentHub 工作在快速确认后异步入队 |
| Retry policy | 重试具备幂等性,不创建重复 Hub task |
| 绑定失败 UX | 未绑定用户收到 TokenDance ID 绑定卡片,而不是泛化失败 |
| Audit | Hub 记录 actor、binding state、task id、action、result、request id 和脱敏失败原因 |
卡片和动作
卡片是 AgentHub 在飞书内的主要交互形态:
- 任务状态卡片;
- 确认、重试、取消、查看详情动作;
- 未绑定用户的 TokenDance ID 绑定卡片;
- 运行中、已完成、失败、需要输入等运行状态卡片。
卡片动作只应携带短 action id 和业务对象 id。不要在卡片 payload 中放 secret、bearer token、完整 prompt 或敏感工作区上下文。
H5 和工作台
飞书 H5/工作台入口可以在飞书客户端内打开 AgentHub,但它不是第二套登录系统。
如果用户尚未绑定,应展示 TokenDance ID 绑定路径。飞书 JSAPI 可以增强客户端内体验,但最终的产品身份和授权必须回到 TokenDance ID 与 AgentHub Hub Server 权限。
绑定闭环
推荐的用户映射流程:
- 飞书事件带着租户和用户上下文进入 Gateway。
- Integration Gateway 查找该飞书用户对应的 TokenDance ID 绑定。
- 如果没有绑定,机器人返回绑定卡片。
- 用户完成 TokenDance ID 登录和飞书账号绑定。
- AgentHub 拿到 TokenDance ID
sub,再按 Hub Server 权限执行。
AgentHub Desktop 和 Web 客户端不应保存飞书 access token;飞书 open_id、user_id 或 union_id 也不能成为产品用户主键。
安全清单
- Verification Token、Encrypt Key、App Secret 和 tenant token 只放在服务端 secret storage。
- 进入业务处理前完成签名校验,并对加密事件做解密。
- 事件和卡片回调都必须在 3 秒内确认。
im.message.receive_v1用message_id去重;其他事件在可用时用 event id 去重。- 日志记录事件类型、message id、event id、tenant、chat id 哈希、action id、耗时、结果和飞书错误码;默认不记录消息全文。
- 飞书 OAuth、refresh token 和账号绑定归 TokenDance ID。
下一步
- 使用系统架构文档确认 Integration Gateway 与 AgentHub Hub Server 的边界。
- 在 AgentHub runtime endpoints、卡片 schema 和绑定 callback 证据发布前,把飞书机器人配置视为开发中能力。
- 在 AgentHub 实现 backlog 中跟踪生产权限范围和审核材料。