openclaw-feishu-docs-perm-auto

GitHub 作者 sadjjk

自动为飞书文档添加用户权限。每次创建飞书文档(多维表格/文档/电子表格/文件夹/云空间文件/知识库节点等)后自动添加用户权限,或用户反馈文档无权限时补充添加权限。适用于 OpenClaw Agent。

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install github:LeoYeAI~openclaw-master-skills~openclaw-feishu-docs-perm-auto
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/github%3ALeoYeAI~openclaw-master-skills~openclaw-feishu-docs-perm-auto/file -o openclaw-feishu-docs-perm-auto.md
# 飞书文档权限自动添加

> 🎯 **一句话总结**:飞书应用创建的文档,用户默认无权限。这个 skill 帮你自动添加权限。

---

## 前置条件

| 条件 | 说明 |
|------|------|
| 飞书开发者账号 | 需要有飞书开放平台的开发者权限 |
| 企业自建应用 | 已创建或有权创建飞书应用 |
| 应用权限 | 应用需开通 `docs:permission.member:create` 权限 |

---

## 变量速查表

| 变量名 | 来源 | 用途 |
|--------|------|------|
| `$APP_ID` | 配置文件 `channels.feishu.appId` | 应用标识 |
| `$APP_SECRET` | 配置文件 `channels.feishu.appSecret` | 应用密钥 |
| `$OWNER_OPEN_ID` | 配置文件或会话上下文 | 权限接收者 |
| `$TENANT_TOKEN` | API 获取 | 请求鉴权 |
| `$FILE_TOKEN` | 创建返回或 URL 解析 | 文档标识 |
| `$DOC_TYPE` | URL 路径识别 | 文档类型 |

---

## 第一步:检查配置 ⚠️

### 1.1 读取配置文件

配置文件位置:`~/.openclaw/openclaw.json`

### 1.2 检查必需字段

在 `channels.feishu` 下查找:

| 字段名 | 说明 | 示例值 | 必需性 |
|--------|------|--------|--------|
| `appId` | 飞书应用 ID | `cli_xxxxxxxx` | ✅ 必需 |
| `appSecret` | 飞书应用密钥 | `xxxxxxxx` | ✅ 必需 |
| `ownerOpenId` | 用户的 open_id | `ou_xxx` | ⚪ 可选* |

> *`ownerOpenId` 在配置文件中可选,但执行时必须有值。若配置文件缺失,从会话上下文提取(格式 `user:ou_xxx` → `ou_xxx`)。

配置示例:

```json
{
  "channels": {
    "feishu": {
      "enabled": true,
      "appId": "cli_xxxxxxxx",
      "appSecret": "xxxxxxxx",
      "ownerOpenId": "ou_xxx"
    }
  }
}
```

### 1.3 检查应用权限

使用 `feishu_app_scopes()` 查询当前飞书应用已开通的权限列表。

检查返回结果中是否包含 `docs:permission.member:create`:
- ✅ 有 → 权限正常,继续下一步
- ❌ 无 → 跳转到 [配置引导流程 C](#c-配置应用权限)

> 💡 如检查出有权限,后续可跳过此步骤。

### 1.4 判断逻辑

根据检查结果,按以下流程处理:

```
┌─────────────────────────────────────────────────────────┐
│  检查 appId + appSecret                                 │
│     ├─ ❌ 缺失 → [配置引导流程 A]                        │
│     └─ ✅ 完整 ↓                                        │
│  检查应用权限 docs:permission.member:create              │
│     ├─ ❌ 缺失 → [配置引导流程 C]                        │
│     └─ ✅ 完整 ↓                                        │
│  检查 ownerOpenId                                       │
│     ├─ ✅ 配置文件有 → 进入第二步                        │
│     ├─ ✅ 会话上下文有 → 提取使用,进入第二步             │
│     └─ ❌ 都没有 → [配置引导流程 B]                      │
└─────────────────────────────────────────────────────────┘
```

---

## 工具调用映射 🛠️

> 明确每个步骤应使用的工具,确保 Agent 能正确执行

| 步骤 | 操作 | 工具 | 说明 |
|------|------|------|------|
| 1.1 | 读取配置文件 | `read` | 读取 `~/.openclaw/openclaw.json` |
| 1.3 | 检查应用权限 | `feishu_app_scopes` | 查询已开通权限列表 |
| 2.2 | 获取 tenant_access_token | `exec` | 执行 curl 命令请求 API |
| 2.3 | 解析文档 token | 内置逻辑 | 从 URL 或返回值中提取 |
| 2.4 | 添加用户权限 | `exec` | 执行 curl 命令请求 API |
| 配置写入 | 保存 ownerOpenId | `edit` | 更新 `openclaw.json` |

**工具调用示例**:

```bash
# 读取配置文件
read("~/.openclaw/openclaw.json")

# 检查应用权限
feishu_app_scopes()

# 获取 tenant_access_token
exec('curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" ...')

# 添加权限
exec('curl -s -X POST "https://open.feishu.cn/open-apis/drive/v1/permissions/..." ...')

# 保存配置
edit("~/.openclaw/openclaw.json", oldText, newText)
```

---

## 第二步:执行权限添加 📋

> 前置条件:第一步检查全部通过

### 2.1 读取配置

**工具**:`read`

```bash
APP_ID="读取到的appId"
APP_SECRET="读取到的appSecret"
OWNER_OPEN_ID="读取到的ownerOpenId"
```

### 2.2 获取 tenant_access_token

**工具**:`exec`

**进度提示**:`[1/4] 获取访问令牌...`

**请求**:

```bash
curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
  -H "Content-Type: application/json" \
  -d "{
    \"app_id\": \"$APP_ID\",
    \"app_secret\": \"$APP_SECRET\"
  }"
```

**成功返回**:

```json
{
  "code": 0,
  "msg": "ok",
  "tenant_access_token": "xxxx",
  "expire": 5535
}
```

**失败返回**:

```json
{
  "code": 10003,
  "msg": "app id or app secret is invalid"
}
```

**处理**:
- ✅ 成功:提取 `tenant_access_token`,继续下一步
- ❌ 失败:提示用户检查 App ID 和 App Secret 是否正确

**token 缓存策略**:

| token 类型 | 有效期 | 缓存建议 |
|-----------|--------|----------|
| `tenant_access_token` | 约 2 小时 | 缓存至会话变量,过期前 5 分钟刷新 |

**缓存实现**:
- 使用会话级变量存储:`CACHED_TENANT_TOKEN`, `TOKEN_EXPIRE_TIME`
- 每次请求前检查:若 `now < TOKEN_EXPIRE_TIME - 300`,直接使用缓存

### 2.3 获取云文档 token

**进度提示**:`[2/4] 解析文档 token...`

**来源**:
1. 创建飞书文档后返回的 token 或文档 URL
2. 从用户提供的文档链接解析

**URL 解析规则**:

| 文档类型 | URL 示例 |
|----------|----------|
| 文件夹 | `https://xxx.feishu.cn/drive/folder/【token】` |
| 文件 | `https://xxx.feishu.cn/file/【token】` |
| 旧版文档 | `https://xxx.feishu.cn/docs/【token】` |
| 新版文档 | `https://xxx.feishu.cn/docx/【token】` |
| 电子表格 | `https://xxx.feishu.cn/【token】` |
| 多维表格 | `https://xxx.feishu.cn/base/【token】` |
| 知识空间 | `https://xxx.feishu.cn/wiki/settings/【token】` |
| 知识库节点 | `https://xxx.feishu.cn/wiki/【token】` |

> ⚠️ 复制 URL 时注意删除末尾多余的 `#` 符号。

**自动识别 doc_type**:

| URL 路径特征 | doc_type |
|-------------|----------|
| `/drive/folder/` | `folder` |
| `/file/` | `file` |
| `/docs/` | `doc` |
| `/docx/` | `docx` |
| `/base/` | `bitable` |
| `/wiki/` | `wiki` |
| 其他(根路径) | `sheet` |

**识别逻辑**:
1. 从 URL 提取 token(最后一个路径段,去除 `?` 和 `#` 后的内容)
2. 根据 URL 路径匹配 doc_type
3. 若无法匹配,提示用户提供文档类型

**变量定义**:
- `FILE_TOKEN = 获取到的云文档 token`
- `DOC_TYPE = 识别到的文档类型`

### 2.4 添加用户权限

**工具**:`exec`

**进度提示**:`[3/4] 添加用户权限...`

**请求**:

```bash
curl -s -X POST "https://open.feishu.cn/open-apis/drive/v1/permissions/{FILE_TOKEN}/members/batch_create?type={DOC_TYPE}" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {tenant_access_token}" \
  -d "{
    \"members\": [{
      \"member_type\": \"openid\",
      \"member_id\": \"$OWNER_OPEN_ID\",
      \"perm\": \"full_access\"
    }]
  }"
```

**参数说明**:

| 参数 | 来源 | 示例 |
|------|------|------|
| `{FILE_TOKEN}` | 创建文档时返回或 URL 解析 | `xxxxx` |
| `{DOC_TYPE}` | URL 路径自动识别 | `bitable` |
| `{tenant_access_token}` | 上一步获取 | `t-xxx` |
| `$OWNER_OPEN_ID` | ownerOpenId | `ou_xxx` |

**doc_type 可选值**:

| 值 | 文档类型 |
|----|----------|
| `bitable` | 多维表格 |
| `docx` | 新版文档 |
| `doc` | 旧版文档 |
| `sheet` | 电子表格 |
| `folder` | 文件夹 |
| `file` | 云空间文件 |
| `wiki` | 知识库节点 |


**成功返回**:

```json
{
  "code": 0,
  "msg": "Success",
  "data": {
    "members": [{
      "member_id": "xxxx",
      "member_type": "openid",
      "perm": "full_access"
    }]
  }
}
```

### 2.5 执行结果反馈

**进度提示**:`[4/4] 完成!`

**成功时**:

```
✅ 权限添加成功!

📄 文档:{文档标题或 token}
🔗 链接:{文档 URL}
👤 权限:完整权限 (full_access)
你现在可以直接访问和编辑这个文档了。
如果配置文件中没有ownerOpenId 并询问 是否需要将 ownerOpenId 写入配置文件中
```

**失败时**:

```
❌ 权限添加失败

原因:{错误信息}
解决方案:{具体步骤}

需要帮助?请提供以上信息。
```

---

## 使用示例 📝

### 示例 1:创建多维表格后自动添加权限

**用户**:帮我创建一个多维表格叫「项目进度追踪」

**Agent 执行流程**:

```
[1/3] 创建多维表格...
      → 调用 feishu_bitable_create_app(name="项目进度追踪")
      → 返回 app_token: "bascnxxx"

[2/3] 添加用户权限...
      → 触发 feishu-perm-auto skill
      → 检查配置:appId ✓ appSecret ✓ ownerOpenId ✓
      → 获取 tenant_access_token
      → 调用权限 API 添加 full_access

[3/3] 完成!
```

**Agent 回复**:

```
✅ 多维表格「项目进度追踪」已创建!

🔗 链接:https://xxx.feishu.cn/base/bascnxxx
🔐 已自动为你添加完整权限,可直接访问和编辑
```

---

### 示例 2:用户反馈文档无权限

**用户**:这个文档我打不开,提示没权限 https://xxx.feishu.cn/docx/doxcnxxx

**Agent 执行流程**:

```
[1/3] 解析文档信息...
      → URL 解析:token=doxcnxxx, doc_type=docx

[2/3] 检查配置并添加权限...
      → 检查配置:appId ✓ appSecret ✓ ownerOpenId ✓
      → 获取 tenant_access_token
      → 调用权限 API 添加 full_access

[3/3] 完成!
```

**Agent 回复**:

```
✅ 权限添加成功!

📄 文档:doxcnxxx
🔗 链接:https://xxx.feishu.cn/docx/doxcnxxx
👤 权限:完整权限 (full_access)

你现在可以直接访问和编辑这个文档了。
```

---

### 示例 3:首次使用,配置缺失

**用户**:帮我创建一个飞书文档

**Agent 执行流程**:

```
[1/2] 检查配置...
      → 读取 ~/.openclaw/openclaw.json
      → 发现 channels.feishu.appId 缺失

[2/2] 引导配置...
```

**Agent 回复**:

```
⚠️ 还没配置飞书应用凭证,需要先设置一下:

📱 获取飞书应用凭证:

1. 打开浏览器,访问:https://open.feishu.cn/app
2. 登录你的飞书账号
3. 点击「创建企业自建应用」或选择已有应用
4. 在左侧菜单找到「凭证与基础信息」
5. 复制以下内容:
   - App ID(cli_ 开头的字符串)
   - App Secret(点击「查看」后显示)

请把 App ID 和 App Secret 发给我,格式如下:
appId: cli_xxxxxxxx
appSecret: xxxxxxxx
```

**用户回复后**:

```
用户:appId: cli_aabbccdd
      appSecret: 1234567890abcdef

Agent:
[1/2] 验证凭证...
      → 获取 tenant_access_token 成功 ✓

[2/2] 保存配置...
      → 更新 ~/.openclaw/openclaw.json
```

**Agent 回复**:

```
✅ 飞书应用配置成功!

现在可以正常使用飞书功能了。需要我帮你创建文档吗?
```

---

### 示例 4:权限已存在(幂等处理)

**用户**:给这个文档加权限 https://xxx.feishu.cn/base/bascnxxx

**Agent 执行流程**:

```
[1/3] 解析文档信息...
      → token=bascnxxx, doc_type=bitable

[2/3] 添加权限...
      → 调用 API 返回错误码 99991661(成员已存在)

[3/3] 幂等处理...
      → 视为成功,无需重复添加
```