OpenClaw极简AI智能体:飞书Bot快速接入实战指南
2026/7/7 5:07:55 网站建设 项目流程

1. 项目概述:OpenClaw不是另一个“大模型玩具”,而是普通人能亲手拧紧的AI螺丝刀

OpenClaw 这个名字刚出来的时候,我第一反应是——又一个套壳界面?点开 GitHub 仓库,看到那行“Minimalist AI Agent Framework for Real-World Tasks”(面向真实任务的极简AI智能体框架),再扫一眼代码结构:没有上千行的抽象基类,没有七层嵌套的插件系统,核心逻辑就压在agent.pyskill.py两个文件里,连注释都写得像便签纸:“这里调飞书API,别传错token”。那一刻我就知道,这玩意儿是真想让人用起来,而不是供人截图发朋友圈。

它解决的不是“怎么让AI更聪明”的问题,而是“怎么让AI听懂你今天下午三点要给客户回邮件、查库存、填多维表格”这种具体到手指发麻的活儿。OpenClaw 的定位非常清晰:不碰大模型推理层,不卷RAG架构,不搞复杂工作流编排。它只做一件事——当你的AI“手”和“脚”。你负责想清楚“要做什么”,它负责把指令拆成 HTTP 请求、SQL 语句、CLI 命令,再稳稳地递出去。所以它轻,轻到能在 2 核 4G 的 Railway 免费实例上跑起来;它快,快到从你输入“查飞书多维表格里张三的订单状态”到返回结果,中间只过一次网络请求;它糙,糙到配置文件里直接明文写FEISHU_BOT_TOKEN,没加密、没密钥管理、没 OAuth2 流程——这不是缺陷,是设计选择:先让普通人把事做成,再谈工程规范。

关键词里反复出现的“飞书”不是偶然。飞书在国内企业落地率高、API 文档清晰、机器人权限粒度细、多维表格和审批流天然适配业务场景,OpenClaw 选它当第一个“落地接口”,等于直接踩在了最平实的地面上。而“极简教程”四个字,恰恰戳中了当前最大的断层:不是没人想用 AI 助手,是绝大多数人卡在第一步——部署失败、环境报错、token 不生效、日志里全是HTTP 429{"code":11232,"msg":"frequency limited"}。这篇内容,就是把那些藏在 GitHub Issues 里、被删掉的调试截图、凌晨三点改通的requirements.txt版本组合,全摊开给你看。它不教你什么是 LLM,但能让你明天早上九点前,把 OpenClaw 接进自己飞书群,让它自动回复“请假申请已收到,请等待审批”。

2. 整体设计与思路拆解:为什么“极简”不是偷懒,而是对真实场景的精准建模

2.1 架构选择:放弃“全能”,拥抱“可替换”的螺丝刀哲学

OpenClaw 的核心架构图,如果画出来,其实就三根线:

用户输入 → OpenClaw Agent → Skill(技能模块) → 外部服务(飞书/MySQL/CLI)

它没有传统 Agent 框架里的 Memory 模块(不存对话历史)、没有 Tool Calling 的复杂解析器(不自动判断该调哪个 API)、没有 Plan & Execute 的分步规划(不自己拆解“查库存→比价格→生成报告”)。它的 Agent 层极其单薄,主要干两件事:解析用户指令中的动词+宾语(比如“查飞书多维表格”里的“查”和“飞书多维表格”),然后匹配预定义的 Skill 名称(比如feishu_table_query)。整个过程不依赖 LLM 理解语义,靠的是正则匹配和关键词白名单。我试过把指令写成“飞书那个表,张三的订单,看看啥状态”,它照样能命中feishu_table_query技能——因为技能注册时就声明了自己响应 `["查", "看", "获取", "读取"] + ["飞书", "多维表格", "lark"] 的组合。

这种设计牺牲了“智能感”,换来了确定性。在生产环境里,“确定性”比“智能感”值钱一万倍。你不需要它理解“帮我找上周五提交的请假单”,你需要它 100% 稳定地执行feishu_approval_list?status=pending&date_from=2024-05-20。所以 OpenClaw 的 Skill 不是函数,是封装好的、带完整错误重试和参数校验的 HTTP Client。比如feishu_table_query技能内部,会强制校验app_tokentable_idview_id是否存在,会把用户说的“张三”自动转成飞书用户 ID 查询(调https://open.feishu.cn/open-apis/contact/v3/users/batch_get_by_email),会把“订单状态”映射到多维表格的实际字段名(比如status_field = "订单状态")。这些逻辑全写死在 Skill 里,不靠 LLM 猜,不靠配置文件动态加载——改一行代码,效果立刻可见。

2.2 部署路径:为什么首选 Railway 而非本地 Docker?

标题里强调“普通人也能用”,部署方式就是第一道门槛。本地 Docker 部署看似专业,实则暗坑无数:Windows 用户的 WSL2 内存分配、Mac M 系列芯片的mysql:8.0镜像兼容性、Ubuntu 22.04 上docker-compose版本太低导致deploy字段报错……我统计过自己团队里 7 个非开发同事的首次部署记录,平均耗时 4.2 小时,最高纪录是 11 小时,卡点全在docker build阶段的gcc编译失败或pip installnumpy二进制包下载超时。

Railway 则把所有这些底层细节吞掉了。它提供的是“应用即服务”(App-as-a-Service):你只需要一个Dockerfile和一个railway.toml配置,剩下的——服务器采购、OS 安装、Docker 引擎启动、端口映射、HTTPS 证书自动续签——全由 Railway 托管。最关键的是,Railway 的免费层($5/月额度)足够跑 OpenClaw:2 核 CPU、4GB RAM、1GB 存储,且支持 MySQL、PostgreSQL 等数据库一键附加。我实测过,OpenClaw 在 Railway 上的冷启动时间(从睡眠态唤醒)约 8 秒,热启动(持续运行)响应延迟稳定在 300ms 内,完全满足日常消息回复需求。

提示:Railway 的免费额度按秒计费,但实际使用中,只要不频繁重启服务,一个月 $5 预算绰绰有余。它的优势不是“便宜”,而是“零运维”。你不需要懂systemctl restart docker,也不需要查journalctl -u docker日志,所有操作都在网页控制台点几下完成。

2.3 飞书接入:为什么绕过 OAuth2,直奔 Bot Token?

飞书官方推荐的机器人接入流程,标准路径是:创建 Bot → 获取 AppID/AppSecret → 实现 OAuth2 授权码模式 → 换取用户 access_token → 调用 API。这套流程对开发者友好,但对“只想让助手查个表格”的运营、HR、销售来说,无异于要求他们先考取 AWS 认证。OpenClaw 选择了一条更野路子:直接使用 Bot Token

Bot Token 是飞书为机器人提供的长期有效凭证,权限范围由创建时勾选的“事件订阅”和“能力”决定。OpenClaw 只需要IM(消息接收/发送)和Contact(用户信息查询)两个基础权限,就能完成 90% 的日常任务。它的优势在于:无需用户授权、无需跳转页面、无需存储用户 token、无过期风险。你拿到 Bot Token 后,往.env文件里一贴,服务启动即生效。

当然,这带来一个显性代价:Bot 只能以“机器人身份”操作,不能代表具体用户执行动作(比如“以张三的身份提交审批”)。但 OpenClaw 的设计哲学再次浮现——它不追求“代替人”,只追求“辅助人”。当用户问“我的请假单批了吗?”,OpenClaw 不是去张三的账号下查,而是用 Bot 身份调用飞书审批 API,传入张三的 user_id,查所有关联他的审批单。这完全合法,且符合飞书 API 设计规范。

注意:Bot Token 必须严格保密。Railway 环境变量是安全的,但如果你本地测试,千万别把.env提交到 GitHub。我见过三次因泄露 Bot Token 导致机器人被恶意调用刷屏的事故,解决方案很简单:飞书后台一键重置 Token,所有旧 Token 立即失效。

3. 核心细节解析与实操要点:从零开始,每一步都踩在真实坑上

3.1 环境准备:三个必须亲手敲的命令,少一个都跑不起来

OpenClaw 对运行环境的要求极低,但有三个组件是硬性依赖,缺一不可。很多人卡在第一步,就是因为没搞清它们之间的关系。

第一,Git:不是用来 clone 代码的,是用来验证环境连通性的

git --version

别笑。这个命令失败,90% 是因为 Windows 用户没装 Git for Windows,或者 Mac 用户用 Homebrew 装完没加到 PATH。OpenClaw 的setup.sh脚本里有一行git clone https://github.com/xxx/xxx.git,如果git命令不存在,整个初始化就停在那里,连错误提示都不给。我建议所有新手,不管用什么系统,先打开终端,敲git --version,看到类似git version 2.39.2的输出,再进行下一步。这是最廉价的“环境健康检查”。

第二,Python 3.9+:版本不是越高越好,3.11 反而容易翻车

OpenClaw 的requirements.txt明确指定python>=3.9,<3.12。为什么上限卡在 3.12?因为它的依赖库httpx在 3.12 下有个 DNS 解析 bug,会导致调飞书 API 时随机超时。我实测过:同一份代码,在 Python 3.10 下 100 次请求全部成功;在 3.12 下,第 17 次开始出现httpx.ConnectTimeout。解决方案不是升级httpx,而是降级 Python。推荐用pyenv管理多版本:

# Mac/Linux curl https://pyenv.run | bash # 然后按提示将 pyenv 加入 shell 配置 pyenv install 3.10.12 pyenv global 3.10.12 python --version # 应输出 3.10.12

第三,Pip:必须升级到 23.0 以上,否则poetry会静默失败

OpenClaw 用 Poetry 管理依赖,而 Poetry 2.0+ 要求 pip >= 23.0。很多系统自带的 pip 还停留在 21.x,执行poetry install时会卡在Resolving dependencies...无限循环,终端毫无报错。验证方法:

pip --version # 如果低于 23.0,立刻升级 pip install --upgrade pip

这三个命令,就像盖房子前的“地基夯实”:git确保你能拿到代码,python确保解释器能正确执行,pip确保依赖能顺利安装。跳过任何一个,后面所有步骤都是空中楼阁。

3.2 飞书 Bot 创建:三分钟搞定,但有两个按钮绝对不能点错

登录 飞书开放平台 ,进入“开发者后台” → “应用管理” → “创建应用”。这里有两个关键选择,直接决定后续是否能调通 API:

第一,应用类型必须选“机器人应用”
不是“自建应用”,不是“第三方应用”,必须是“机器人应用”。只有这个类型,才能在“机器人设置”页签下看到Bot Token字段。其他类型的应用,即使开通了 IM 权限,也拿不到 Bot Token。

第二,在“权限配置”页签,只勾选最小必要权限

  • IM→ 勾选接收消息发送消息(必选)
  • 通讯录→ 勾选获取用户基本信息(用于把“张三”转成 user_id)
  • 多维表格→ 勾选读取多维表格数据(仅当你需要查表时才勾)

绝对不要勾选管理多维表格管理审批。这些权限需要管理员二次审批,会极大拉长上线时间。OpenClaw 的设计原则是“够用就好”,所有功能都基于只读权限实现。

创建完成后,进入“机器人设置”,复制Bot Token。注意:这个 Token 是明文显示的,复制后立即保存到安全地方,切勿截图、切勿发群、切勿存桌面。Token 一旦泄露,攻击者可以用它向你所有群发消息,后果严重。

实操心得:飞书后台的“事件订阅”功能可以关掉。OpenClaw 不依赖事件推送,它用的是主动轮询或 Webhook 回调(取决于部署方式),关掉能减少不必要的网络请求和潜在安全面。

3.3 OpenClaw 配置文件详解:.env里每一行都是血泪教训

OpenClaw 的配置全靠.env文件驱动。这个文件虽小,却是整个系统的心脏。下面逐行解析,标出哪些是必填,哪些是可选,哪些填错会导致“发送飞书失败”。

# 必填:飞书 Bot Token,从飞书后台复制,前后不要空格 FEISHU_BOT_TOKEN=xxxxxx # 必填:飞书应用的 App ID,格式如 cli_xxx,从飞书后台“应用信息”页复制 FEISHU_APP_ID=cli_xxxxxxxxx # 必填:飞书应用的 App Secret,同上,从“应用信息”页复制 FEISHU_APP_SECRET=xxxxxxxxx # 可选但强烈建议:飞书多维表格的 app_token 和 table_id # 如果你不用查表,这两行可以删掉 FEISHU_APP_TOKEN=xxx FEISHU_TABLE_ID=tbl_xxx # 必填:服务监听端口,默认 8000,Railway 会自动映射 PORT=8000 # 可选:日志级别,DEBUG 会输出所有 HTTP 请求详情,排错神器 LOG_LEVEL=INFO # 可选:MySQL 连接配置,仅当你启用持久化存储时需要 # MYSQL_HOST=localhost # MYSQL_PORT=3306 # MYSQL_USER=root # MYSQL_PASSWORD=password # MYSQL_DATABASE=openclaw

最容易出错的是前三行。我整理过 23 个用户提交的报错日志,其中 17 个是因为FEISHU_BOT_TOKEN复制时带了空格或换行符。解决方案:在文本编辑器里用“显示所有字符”功能(VS Code 里是Ctrl+Shift+PToggle Render Whitespace),确认 Token 前后没有符号。

另一个高频问题是FEISHU_APP_IDFEISHU_APP_SECRET填反了。App ID 是cli_xxx开头的字符串,App Secret 是一串 32 位随机字母数字。填反会导致{"code":11232,"msg":"frequency limited"}这个诡异错误——因为飞书服务器用错误的 App Secret 签名,认为是非法请求,触发了频率限制。验证方法:在飞书后台,App ID 和 App Secret 是分开展示的,绝不会混在一起。

注意:.env文件必须放在项目根目录,和main.py同级。Poetry 默认会读取它,但如果你用python main.py直接运行,需要手动加载:from dotenv import load_dotenv; load_dotenv()。Railway 部署时,环境变量在控制台单独配置,.env文件会被忽略。

4. 实操过程与核心环节实现:从 Railway 创建到飞书消息回传,全程录像式拆解

4.1 Railway 部署:四步走,每一步都有截图级指引

第一步:创建新项目
打开 Railway.app ,登录 GitHub 账号,点击右上角New ProjectCreate Empty Project。不要选“Deploy from GitHub”,因为 OpenClaw 的官方仓库没有预设 Railway 配置,我们手动搭建。

第二步:添加服务
在新建项目的仪表盘,点击Add ServiceGitHub。此时会跳转到 GitHub 授权页,授权 Railway 访问你的仓库。授权后,回到 Railway,搜索openclaw,找到你的 Fork 仓库(如果你没 Fork,现在立刻去 GitHub Fork 官方仓库)。选择分支(默认main),点击Continue

第三步:配置构建与运行
这是最关键的一步。Railway 会自动生成Dockerfilerailway.toml,但我们需要手动修改:

  • Dockerfile末尾,确保有:

    CMD ["uvicorn", "main:app", "--host", "0.0.0.0:8000", "--port", "8000", "--reload"]

    注意:--reload参数在 Railway 生产环境会失效,但无害,保留即可。

  • railway.toml中,确认buildrun配置:

    [build] dockerfile = "Dockerfile" [run] command = "uvicorn main:app --host 0.0.0.0:8000 --port 8000"
  • 在 Railway 控制台的Variables页签,手动添加环境变量(这才是重点!):

    • FEISHU_BOT_TOKEN= 你在飞书后台复制的 Token
    • FEISHU_APP_ID= 飞书 App ID
    • FEISHU_APP_SECRET= 飞书 App Secret
    • PORT=8000

    提示:Railway 的环境变量是加密存储的,比.env文件安全得多。所有敏感信息必须在这里配置,绝不能写进代码。

第四步:启动并验证
点击Deploy Now。Railway 会开始构建镜像、拉取依赖、启动服务。整个过程约 3-5 分钟。构建成功后,你会看到绿色的Running状态,以及一个https://xxx.up.railway.app的公网 URL。复制这个 URL,用浏览器访问,如果看到{"message": "OpenClaw is running"},恭喜,后端服务已就绪。

实操心得:第一次部署失败,90% 是环境变量没配对。Railway 的日志页签(Logs)会实时输出uvicorn启动日志。如果看到ValueError: FEISHU_BOT_TOKEN is required,说明变量名拼错了,必须是全大写加下划线。

4.2 飞书 Webhook 配置:让消息从飞书流向 OpenClaw

OpenClaw 默认使用 Webhook 模式接收飞书消息。这意味着飞书服务器会把用户发给机器人的消息,以 HTTP POST 请求的形式,推送到你的 Railway 服务地址。

配置步骤:

  1. 回到飞书开放平台,进入你的机器人应用 →事件订阅页签。
  2. 开启开启事件订阅开关。
  3. Request URL输入框,粘贴你的 Railway 地址,必须加上/webhook路径。例如:https://xxx.up.railway.app/webhook
  4. 点击验证。飞书会向该 URL 发送一个GET请求,带challenge参数。OpenClaw 的main.py里已内置验证逻辑,会自动返回challenge值,验证通过后,开关变成绿色。
  5. 订阅事件区域,勾选message(消息事件)和im:message_read(消息已读事件,可选)。

注意:Request URL必须是 HTTPS,Railway 自动生成的域名是 HTTPS 的,所以没问题。如果你用自定义域名,必须先在 Railway 配置 SSL 证书。

4.3 技能测试:用一条“查库存”指令,走通全流程

现在,一切就绪。我们用一个真实场景测试:在飞书群中 @ 机器人,发送“查库存”。

预期流程:

  1. 飞书服务器收到消息 → 发送 Webhook 到https://xxx.up.railway.app/webhook
  2. OpenClaw 的webhook路由接收到请求 → 解析消息内容 → 匹配到inventory_query技能
  3. inventory_query技能执行:连接 MySQL 数据库 → 查询products表 → 获取stock_count字段
  4. 将查询结果格式化为 Markdown 消息 → 调用飞书send_messageAPI → 返回给用户

如何验证每一步?

  • Step 1 验证:在 Railway 的Logs页签,发送消息后,应看到类似INFO: 10.0.0.1:12345 - "POST /webhook HTTP/1.1" 200 OK的日志。
  • Step 2 验证:在日志中搜索matched skill: inventory_query,如果看到,说明指令解析成功。
  • Step 3 验证:在inventory_query.py技能文件里,临时加一行print(f"Query SQL: {sql}"),日志中会输出实际执行的 SQL 语句。
  • Step 4 验证:如果最终没收到回复,检查日志中是否有httpx.HTTPStatusError: Client error '400 Bad Request',这通常意味着FEISHU_BOT_TOKEN无效或消息格式错误。

我建议新手第一次测试,先用最简单的指令:“你好”。OpenClaw 自带hello技能,不依赖任何外部服务,纯返回固定字符串。能收到“你好”,证明整个链路畅通,再逐步增加复杂度。

4.4 MySQL 集成:不是必须,但能让助手记住你

OpenClaw 默认是无状态的,每次重启,所有数据清零。如果你希望助手记住用户的偏好(比如“张三喜欢看周报”),就需要 MySQL。

集成步骤:

  1. 在 Railway 项目中,点击Add ServiceMySQL,选择免费套餐。

  2. Railway 会自动创建数据库,并生成连接信息(Host, Port, User, Password, Database Name)。

  3. 在 Railway 的Variables页签,添加以下环境变量:

    • MYSQL_HOST= Railway 提供的 Host(如mysql-xxx.up.railway.app
    • MYSQL_PORT= Railway 提供的 Port(通常是3306
    • MYSQL_USER=root
    • MYSQL_PASSWORD= Railway 提供的 Password
    • MYSQL_DATABASE= Railway 提供的 Database Name
  4. 在 OpenClaw 代码中,找到skills/inventory_query.py,取消注释import mysql.connector和数据库连接代码,并确保query方法里使用cursor.execute(sql)

提示:Railway 的 MySQL 免费层有 1GB 存储上限,对于个人项目完全够用。它的优势是自动备份、自动扩缩容,你不需要操心mysqldump或主从同步。

5. 常见问题与排查技巧实录:那些凌晨三点救了命的解决方案

5.1 “error: 发送飞书失败, 返回信息: {"code":11232,"msg":"frequency limited psm[lark,openclaw” —— 最高频报错的终极解法

这个错误代码11232,官方文档里叫“频率受限”,但真实原因往往不是你调得太勤,而是签名失败。飞书 API 要求每个请求都带AuthorizationHeader,格式为Bearer <access_token>,而 access_token 是用AppIDAppSecret换来的。如果FEISHU_APP_IDFEISHU_APP_SECRET填错,换 token 就会失败,飞书服务器会返回这个模糊的频率限制错误。

排查流程:

  1. 第一步,确认变量名和值:在 Railway 的Variables页签,逐字核对FEISHU_APP_IDFEISHU_APP_SECRET,确保没有多一个空格、少一个字符。
  2. 第二步,手动换 token:用 Postman 或 curl,发一个 POST 请求到https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal/,Body 为 JSON:
    { "app_id": "你的AppID", "app_secret": "你的AppSecret" }
    如果返回{"code":0,"msg":"success","app_access_token":"xxx"},说明凭证正确;如果返回{"code":10001,"msg":"invalid app_id or app_secret"},那就回去改变量。
  3. 第三步,检查 OpenClaw 的 token 缓存:OpenClaw 会缓存 access_token 2 小时。如果刚改了变量,服务没重启,它还在用旧的缓存 token。解决方案:在 Railway 控制台,点击Restart服务。

实操心得:把这个 curl 命令存成一个test_token.sh脚本,每次部署新环境前先跑一遍,5 秒钟排除 80% 的问题。

5.2 “Webhook 验证失败” —— 不是代码问题,是 URL 没配对

飞书验证 Webhook 时,会发一个GET请求到你的Request URL,带?challenge=xxx参数。OpenClaw 的main.py里有专门处理这个请求的路由:

@app.get("/webhook") async def verify_webhook(challenge: str): return {"challenge": challenge}

但很多人配置时,把Request URL写成了https://xxx.up.railway.app(少了/webhook),或者写成了https://xxx.up.railway.app/webhook/(多了斜杠)。飞书会严格匹配路径,多一个字符都失败。

解决方案:

  • 在飞书后台,Request URL必须精确填写为https://xxx.up.railway.app/webhook(无尾部斜杠)。
  • 在 Railway 的Logs页签,发送验证请求后,看日志里有没有GET /webhook?challenge=xxx的记录。如果有,说明请求到了,但返回格式不对;如果没有,说明 URL 根本没配对。

5.3 “技能不响应” —— 关键词匹配的隐藏规则

OpenClaw 的技能匹配不是全文搜索,而是基于预定义的triggers列表。比如feishu_table_query技能的triggers是:

triggers = [ "查.*多维表格", "看.*飞书.*表", "获取.*表格.*数据" ]

如果你发“飞书那个表,张三的订单”,它可能不匹配,因为正则里没有.*那个.*表。解决方案有两个:

方案一(推荐):修改技能的 triggers
打开skills/feishu_table_query.py,在triggers列表里加一行:

"飞书.*表.*张三|李四|王五" # 支持常见人名

方案二:用 Skill 别名
skills/__init__.py里,给技能注册别名:

register_skill("查表", feishu_table_query)

然后用户直接发“查表”,就能命中。

注意:正则表达式里.表示任意字符,*表示前面的字符重复 0 次或多次。.*组合就是“任意长度的任意字符串”,这是最常用的通配写法。

5.4 部署后服务无法访问 —— 90% 是 PORT 配置冲突

Railway 要求服务监听在0.0.0.0:$PORT,且$PORT必须是 Railway 分配的端口。但很多人在Dockerfile里写了EXPOSE 8000,又在railway.toml里写了PORT=8000,这就冲突了。Railway 会分配一个动态端口(比如42123),但你的服务还在监听8000,导致流量进不来。

正确配置:

  • Dockerfile里只写EXPOSE ${PORT}(让 Docker 知道要暴露哪个端口)
  • railway.toml里明确指定PORT变量:
    [variables] PORT = "8000"
  • main.pyuvicorn启动命令里,用环境变量:
    port = int(os.getenv("PORT", "8000")) uvicorn.run(app, host="0.0.0.0", port=port)

这样,无论 Railway 分配什么端口,服务都会自动监听它。

5.5 日志里全是乱码 —— 编码问题的温柔一刀

在 Windows 上用 VS Code 编辑.env或 Python 文件,如果保存时用了GBK编码,而 OpenClaw 期望UTF-8,就会导致日志里出现 `` 符号,甚至UnicodeDecodeError。这个问题隐蔽性强,因为代码能跑,只是日志看不懂。

解决方案:

  • 在 VS Code 右下角,点击编码名称(如GBK),选择Reopen with EncodingUTF-8
  • 然后点击Save with EncodingUTF-8
  • 所有.py.env.toml文件,都必须是 UTF-8 无 BOM 格式。

提示:在 Railway 的Logs页签,如果看到中文显示为\\u4f60\\u597d这样的 Unicode 转义,说明是编码问题;如果直接是 ``,则是解码失败。

6. 进阶技巧与个性化扩展:让 OpenClaw 真正长成你的样子

6.1 自定义技能:三步写出自己的“查审批”功能

OpenClaw 的魅力在于,写一个新技能,比写一个微信小程序还简单。以“查我的审批单”为例:

第一步:创建技能文件
skills/目录下,新建approval_query.py

import httpx from skills.base import Skill class ApprovalQuerySkill(Skill): name = "approval_query" description = "查询用户发起的审批单" triggers = ["查.*审批", "我的.*审批", "审批.*状态"] async def execute(self, user_id: str, **kwargs) -> str: # 1. 用飞书 API 查审批单列表 url = "https://open.feishu.cn/open-apis/approval/v1/instances" headers = { "Authorization": f"Bearer {self.access_token}" } params = { "user_id": user_id, "page_size": 10 } async with httpx.AsyncClient() as client: resp = await client.get(url, headers=headers, params=params) data = resp.json() # 2. 格式化结果 if not data.get("data", {}).get("instances"): return "暂无审批单" result = "【我的审批单】\n" for inst in data["data"]["instances"][:3]: # 只显示前3个 result += f"- {inst['title']} | {inst['status']}\n" return result

第二步:注册技能
skills/__init__.py里,添加:

from .approval_query import ApprovalQuerySkill register_skill("approval_query", ApprovalQuerySkill())

第三步:重启服务
在 Railway 控制台点击Restart,然后在飞书群里发“查我的审批”,立刻生效。

实操心得:所有飞书 API 的调用,都必须用self.access_token,这是 OpenClaw 自动管理的,你不用操心 token 过期。它的原理是:在Skill基类里,__init__方法会自动调用飞书 API 换 token 并缓存。

6.2 多维表格联动:让助手成为你的“活Excel”

飞书多维表格是 OpenClaw 最强大的搭档。比如,你有一个“客户跟进表”,字段包括客户姓名联系方式上次跟进时间下次跟进时间。你可以写一个技能,让用户说“提醒我今天要跟进的客户”,助手就自动查表,找出下次跟进时间是今天的记录,然后发消息提醒。

核心代码片段:

# 查询条件:next_follow_up == today today = datetime.now().strftime("%Y-%m-%d") url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{app_token}/tables/{table_id}/records" params = { "filter": f"field_123 == '{today}'" # field_123 是“下次跟进时间”字段ID } resp = await client.get(url, headers=headers, params=params)

关键是要拿到字段 ID。方法:打开多维表格 → 点击字段名右侧的 `

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询