AI AGENT SKILLS

Feishu Wiki Query

一个面向 Other 场景的 Agent 技能。原始说明:飞书知识库文档查询技能。当用户询问需要查询飞书知识库中的文档时使用此技能,包括:查询动物信息、查看排期、读取文档内容、处理文档中的图片、画板和电子表格等。触发场景包括:用户说"查一下xx动物"、"看看排期"、"查询知识库"、"食堂菜谱"等。

SKILL.md

SKILL.md


name: feishu-wiki-query
description: 飞书知识库文档查询技能。当用户询问需要查询飞书知识库中的文档时使用此技能,包括:查询动物信息、查看排期、读取文档内容、处理文档中的图片、画板和电子表格等。触发场景包括:用户说"查一下xx动物"、"看看排期"、"查询知识库"、"食堂菜谱"等。


飞书知识库查询

概述

本技能用于查询飞书知识库中的文档内容,支持读取文本、图片、画板、电子表格等多种类型的文档内容。

本技能支持用户自定义知识库配置,安装后可随时添加/移除知识库。

配置文件

配置存储在:~/.openclaw/workspace/skills/feishu-wiki-query/config.json

首次使用前需要先进行配置。

首次配置

用户首次使用时,提示:

🎀 欢迎使用飞书知识库查询技能!

请先配置你的知识库地址~

方式:发送 添加知识库 [知识库名称] [知识库URL]

例如:添加知识库 我的知识库 https://my.feishu.cn/wiki/XEMRwElx2iMzHhkkVdCcpj0tnDg

知识库 URL 就是你在浏览器打开知识库时地址栏的地址~

配置管理命令

添加知识库

添加知识库 [名称] [知识库URL]

示例:

添加知识库 海洋动物专区 https://my.feishu.cn/wiki/XEMRwElx2iMzHhkkVdCcpj0tnDg
添加知识库 技术文档 https://my.feishu.cn/wiki/abcdefg1234567

自动解析: 从 URL 中提取 nodetoken,并通过 API 获取 spaceid,全程无需用户手动提供。

移除知识库

移除知识库 [名称]

查看已配置的知识库

查看知识库

重置配置

重置知识库配置

⚠️ 此操作会清空所有已配置的知识库,请谨慎使用!

添加知识库时的自动解析流程

当用户输入 添加知识库 [名称] [URL] 时:

  1. 解析 URL 获取 node_token
  • URL 格式:https://my.feishu.cn/wiki/{node_token}
  • 提取 node_token = URL 路径最后一段
  1. 获取 space_id
   feishu_wiki {
     action: "get",
     token: "解析出的node_token"
   }

从返回中获取 space_id

  1. 保存配置

将以下内容写入 config.json

   {
     "version": 1,
     "updated_at": "当前时间",
     "knowledge_bases": [
       {
         "name": "用户提供的名称",
         "space_id": "获取到的space_id",
         "root_node_token": "解析出的node_token"
       }
     ]
   }

查询流程

步骤1:浏览知识库目录

首先获取首页目录(使用配置中的 spaceid 和首页 nodetoken):

如果只有一个知识库,直接使用:

feishu_wiki {
  action: "nodes",
  space_id: "配置中的space_id",
  parent_node_token: "配置中的首页node_token"
}

如果有多个知识库,先询问用户要查询哪个:

你想查询哪个知识库?

1. 海洋动物专区

2. 技术文档

...

用户选择后,使用对应的 spaceid 和 nodetoken。

步骤2:进入子目录

必须加 parent_node_token 参数才能读到子目录!

feishu_wiki {
  action: "nodes",
  space_id: "space_id",
  parent_node_token: "当前目录的node_token"
}

步骤3:递归深入找到目标文档

重复步骤2,直到找到目标文档。

步骤4:读取文档内容

feishu_doc {
  action: "read",
  doc_token: "obj_token"
}

通过 URL 解析获取 space_id

如果用户提供了知识库的 wiki URL(如 https://my.feishu.cn/wiki/XEMRwElx2iMzHhkkVdCcpj0tnDg),可以尝试自动获取 space_id:

# URL 中的 node_token
node_token = "XEMRwElx2iMzHhkkVdCcpj0tnDg"

# 尝试获取节点信息(可能包含 space_id)
feishu_wiki {
  action: "get",
  token: node_token
}

注意:部分节点可能无法直接获取 spaceid,此时请让用户提供正确的 spaceid。

文档Blocks类型

常用 block_type 对照表:

| block_type | 含义 |
|------------|------|
| 1 | Page(页面) |
| 2 | Text(文本段落) |
| 4 | Heading2(二级标题) |
| 27 | Image(图片) |
| 43 | Whiteboard(画板) |

处理图片内容

当文档包含图片时,feishu_doc { action: "read" } 会返回提示:

"This document contains Image which are NOT included in the plain text above."

处理步骤:

  1. 列出所有 Blocks
   feishu_doc {
     action: "list_blocks",
     doc_token: "文档token"
   }
  1. 找到图片 Block
  • 图片的 block_type27
  • 图片 token 在 block.image.token 字段
  1. 下载图片
   curl "https://open.feishu.cn/open-apis/drive/v1/medias/{image_token}/download" \
     -H "Authorization: Bearer {token}"

处理画板(Whiteboard)内容

当文档包含画板时(block_type=43):

  1. 获取画板的 whiteboard_id
  • list_blocks 列出所有 blocks
  • 找到 block_type=43 的 block,其 block_id 即为 whiteboard_id
  1. 获取画板内容
   curl "https://open.feishu.cn/open-apis/board/v1/whiteboards/{whiteboard_id}/nodes" \
     -H "Authorization: Bearer {token}"
  • 需权限:board:whiteboard:node:read

发送图片给用户

当需要将知识库中的图片发送给用户时,使用以下Python脚本:

import requests
import json

# 1. 获取 tenant_access_token
token_resp = requests.post(
    "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
    json={
        "app_id": "cli_a938e5e808b8dbca",
        "app_secret": "0ejwDP7CVN11Mm3PPhtYtfnMQONSJjDo"
    }
)
token = token_resp.json()["tenant_access_token"]

# 2. 上传图片
with open('/tmp/图片.png', 'rb') as f:
    img_resp = requests.post(
        "https://open.feishu.cn/open-apis/im/v1/images",
        headers={"Authorization": f"Bearer {token}"},
        files={"image": ("图片.png", f.read(), "image/png")},
        data={"image_type": "message"}
    )
image_key = img_resp.json()["data"]["image_key"]

# 3. 发送图片消息(需提供接收者的 open_id)
msg_resp = requests.post(
    "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id",
    headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
    json={
        "receive_id": "用户open_id",
        "msg_type": "image",
        "content": json.dumps({"image_key": image_key})
    }
)

处理电子表格(Sheet)

当知识库中的文档类型是 sheet(电子表格)时,需要使用 Sheets API 处理。

重要前提

必须开通 sheets:spreadsheet 权限(不是 readonly)!否则会返回 404。

读取电子表格步骤

步骤1:获取工作表列表

# API 路径:/sheets/v3/spreadsheets/{spreadsheetToken}/sheets/query
curl "https://open.feishu.cn/open-apis/sheets/v3/spreadsheets/{sheet_token}/sheets/query" \
  -H "Authorization: Bearer {token}"

返回示例:

{
  "data": {
    "sheets": [{
      "sheet_id": "b56f8e",
      "title": "Sheet1",
      "resource_type": "sheet"
    }]
  }
}

步骤2:读取表格数据

使用 v2 API 读取数据:

# API 路径:/sheets/v2/spreadsheets/{spreadsheetToken}/values/{sheetId}!A1:Z100
curl "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{sheet_token}/values/b56f8e!A1:Z100" \
  -H "Authorization: Bearer {token}"

返回示例:

{
  "data": {
    "valueRange": {
      "range": "b56f8e!A1:Z100",
      "values": [
        ["", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
        ["早饭", "油条", "油条", "油条", "油条", "包子", "包子", "包子"],
        ["午饭", "鱼香茄子", "鱼香茄子", "鱼香茄子", "鱼香茄子", "鱼香茄子", "鱼香茄子", "鱼香茄子"],
        ["晚饭", "红烧肉", "红烧肉", "红烧肉", "红烧肉", "红烧肉", "红烧肉", "红烧肉"]
      ]
    }
  }
}

完整读取电子表格示例

import requests
import json

# 获取 token
token_resp = requests.post(
    "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
    json={
        "app_id": "cli_a938e5e808b8dbca",
        "app_secret": "0ejwDP7CVN11Mm3PPhtYtfnMQONSJjDo"
    }
)
token = token_resp.json()["tenant_access_token"]

sheet_token = "电子表格的obj_token"

# 1. 获取工作表 ID
sheets_resp = requests.get(
    f"https://open.feishu.cn/open-apis/sheets/v3/spreadsheets/{sheet_token}/sheets/query",
    headers={"Authorization": f"Bearer {token}"}
)
sheet_id = sheets_resp.json()["data"]["sheets"][0]["sheet_id"]

# 2. 读取表格数据(使用 v2 API)
values_resp = requests.get(
    f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{sheet_token}/values/{sheet_id}!A1:Z100",
    headers={"Authorization": f"Bearer {token}"}
)
values = values_resp.json()["data"]["valueRange"]["values"]

# 3. 格式化输出(过滤空值)
for row in values:
    if any(cell is not None for cell in row):
        print(row)

注意事项

  1. 获取工作表用 v3,读取数据用 v2 - 这是飞书 API 的现状
  2. 必须开通 sheets:spreadsheet 权限 - 否则返回 404
  3. 表格数据可能很大 - 建议只读取需要的范围,如 A1:Z100

常见问题

| 问题 | 原因 | 解决方案 |
|------|------|----------|
| Search is not available | 知识库搜索未开放 | 改用 nodes 遍历 |
| Missing access token | token 过期 | 重新获取 tenantaccesstoken |
| receive_id_type is required | 发送消息缺参数 | URL 加 ?receive_id_type=open_id |
| WrongBaseToken | token 格式错误 | 确认使用的是正确的 token 类型 |
| NOTEXIST | 文档不存在或无权访问 | 检查 token 是否正确 |
| 404 page not found (sheets) | 缺少 sheets:spreadsheet 权限 | 在飞书后台开通该权限 |
| 读取表格返回空数据 | 使用的 API 版本不对 | 确认用 v2 API 读取值 |
| 未配置知识库 | 首次使用未配置 | 按上方"首次配置"步骤进行配置 |

输出格式

查询完成后,必须标注信息来源:

  • "📋 来源:飞书知识库 - [知识库名称]"
  • "📋 来源:飞书知识库 - 动物园排班表"