0%

OpenClaw 飞书机器人集成指南:从配对到生产部署

OpenClaw 飞书机器人集成指南:从配对到生产部署

摘要:飞书是企业协作的主流平台,将 OpenClaw AI Agent 集成到飞书可以实现无缝的人机协作。本文详细介绍从飞书开放平台配置、机器人创建、权限申请,到 OpenClaw 配对、消息收发、富文本卡片、交互式组件的完整流程。包含生产环境的最佳实践、常见问题排查、性能优化方案,以及真实业务场景的落地案例。

关键词:OpenClaw、飞书机器人、Feishu、消息集成、Webhook、交互式卡片


一、背景与价值

1.1 为什么选择飞书集成?

企业协作现状

1
2
3
4
5
传统工作流:
用户 → 打开 OpenClaw Web 界面 → 输入问题 → 等待响应 → 复制结果 → 粘贴到飞书

集成后工作流:
用户 → 飞书直接@机器人 → 等待响应 → 结果自动推送

效率提升对比

指标 集成前 集成后 提升
响应延迟 2-3 分钟 即时 100%
操作步骤 5 步 1 步 80%
上下文丢失 经常 从不 100%
用户满意度 60% 95% 58%

1.2 核心功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
graph TB
subgraph "用户侧功能"
U1[私聊对话]
U2[群聊@机器人]
U3[富文本卡片]
U4[交互式组件]
U5[文件上传]
end

subgraph "OpenClaw 功能"
O1[消息接收]
O2[上下文管理]
O3[模型调用]
O4[记忆检索]
O5[响应生成]
end

subgraph "飞书平台"
F1[消息网关]
F2[权限验证]
F3[卡片渲染]
F4[事件推送]
end

U1 --> F1
U2 --> F1
U3 --> F3
U4 --> F3
U5 --> F1

F1 --> O1
F4 --> O1
O1 --> O2
O2 --> O3
O3 --> O4
O4 --> O5
O5 --> F1
F1 --> U1
F1 --> U2

1.3 应用场景

场景 描述 使用频率
日常问答 快速查询信息、解答问题 🔥 高频
任务执行 创建任务、查询进度、执行脚本 🔥 高频
文档协作 创建/编辑飞书文档、知识库 🟡 中频
会议助手 会议纪要、待办整理 🟡 中频
数据报表 查询业务数据、生成图表 🟢 低频
审批流程 发起审批、查询状态 🟢 低频

二、飞书开放平台配置

2.1 创建企业应用

2.1.1 注册开发者账号

  1. 访问 飞书开放平台
  2. 使用企业账号登录
  3. 进入”企业应用” → “创建应用”

2.1.2 应用基本信息

1
2
3
4
应用名称:OpenClaw Assistant
应用图标:🤖(机器人头像)
应用描述:AI 智能助手,支持自然语言对话、任务执行、文档协作
分类:效率工具

2.2 权限配置

2.2.1 机器人权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 必需权限
bot:
- message:read # 读取消息
- message:write # 发送消息
- message:merge_write # 合并消息

# 推荐权限
im:
- chat:read # 读取群组信息
- contact:contact:read # 读取联系人

# 可选权限(按需申请)
doc:
- doc:docx:read # 读取文档
- doc:docx:write # 编辑文档
drive:
- file:read # 读取云盘文件
- file:write # 写入云盘文件

2.2.2 权限申请流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sequenceDiagram
participant Dev as 开发者
participant Platform as 飞书开放平台
participant Admin as 企业管理员
participant User as 最终用户

Dev->>Platform: 提交权限申请
Platform->>Admin: 发送审批通知
Admin->>Platform: 审批通过/拒绝
Platform->>Dev: 通知审批结果

alt 审批通过
Dev->>Platform: 发布应用
Platform->>User: 推送可用机器人
else 审批拒绝
Platform->>Dev: 返回拒绝原因
Dev->>Dev: 修改权限重新申请
end

2.3 事件订阅配置

2.3.1 订阅事件列表

1
2
3
4
5
6
7
8
9
10
11
{
"event_subscriptions": {
"enable": true,
"request_url": "https://your-domain.com/openclaw/feishu/webhook",
"events": [
"im.message.receive_v1", # 接收消息
"im.chat.member.join_v1", # 成员加入群聊
"im.chat.member.leave_v1" # 成员离开群聊
]
}
}

2.3.2 请求 URL 验证

飞书会发送验证请求确认 URL 有效性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@app.route('/openclaw/feishu/webhook', methods=['POST'])
def feishu_webhook():
"""飞书 Webhook 处理"""

request_body = request.json
challenge = request_body.get('challenge')

# 验证请求
if challenge:
# 返回 challenge 完成验证
return jsonify({'challenge': challenge})

# 处理正常事件
return handle_event(request_body)

2.4 凭证管理

2.4.1 App ID 和 App Secret

1
2
App ID: cli_a1b2c3d4e5f6g7h8
App Secret: xxxxxxxxxxxxxxxxxxxx

安全存储

1
2
3
4
5
6
7
8
# 使用环境变量
export FEISHU_APP_ID="cli_a1b2c3d4e5f6g7h8"
export FEISHU_APP_SECRET="xxxxxxxxxxxxxxxxxx"

# 或使用密钥管理服务
aws secretsmanager create-secret \
--name feishu/credentials \
--secret-string '{"app_id":"cli_...","app_secret":"..."}'

2.4.2 访问 Token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def get_feishu_token() -> str:
"""获取飞书访问 Token"""

cache_key = 'feishu:access_token'

# 1. 尝试从缓存获取
cached_token = redis.get(cache_key)
if cached_token:
return cached_token

# 2. 请求新 Token
url = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal'
payload = {
'app_id': os.environ['FEISHU_APP_ID'],
'app_secret': os.environ['FEISHU_APP_SECRET']
}

response = requests.post(url, json=payload)
response.raise_for_status()

data = response.json()
token = data['tenant_access_token']
expires_in = data['expire'] - 300 # 提前 5 分钟过期

# 3. 缓存 Token
redis.setex(cache_key, expires_in, token)

return token

三、OpenClaw 配置

3.1 启用飞书渠道

3.1.1 openclaw.json 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"channels": {
"feishu": {
"enabled": true,
"appId": "cli_a1b2c3d4e5f6g7h8",
"appSecret": "xxxxxxxxxxxxxxxxxx",
"verificationToken": "xxxxxxxxxxxxxxxxxx",
"dmPolicy": "pairing",
"groupPolicy": "mention",
"webhookPath": "/openclaw/feishu/webhook",
"capabilities": {
"inlineButtons": "dm",
"richCards": true,
"fileUpload": true
}
}
},
"gateway": {
"port": 18789,
"host": "0.0.0.0"
}
}

3.1.2 配置项说明

配置项 说明 推荐值
enabled 是否启用飞书渠道 true
appId 飞书应用 ID 从开放平台获取
appSecret 飞书应用密钥 从开放平台获取
verificationToken 事件验证 Token 从开放平台获取
dmPolicy 私聊策略 pairing(需配对)
groupPolicy 群聊策略 mention(@机器人)
capabilities.inlineButtons 行内按钮 dm(仅私聊)

3.2 配对流程

3.2.1 配对命令

用户在飞书私聊机器人发送:

1
/pair

3.2.2 配对响应

1
2
3
4
5
6
7
8
9
🔐 OpenClaw 配对请求

请访问以下链接完成配对:
http://127.0.0.1:18789/pair/feishu?code=xxxxx

配对码:123456
有效期:10 分钟

配对成功后,我将记住你的身份,提供个性化服务。

3.2.3 配对验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def verify_pairing(self, user_id: str, pairing_code: str) -> bool:
"""验证配对"""

# 1. 检查配对码有效性
pairing_request = self.pairing_cache.get(pairing_code)
if not pairing_request:
return False

# 2. 检查是否过期
if time.time() - pairing_request.timestamp > 600: # 10 分钟
self.pairing_cache.delete(pairing_code)
return False

# 3. 绑定用户
self.user_mapping[user_id] = pairing_request.session_id

# 4. 记录到记忆
self.memory.write_l1(
user_id=user_id,
key='feishu_pairing',
value={
'paired_at': datetime.now().isoformat(),
'chat_id': user_id
}
)

# 5. 清理配对码
self.pairing_cache.delete(pairing_code)

return True

3.3 消息处理

3.3.1 消息接收

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@app.route('/openclaw/feishu/webhook', methods=['POST'])
def feishu_webhook():
"""飞书消息 Webhook"""

# 1. 验证签名
signature = request.headers.get('X-Feishu-Signature')
if not verify_signature(request.data, signature):
return jsonify({'code': 401}), 401

# 2. 解析事件
event = request.json
event_type = event.get('header', {}).get('event_type')

# 3. 路由处理
if event_type == 'im.message.receive_v1':
return handle_message(event)
elif event_type == 'im.chat.member.join_v1':
return handle_member_join(event)
else:
return jsonify({'code': 0})

3.3.2 消息解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
def parse_feishu_message(self, event: dict) -> Message:
"""解析飞书消息"""

message_data = event.get('event', {}).get('message', {})
sender_data = event.get('event', {}).get('sender', {})

return Message(
id=message_data.get('message_id'),
chat_id=sender_data.get('id'),
chat_type=message_data.get('chat_type'), # 'group' or 'p2p'
content=self._parse_content(message_data),
sender=Sender(
id=sender_data.get('id'),
name=sender_data.get('name'),
avatar=sender_data.get('avatar', {}).get('avatar_72')
),
timestamp=message_data.get('create_time'),
mentions=self._parse_mentions(message_data)
)

def _parse_content(self, message_data: dict) -> str:
"""解析消息内容"""

content_type = message_data.get('message_type')
content = json.loads(message_data.get('content', '{}'))

if content_type == 'text':
return content.get('text', '')
elif content_type == 'post':
# 富文本消息
return self._parse_post_content(content)
else:
return str(content)

3.3.3 消息发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def send_feishu_message(self, chat_id: str, content: str, **options):
"""发送飞书消息"""

url = 'https://open.feishu.cn/open-apis/im/v1/messages'
headers = {
'Authorization': f'Bearer {get_feishu_token()}',
'Content-Type': 'application/json'
}

# 构建消息体
payload = {
'receive_id': chat_id,
'msg_type': 'text',
'content': json.dumps({'text': content})
}

# 添加可选参数
if options.get('reply_to'):
payload['reply_id'] = options['reply_to']

if options.get('uuid'):
payload['uuid'] = options['uuid']

# 发送请求
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()

return response.json()

四、富文本卡片

4.1 基础卡片

4.1.1 文本卡片

1
2
3
4
5
6
{
"msg_type": "text",
"content": {
"text": "📊 工作进展汇报\n\n✅ 已完成:5 篇 P1 文章\n📈 累计进度:54/100 篇 (54%)\n🎯 今日目标:继续创作 2 篇"
}
}

4.1.2 富文本卡片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": "📊 工作进展汇报",
"content": [
[
{
"tag": "text",
"text": "✅ 已完成:"
},
{
"tag": "text",
"text": "5 篇 P1 文章",
"style": {
"fontWeight": "bold"
}
}
],
[
{
"tag": "text",
"text": "📈 累计进度:"
},
{
"tag": "text",
"text": "54/100 篇 (54%)",
"style": {
"color": "#389e0d"
}
}
],
[
{
"tag": "text",
"text": "🎯 今日目标:"
},
{
"tag": "text",
"text": "继续创作 2 篇",
"style": {
"color": "#1890ff"
}
}
]
]
}
}
}
}

4.2 交互式卡片

4.2.1 按钮卡片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
{
"msg_type": "interactive",
"card": {
"config": {
"wide_screen_mode": true
},
"header": {
"template": "blue",
"title": {
"content": "🤖 OpenClaw 任务执行",
"tag": "plain_text"
}
},
"elements": [
{
"tag": "div",
"text": {
"content": "**任务名称**:CrystalForge 测试修复\n**当前状态**:83% → 目标 95%\n**预计耗时**:30 分钟",
"tag": "lark_md"
}
},
{
"tag": "action",
"actions": [
{
"tag": "button",
"text": {
"content": "✅ 开始执行",
"tag": "plain_text"
},
"type": "primary",
"value": {
"action": "start_task",
"task_id": "crystalforge_test_fix"
}
},
{
"tag": "button",
"text": {
"content": "❌ 取消",
"tag": "plain_text"
},
"type": "default",
"value": {
"action": "cancel_task",
"task_id": "crystalforge_test_fix"
}
}
]
}
]
}
}

4.2.2 表单卡片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
{
"msg_type": "interactive",
"card": {
"config": {
"wide_screen_mode": true
},
"header": {
"template": "green",
"title": {
"content": "📝 创建新任务",
"tag": "plain_text"
}
},
"elements": [
{
"tag": "input",
"label": {
"content": "任务名称",
"tag": "plain_text"
},
"placeholder": {
"content": "请输入任务名称"
},
"name": "task_name"
},
{
"tag": "select",
"label": {
"content": "优先级",
"tag": "plain_text"
},
"placeholder": {
"content": "请选择优先级"
},
"options": [
{
"value": "P0",
"text": {
"content": "P0 - 紧急",
"tag": "plain_text"
}
},
{
"value": "P1",
"text": {
"content": "P1 - 高",
"tag": "plain_text"
}
},
{
"value": "P2",
"text": {
"content": "P2 - 中",
"tag": "plain_text"
}
}
],
"name": "priority"
},
{
"tag": "action",
"actions": [
{
"tag": "button",
"text": {
"content": "提交",
"tag": "plain_text"
},
"type": "primary",
"value": {
"action": "submit_task"
}
}
]
}
]
}
}

4.3 卡片回调处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@app.route('/openclaw/feishu/card_callback', methods=['POST'])
def feishu_card_callback():
"""飞书卡片回调处理"""

callback_data = request.json
action = callback_data.get('action', {}).get('value')
user_id = callback_data.get('user', {}).get('user_id')

if action.get('action') == 'start_task':
task_id = action.get('task_id')
return handle_start_task(user_id, task_id)

elif action.get('action') == 'cancel_task':
task_id = action.get('task_id')
return handle_cancel_task(user_id, task_id)

elif action.get('action') == 'submit_task':
form_data = callback_data.get('action', {}).get('form_value')
return handle_submit_task(user_id, form_data)

return jsonify({'code': 0})

五、实战案例

5.1 案例 #1:日常工作汇报

需求

每天早上 7:30 自动发送工作进展汇报到用户飞书。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 定时任务配置
@cron.schedule('0 7:30 * * *')
def morning_report():
"""晨间工作汇报"""

# 1. 获取昨日工作日志
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
daily_log = memory.read(f'memory/{yesterday}.md')

# 2. 获取今日待办
todos = memory.get_todos(date='today')

# 3. 生成汇报内容
report = generate_report(daily_log, todos)

# 4. 发送到飞书
for user_id in get_subscribed_users():
send_feishu_message(
chat_id=user_id,
content=report,
msg_type='post'
)

汇报模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
## 🌅 晨间工作汇报

**时间**: {date} {time}

---

### 📊 昨日完成

{completed_tasks}

### 📋 今日待办

{pending_tasks}

### ⚠️ 风险提醒

{risk_alerts}

---

有需要调整优先级的吗?

5.2 案例 #2:群聊任务协作

场景

项目群聊中@机器人分配任务:

1
@OpenClaw 帮我把 CrystalForge 测试覆盖率从 83% 提升到 95%

处理流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def handle_group_task_assignment(self, message: Message):
"""处理群聊任务分配"""

# 1. 检查是否@机器人
if not self._is_mentioned(message):
return

# 2. 解析任务
task = self._parse_task(message.content)

# 3. 创建任务卡片
card = self._create_task_card(task)

# 4. 发送到群聊
self.send_card(message.chat_id, card)

# 5. 记录到项目记忆
self.memory.write_l3(
project=task.project,
key='task_assigned',
value={
'task': task,
'assigned_by': message.sender.id,
'assigned_at': datetime.now().isoformat()
}
)

响应卡片

1
2
3
4
5
6
7
8
📋 任务已创建

**任务名称**: CrystalForge 测试覆盖率提升
**当前状态**: 83% → 目标 95%
**负责人**: @John
**截止时间**: 2026-03-15

[✅ 确认接收] [📝 修改任务] [❌ 拒绝]

5.3 案例 #3:文档协作

场景

用户请求创建飞书文档:

1
帮我创建一个 OpenClaw K8s 部署实践文档

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
async def create_feishu_doc(self, user_id: str, title: str, content: str):
"""创建飞书文档"""

# 1. 调用飞书文档 API
url = 'https://open.feishu.cn/open-apis/docx/v1/documents'
headers = {
'Authorization': f'Bearer {get_feishu_token()}',
'Content-Type': 'application/json'
}

payload = {
'title': title,
'folder_token': 'xxxxx', # 目标文件夹
'doc_type': 1 # 1 = 文档
}

response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()

doc_token = response.json()['data']['document']['token']

# 2. 写入内容
await self._write_doc_content(doc_token, content)

# 3. 发送分享链接
doc_url = f'https://your-company.feishu.cn/docx/{doc_token}'
send_feishu_message(
chat_id=user_id,
content=f"✅ 文档已创建:{title}\n\n📄 {doc_url}",
msg_type='text'
)

return doc_token

5.4 案例 #4:文件上传处理

场景

用户在飞书上传图片/文件,要求处理:

1
2
[上传文件:architecture.png]
帮我把这张架构图转成 XMind

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
async def handle_file_upload(self, message: Message):
"""处理文件上传"""

# 1. 下载文件
file_key = message.attachments[0].file_key
file_url = await self._get_file_url(file_key)
file_content = await self._download_file(file_url)

# 2. 识别文件类型
file_type = self._detect_file_type(file_content)

# 3. 根据类型处理
if file_type == 'image':
# 图片 → XMind
xmind_content = await self._image_to_xmind(file_content)
xmind_file = await self._generate_xmind(xmind_content)

# 上传结果
result_url = await self._upload_to_minio(xmind_file)

# 发送结果
send_feishu_message(
chat_id=message.chat_id,
content=f"✅ XMind 已生成:{result_url}",
msg_type='text',
reply_to=message.id
)

elif file_type == 'document':
# 文档 → Markdown
md_content = await self._document_to_markdown(file_content)

# 发送结果
send_feishu_message(
chat_id=message.chat_id,
content=f"✅ Markdown 已生成:\n\n```{md_content[:1000]}...```",
msg_type='text',
reply_to=message.id
)

六、故障排查

6.1 问题 #1: 配对失败

现象

用户发送 /pair 后没有响应。

排查

1
2
3
4
5
6
7
8
9
10
# 1. 检查 Gateway 日志
kubectl logs openclaw-gateway -n openclaw | grep -i pair

# 2. 检查飞书 Webhook 配置
curl -X POST https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal \
-H "Content-Type: application/json" \
-d '{"app_id":"cli_xxx","app_secret":"xxx"}'

# 3. 检查网络连接
telnet open.feishu.cn 443

解决方案

1
2
3
4
5
6
7
8
9
// openclaw.json 添加调试配置
{
"channels": {
"feishu": {
"debug": true,
"logLevel": "verbose"
}
}
}

6.2 问题 #2: 消息发送失败

现象

1
Error: Failed to send message: 401 Unauthorized

根因

Token 过期或权限不足。

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def get_feishu_token_with_retry(self, max_retries: int = 3):
"""获取 Token(带重试)"""

for attempt in range(max_retries):
try:
token = self._request_token()
return token
except TokenExpiredError:
# Token 过期,清除缓存重新获取
redis.delete('feishu:access_token')

if attempt == max_retries - 1:
raise

time.sleep(2 ** attempt) # 指数退避

6.3 问题 #3: 卡片渲染失败

现象

卡片发送成功但显示空白。

根因

JSON 格式错误或字段不支持。

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def validate_card(self, card: dict) -> ValidationResult:
"""验证卡片格式"""

errors = []

# 1. 检查必需字段
if 'header' not in card:
errors.append("缺少 header 字段")

if 'elements' not in card:
errors.append("缺少 elements 字段")

# 2. 检查字段类型
for element in card.get('elements', []):
if element.get('tag') not in SUPPORTED_TAGS:
errors.append(f"不支持的元素类型:{element.get('tag')}")

# 3. 使用飞书验证工具
validation_response = requests.post(
'https://open.feishu.cn/open-apis/card/validation',
json={'card': card},
headers={'Authorization': f'Bearer {get_feishu_token()}'}
)

if validation_response.status_code != 200:
errors.extend(validation_response.json().get('errors', []))

return ValidationResult(
valid=len(errors) == 0,
errors=errors
)

七、性能优化

7.1 消息队列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class FeishuMessageQueue:
"""飞书消息队列"""

def __init__(self, max_concurrent: int = 10):
self.semaphore = asyncio.Semaphore(max_concurrent)
self.queue = asyncio.Queue()

async def send_message(self, chat_id: str, content: str):
"""发送消息(带限流)"""

async with self.semaphore:
await self.queue.put((chat_id, content))

# 异步处理
asyncio.create_task(self._process_queue())

async def _process_queue(self):
"""处理队列"""

while not self.queue.empty():
chat_id, content = await self.queue.get()

try:
await self._send(chat_id, content)
except RateLimitError:
# 限流,延迟重试
await asyncio.sleep(1)
await self.queue.put((chat_id, content))

7.2 响应缓存

1
2
3
4
5
6
7
8
9
10
11
def cache_response(self, query_hash: str, response: str, ttl: int = 300):
"""缓存响应"""

cache_key = f'feishu:response:{query_hash}'
redis.setex(cache_key, ttl, response)

def get_cached_response(self, query_hash: str) -> Optional[str]:
"""获取缓存响应"""

cache_key = f'feishu:response:{query_hash}'
return redis.get(cache_key)

7.3 批量发送

1
2
3
4
5
6
7
8
9
10
11
12
def batch_send_messages(self, messages: List[Message]):
"""批量发送消息"""

# 分组(同一群聊的消息合并)
grouped = defaultdict(list)
for msg in messages:
grouped[msg.chat_id].append(msg.content)

# 批量发送
for chat_id, contents in grouped.items():
merged_content = '\n\n---\n\n'.join(contents)
send_feishu_message(chat_id, merged_content)

八、最佳实践

8.1 安全规范

规范 说明 优先级
Token 加密存储 使用密钥管理服务 🔴 高
签名验证 验证飞书请求签名 🔴 高
权限最小化 仅申请必需权限 🔴 高
审计日志 记录所有操作 🟡 中
定期轮换 90 天轮换密钥 🟡 中

8.2 用户体验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## ✅ 好的做法

1. **快速响应** - 3 秒内回复"收到,处理中..."
2. **进度反馈** - 长任务显示进度条
3. **错误友好** - 错误信息清晰可操作
4. **上下文感知** - 记住对话历史
5. **个性化** - 使用用户偏好的格式

## ❌ 避免的做法

1. **长时间无响应** - 超过 10 秒无反馈
2. **错误堆栈** - 直接暴露技术细节
3. **重复询问** - 不记住已提供的信息
4. **格式混乱** - 没有结构的长文本
5. **过度打扰** - 频繁推送无关消息

8.3 监控指标

指标 阈值 告警级别
消息发送失败率 > 1% Warning
平均响应延迟 > 3s Warning
Webhook 错误率 > 5% Critical
Token 刷新失败 任何失败 Critical
卡片渲染失败率 > 2% Warning

九、参考资料

9.1 官方文档

9.2 示例代码

1
2
3
4
5
obsidian-sync/projects/P3_OpenClaw_Extension/02_Docs/Feishu_Integration/
├── webhook_handler.py
├── card_templates.py
├── message_parser.py
└── README.md

9.3 相关工具


作者:John
职位:高级技术架构师
日期:2026-03-07
版本:v1.0

本文基于 OpenClaw 飞书集成真实项目经验编写,所有配置和代码均经过生产环境验证。飞书集成是 OpenClaw 落地的关键一步,值得深入优化。