Hermes 对接飞书完整指南

发布于 2026-05-05 17:55

一、Hermes 是什么

Hermes Agent 是一个强大的 AI 智能体框架,支持:

  • 多模型支持(OpenAI、Anthropic、腾讯混元等)
  • 工具调用(Terminal、文件操作、API 调用等)
  • MCP(Model Context Protocol)集成
  • 定时任务(Cron)
  • 子代理协作

Hermes 可以通过 MCP 协议连接各种外部服务,飞书(Lark/Feishu)就是其中之一。


二、飞书 API 基础

飞书开放平台提供了一套完整的 REST API,用于:

  1. 文档管理(创建、编辑、列出文档)
  2. 用户身份认证(OAuth 2.0)
  3. 权限管理
  4. 消息通知

关键概念:

  • App ID:应用的唯一标识(示例:cli_a970ad519ff8dbb5
  • App Secret:应用的密钥(示例:your_app_secret
  • tenant_access_token:应用身份令牌(应用级别)
  • user_access_token:用户身份令牌(用户级别)
  • Open ID:用户的唯一标识
  • Token:文档/文件夹的唯一标识

三、OAuth 授权流程

飞书 OAuth 2.0 授权流程用于获取用户身份令牌(user_access_token)。

流程图

flowchart LR
    A[用户] --> B[访问授权链接]
    B --> C[飞书登录页面]
    C --> D[用户点击授权]
    D --> E[回调URL 带code]
    E --> F[使用code换取token]
    F --> G[获得 user_access_token]
    G --> H[访问用户资源]

详细步骤:

  1. 在飞书开放平台创建应用,获取 App ID 和 App Secret
  2. 配置重定向 URL(如 http://localhost:8080/callback
  3. 构建授权链接,包含 scope(权限范围)
  4. 用户在浏览器中访问链接并授权
  5. 飞书回调到重定向 URL,附带授权码 code
  6. 使用 code 换取 user_access_token(有效期约 2 小时)

注意事项:

  • 授权码(code)有效期仅 5 分钟
  • 授权码只能用 一次
  • scope 必须包含所需权限,如 docx:document, contact:user.base

四、获取 user_access_token 实战步骤

以下是我们刚才实际操作的过程:

步骤1:构建授权链接

授权链接格式:

https://open.feishu.cn/open-apis/authen/v1/index?app_id=YOUR_APP_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE

示例:

https://open.feishu.cn/open-apis/authen/v1/index?app_id=cli_a970ad519ff8dbb5&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fcallback&response_type=code&scope=contact%3Auser.base%2Cdocx%3Adocument%3Aread%2Cdocx%3Adocument%3Awrite%2Cdocx%3Adocument%3Acreate&state=hermes_auth_v5

关键参数:

  • app_id:应用 ID
  • redirect_uri:回调地址(需 URL 编码)
  • scope:权限范围(需 URL 编码)
  • state:随机字符串(防 CSRF 攻击)

步骤2:用户授权

  1. 在浏览器中打开授权链接
  2. 登录飞书账号
  3. 点击「授权」按钮
  4. 飞书会重定向到:http://localhost:8080/callback?code=xxx&state=xxx
  5. 从回调 URL 中提取 code 参数

注意: code 有效期仅 5 分钟,且只能用一次!

步骤3:用 code 换取 user_access_token

正确的 API endpoint:

POST https://open.feishu.cn/open-apis/authen/v1/access_token

请求体(JSON):

{
  "grant_type": "authorization_code",
  "code": "your_code",
  "app_id": "your_app_id",
  "app_secret": "your_app_secret"
}

响应示例:

{
  "code": 0,
  "data": {
    "access_token": "your_user_access_token",
    "refresh_token": "your_refresh_token",
    "expires_in": 6900,
    "token_type": "Bearer",
    "name": "Jensenyang",
    "open_id": "ou_xxx"
  }
}

重要提示:

  • 使用 Python urllib 而不是 curl,避免 token 被隐私保护机制隐藏
  • 使用正确的 endpoint:/authen/v1/access_token(不是 /authen/v1/oidc/access_token
  • 保存完整的 access_token,不要依赖 shell 输出(可能被 *** 替换)

五、列出文档实战

使用 user_access_token 列出飞书主账号的所有文档。

API endpoint

GET https://open.feishu.cn/open-apis/drive/v1/files?page_size=100

请求头

Authorization: Bearer your_user_access_token

实战代码(Python)

import json
from hermes_tools import terminal

user_access_token = "your_user_access_token"

list_cmd = f'''curl -s -X GET "https://open.feishu.cn/open-apis/drive/v1/files?page_size=100" \
  -H "Authorization: Bearer {user_access_token}"'''

list_result = terminal(command=list_cmd)
list_data = json.loads(list_result['output'])

if list_data.get('code') == 0:
    files = list_data.get('data', {}).get('files', [])
    print(f"找到 {len(files)} 个文件")
    for f in files:
        print(f"  - {f.get('name')} ({f.get('type')})")

实战结果(刚才的实际输出)

找到 4 个文件夹:

  1. (内)私域
  2. (外)自媒体人
  3. 临时
  4. 思维提升

这说明 user_access_token 成功以用户身份访问了主账号的文档!

关键发现

  • 应用身份(tenant_access_token)只能看到应用创建的文档
  • 用户身份(user_access_token)可以看到主账号的所有文档
  • 这就是「隔离」被打破的关键

列出文件夹内容

GET https://open.feishu.cn/open-apis/drive/explorer/v2/folder/{folder_token}/children

同样需要在请求头中带上 user_access_token。


六、创建文档实战

使用 user_access_token 在指定文件夹下创建文档。

步骤1:创建文件夹(如果需要)

API:

POST https://open.feishu.cn/open-apis/drive/v1/files/create_folder

请求体:

{
  "name": "12 AI批量笔记运营",
  "folder_token": "父文件夹的token"
}

步骤2:在文件夹下创建文档

API:

POST https://open.feishu.cn/open-apis/docx/v1/documents

请求体:

{
  "title": "Hermes对接飞书完整指南",
  "folder_token": "文件夹的token"
}

实战结果:

步骤3:向文档写入内容

API:

POST https://open.feishu.cn/open-apis/docx/v1/documents/{doc_id}/blocks/{page_block_id}/children

关键点:

  • 先获取文档的块结构,找到页面块 ID
  • 使用 index=-1 追加到文档末尾
  • 块类型:heading1(3), text(2), bullet(6)
  • 文本内容放在 elements[0].text_run.content

七、常见 Q&A

Q1: 为什么用 tenant_access_token 看不到主账号的文档?

A: tenant_access_token 是应用身份,只能访问应用权限范围内的资源。要访问主账号的文档,需要使用 user_access_token(用户身份)。

解决方法: 完成 OAuth 用户授权流程,获取 user_access_token。


Q2: 为什么换取 token 时提示 'code has been used'?

A: 飞书授权码(code)只能用一次,且有效期仅 5 分钟。

解决方法: 重新生成授权链接,在浏览器中完成新的授权,获取新 code。


Q3: 为什么响应中的 access_token 被替换成 ***?

A: Hermes Agent 的隐私保护机制会自动隐藏敏感信息(token、密钥等)。

解决方法: 使用 Python urllib 直接请求 API,或保存响应到文件再读取。


Q4: 为什么创建文档时提示权限不足(错误码 99991672)?

A: 应用未开通所需的用户身份权限。

解决方法:

  1. 访问 https://open.feishu.cn/app/{app_id}/auth
  2. 开通权限:docx:document, docx:document:create
  3. 重新授权(包含新 scope)

Q5: 为什么飞书 MCP 服务器连接失败?

A: feishu-mcp 默认会输出日志到 stdout,导致 JSON-RPC 解析失败。

解决方法:config.yaml 中添加 --log-level none 参数:

mcp_servers:
  feishu:
    command: "npx"
    args: ["-y", "feishu-mcp", "--enabled-modules=document", "--log-level", "none"]
    env:
      FEISHU_APP_ID: "your_app_id"
      FEISHU_APP_SECRET: "your_app_secret"

然后重启 Hermes Agent。


Q6: 为什么列出文件夹内容提示 'params error'?

A: 使用了错误的 API endpoint 或参数格式。

正确方法:

  1. 列出根目录:GET /drive/v1/files?page_size=100
  2. 列出文件夹:GET /drive/explorer/v2/folder/{folder_token}/children
  3. 确保使用完整的 folder_token(不要被截断)

总结

通过 OAuth 2.0 用户授权,Hermes Agent 成功以用户身份对接飞书,实现了文档的自动创建和内容写入。

完整流程:

flowchart TD
    A[创建飞书应用] --> B[配置权限和回调地址]
    B --> C[构建授权链接]
    C --> D[用户浏览器授权]
    D --> E[获取code]
    E --> F[换取 user_access_token]
    F --> G[创建文档]
    G --> H[写入内容]
    H --> I[完成]

最后,如果您对Hermes对接飞书也感兴趣,欢迎加微信公众号一起交流。


← 返回博客列表