Jetson + OpenClaw + 飞书机器人:构建一个让边缘设备成为 AI Agent 助手的远程交互系统

Jetson + OpenClaw + 飞书机器人:构建一个让边缘设备成为 AI Agent 助手的远程交互系统

1. 背景

最近我希望在 Jetson 上部署一个本地 Openclaw,并通过飞书机器人进行远程交互,从而让闲置的边缘设备秒变我的高级AI助手。整体目标很简单:

  • 在 Jetson 上运行 OpenClaw
  • 接入自己的模型 API(我使用的是阿里的Coding Plan)
  • 通过飞书群聊 @机器人 或者私聊机器人直接调用本地 Agent

最终希望实现这样的工作流:

Feishu Group ↓ Feishu Bot ↓ OpenClaw Gateway (Jetson) ↓ Agent ↓ LLM API ↓ 返回飞书消息 

这篇文章记录一下从源码部署 OpenClaw,到接通飞书机器人的完整过程,以及过程中踩到的几个关键坑。


2. 环境信息

本文使用环境如下:

Jetson 环境

uname -a # 输出 Linux agx229-desktop 5.10.216-tegra #1 SMP PREEMPT Tue Mar 4 01:35:16 PST 2025 aarch64 aarch64 aarch64 GNU/Linux lsb_release -a # 输出 Distributor ID: Ubuntu Description: Ubuntu 20.04.6 LTS Release: 20.04 Codename: focal nvcc --version # 输出 Cuda compilation tools, release 11.4, V11.4.315 

说明

当前平台为:

  • Jetson ARM64
  • Ubuntu 20.04
  • CUDA 11.4

这点很重要,因为后续某些依赖在 ARM64 + Ubuntu 20.04 上会遇到额外兼容性问题。


3. 安装 Node.js 与 pnpm

OpenClaw 是一个 Node.js 项目,因此首先需要准备 Node 环境。

建议使用 Node 22。

# 安装 nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash # 重新加载 shell 配置 source ~/.bashrc # 如果使用 zsh source ~/.zshrc # 配置镜像加速下载(可选,建议中国用户使用) nvm node_mirror https://npmmirror.com/mirrors/node/ nvm npm_mirror https://npmmirror.com/mirrors/npm/ # 安装并使用 Node.js 20 nvm install 20 nvm use 20 # 设为默认版本 nvm alias default 20 # 配置 npm 镜像加速 npm config set registry https://registry.npmmirror.com # 验证安装 node --version npm --version

还需要安装 pnpm

npm install -g pnpm 

安装后检查:

pnpm -v 

4. 配置 pnpm 环境变量

这一步非常重要。

如果不配置 PNPM_HOME,后面可能出现这些问题:

  • pnpm link --global 报错
  • OpenClaw 自动构建 UI 时提示找不到 pnpm
  • 全局命令不可用

建议将下面内容加入 ~/.bashrc

# pnpm export PNPM_HOME="/home/agx229/.local/share/pnpm" case ":$PATH:" in *":$PNPM_HOME:"*) ;; *) export PATH="$PNPM_HOME:$PATH" ;; esac # pnpm end 

保存后执行:

source ~/.bashrc 

再验证:

echo $PNPM_HOME which pnpm 

5. 克隆 OpenClaw 源码

cd ~ git clone https://github.com/openclaw/openclaw.git cd openclaw 

6. 解决 Jetson 上 CMake 版本过低的问题

在 Jetson Ubuntu 20.04 上,系统自带的 CMake 往往版本较低。
而 OpenClaw 的某些依赖在编译时要求更高版本的 CMake。

我在安装过程中遇到的典型报错是:

CMake 3.19 or higher is required. You are running version 3.16.3 

因此需要手动升级 CMake。

安装新版 CMake

cd ~ wget https://github.com/Kitware/CMake/releases/download/v3.31.6/cmake-3.31.6-linux-aarch64.sh chmod +x cmake-3.31.6-linux-aarch64.sh sudo ./cmake-3.31.6-linux-aarch64.sh --skip-license --prefix=/usr/local 

检查版本:

/usr/local/bin/cmake --version 

如果系统仍然找不到新版本,可临时加入 PATH:

export PATH=/usr/local/bin:$PATH hash -r cmake --version 

必要时可以加入 ~/.bashrc


7. 安装依赖并编译 OpenClaw

在项目目录执行:

cd ~/openclaw pnpm install pnpm build 

如果安装过程中出现原生模块编译问题,优先检查:

  • CMake 版本
  • build-essential 是否安装
  • pnpm 是否在 PATH 中

8. 配置模型 API

OpenClaw 通过 ~/.openclaw/openclaw.json 进行配置。

如果目录不存在,先创建:

mkdir -p ~/.openclaw nano ~/.openclaw/openclaw.json 

我使用阿里的Coding Plan,个人体验觉得挺不错的,速度快,模型也多,非广告!这部分配置教程可以参考阿里官方的教程
大模型服务平台百炼控制台


9. 配置 Gateway Token

这是本文里一个非常关键的坑。

OpenClaw 的架构不是“CLI 直接调用模型”,而是:

CLI / TUI / Logs ↓ Gateway ↓ Agent ↓ Model 

所以 CLI 其实是 Gateway 的客户端
既然是客户端连接服务端,就涉及认证。

为什么要加 token

如果只配置服务端 token,而没有配置客户端 token,就会出现:

unauthorized: gateway token mismatch 

因此需要让 gateway 服务端客户端连接配置 使用同一个 token。

通过 ~/.openclaw/openclaw.json 进行知道如下,推荐配置如下:

{ "gateway": { "mode": "local", "auth": { "mode": "token", "token": "Yours Token" }, "remote": { "token": "Yours Token" } } } 

解释

  • gateway.auth.token:Gateway 服务端认证 token
  • gateway.remote.token:CLI / TUI / logs 等客户端连接 Gateway 时使用的 token

这两个必须一致。


10. 启动 Gateway 服务

先安装 gateway service:

openclaw gateway install 

然后启动:

systemctl --user start openclaw-gateway.service 

检查状态:

openclaw gateway status 

正常情况下会看到类似输出:

Runtime: running RPC probe: ok Listening: 127.0.0.1:18789 

如果配置修改过,需要重启:

systemctl --user restart openclaw-gateway.service 

12. 验证 TUI 是否可用

如果配置正确,可以直接运行:

openclaw tui 

若成功,界面会显示已连接,并能直接与模型对话。

如果出现 token mismatch,基本就是 auth.tokenremote.token 不一致。


13. 配置飞书机器人

第一步:创建飞书应用

进入飞书开放平台https://open.feishu.cn/?lang=zh-CN,创建一个企业自建应用。

第二步:启用机器人能力

在应用后台启用机器人。

第二步:配置权限

在左侧目录树选择“开发配置 > 权限管理”,单击“批量导入/导出权限”按钮。

加入如下内容:

{ "scopes": { "tenant": [ "contact:contact.base:readonly", "docx:document:readonly", "im:chat:read", "im:chat:update", "im:message.group_at_msg:readonly", "im:message.p2p_msg:readonly", "im:message.pins:read", "im:message.pins:write_only", "im:message.reactions:read", "im:message.reactions:write_only", "im:message:readonly", "im:message:recall", "im:message:send_as_bot", "im:message:send_multi_users", "im:message:send_sys_msg", "im:message:update", "im:resource", "application:application:self_manage", "cardkit:card:write", "cardkit:card:read" ], "user": [ "contact:user.employee_id:readonly", "offline_access","base:app:copy", "base:field:create", "base:field:delete", "base:field:read", "base:field:update", "base:record:create", "base:record:delete", "base:record:retrieve", "base:record:update", "base:table:create", "base:table:delete", "base:table:read", "base:table:update", "base:view:read", "base:view:write_only", "base:app:create", "base:app:update", "base:app:read", "board:whiteboard:node:create", "board:whiteboard:node:read", "calendar:calendar:read", "calendar:calendar.event:create", "calendar:calendar.event:delete", "calendar:calendar.event:read", "calendar:calendar.event:reply", "calendar:calendar.event:update", "calendar:calendar.free_busy:read", "contact:contact.base:readonly", "contact:user.base:readonly", "contact:user:search", "docs:document.comment:create", "docs:document.comment:read", "docs:document.comment:update", "docs:document.media:download", "docs:document:copy", "docx:document:create", "docx:document:readonly", "docx:document:write_only", "drive:drive.metadata:readonly", "drive:file:download", "drive:file:upload", "im:chat.members:read", "im:chat:read", "im:message", "im:message.group_msg:get_as_user", "im:message.p2p_msg:get_as_user", "im:message.send_as_user", "im:message:readonly", "search:docs:read", "search:message", "space:document:delete", "space:document:move", "space:document:retrieve", "task:comment:read", "task:comment:write", "task:task:read", "task:task:write", "task:task:writeonly", "task:tasklist:read", "task:tasklist:write", "wiki:node:copy", "wiki:node:create", "wiki:node:move", "wiki:node:read", "wiki:node:retrieve", "wiki:space:read", "wiki:space:retrieve", "wiki:space:write_only" ] } }

在弹窗中确认权限无误后,单击“申请开通”按钮,完成操作。

第三步:发布应用

到此就可以回来Jetson去连接我们的飞书机器人了

第四步:配置 Feishu Channel

运行:

openclaw channels add 

选择:

Feishu / Lark 

然后输入:

  • App ID
  • App Secret

具体过程可以选项可以参考我的

到此就基本完成了openclaw与飞书机器人的连接了,但是要实现聊天还得再继续配置。

第五步:重启Gateway

openclaw gateway restart

第六步:配置事件与回调

选择:

使用长连接接收事件 

然后添加事件:

im.message.receive_v1 

这是机器人接收消息所必需的事件。

继续配置回调

添加回调

第七步:发布应用版本

这一步非常关键。(这里参考第三步)

很多时候飞书应用配置改了但机器人无效,就是因为没有发布版本

进入:

版本管理与发布 

创建版本并发布。

第八步:配置私聊飞书机器人

在飞书APP中找到开发者小助手

之后给机器人发送任何信息

将Pairing code复制然后在Jetson终端输入

openclaw pairing approve feishu NHMC7CRG

到此,基本就实现了在飞书中直接召唤我们边缘设备干活了,回到飞书,与我们小助手聊天即可。


14. 常见坑总结

坑 1:Jetson 上 CMake 版本过低

会导致依赖编译失败。

坑 2:没有配置 pnpm PATH

会导致全局命令或 UI 构建异常。

坑 3:误以为需要单独安装 Feishu 插件

源码版已经内置,不需要重复安装。

坑 4:没有配置 gateway.remote.token

会导致 CLI 连接 Gateway 时出现 token mismatch。

坑 5:App ID / App Secret 使用了旧应用凭证

这是我这次飞书始终接不通的根因。

坑 6:飞书应用修改后未发布版本

会导致机器人看似配置好了,但实际不生效。


15. 最终效果

完成上述配置后,可以实现:

  • 在 Jetson 上运行 OpenClaw Gateway
  • 接入自己的模型 API
  • 在飞书群中 @机器人
  • 机器人调用本地 Agent 并返回回复

这为后续扩展提供了很好的基础,例如:

  • 远程查询 Jetson 状态
  • 执行自动化任务
  • 调用机器人系统接口
  • 通过飞书统一管理实验设备

16. 总结

这次在 Jetson 上部署 OpenClaw 并接入飞书机器人的过程,整体并不算复杂,但有几个坑非常容易卡住:

  • ARM 平台的依赖编译问题
  • pnpm 环境变量问题
  • Gateway token 机制

只要把这些关键点处理好,OpenClaw + 飞书这套链路其实是很顺的。

如果你也想在 Jetson 上搭一个可远程交互的本地 Agent,这套方案很值得尝试。


预告一下,下一期我将更新一下好用的Skills,让我们边缘设备更好的给我们干活!

Read more

彻底弄懂Web Storage与Cookie:从机制到应用的全方位对比

彻底弄懂Web Storage与Cookie:从机制到应用的全方位对比

彻底弄懂Web Storage与Cookie:从机制到应用的全方位对比 * 引言 * 1. 什么是Cookie? * Cookie 的核心特性: * Cookie 流程图 * 2. 什么是Web Storage? * Web Storage 流程图 * 3. 核心区别深度解析(对标选项逐一解读) * a. 存储容量 * b. 网络流量(带宽浪费) * c. 作用域与跨域 * d. API 易用性 * e. 设计初衷 * f. 历史兼容与封装 * 4. 总结对比表 * 5. 应用场景建议 * 什么时候选 Cookie? * 什么时候选 Web Storage? * 6. 结语 🌺The Begin🌺点点关注,收藏不迷路🌺 引言 在前端开发中,

用 Web 技术构建跨平台应用:Capacitor 完全指南

开篇的碎碎念:自从发现了capacitor,我就一直在用!不用像 Flutter 那样配置一堆环境,也不用学习新的 UI 写法,直接用前端三件套就能打包原生 App。简直是降维打击!那么接下来就开始capacitor的学习吧!!! 目录 速成版 1. 什么是 Capacitor?         1.1 定义与背景         1.2 为什么叫 Capacitor?         1.3 发展历程         1.4 核心理念 2. Capacitor vs 其他跨平台方案         2.1 横评对比         2.2 为什么选择 Capacitor? 3. Capacitor 核心架构         3.1 架构图         3.2

Altium Designer导入DXF/DWG文件常见问题与实战解决方案

1. 导入失败:版本兼容性与文件损坏问题 我在使用Altium Designer导入DXF/DWG文件时,最常遇到的就是导入失败的情况。软件弹窗提示"由于文件版本不兼容或文件损坏而无法打开",这种情况特别让人头疼,尤其是赶项目的时候。 根本原因在于CAD和Altium Designer之间的版本鸿沟。AutoCAD每年都会推出新版本,而Altium Designer的更新节奏跟不上,这就导致了高版本的DWG文件在AD中无法识别。我实测过,AD 16.1版本最高只能兼容到AutoCAD 2013格式,再新的版本就会报错。 解决方案其实很简单:在AutoCAD中另存为低版本格式。我建议保存为2004或2007版本的DXF文件,这两个版本在兼容性方面表现最稳定。具体操作:在AutoCAD中打开文件后,点击"另存为",在文件类型中选择"AutoCAD 2004/LT2004 DXF (*.dxf)"。这个办法我用了十年,几乎能解决90%的导入失败问题。 如果保存为低版本后仍然无法导入,可能是文件本身损坏了。这时候可以在AutoCAD中使用RECOVER命令修复文件,然后再重新保存为低版

快学快用系列:一文学会java后端WebApi开发

快学快用系列:一文学会java后端WebApi开发

文章目录 * 第一部分:Web API开发基础概念 * 1.1 什么是Web API * 1.2 RESTful API设计原则 * 第二部分:开发环境搭建 * 2.1 环境要求 * 2.2 创建Spring Boot项目 * 2.3 配置文件 * 第三部分:项目架构设计 * 3.1 分层架构 * 3.2 包结构设计 * 第四部分:数据模型设计 * 4.1 实体类设计 * 4.2 DTO设计 * 第五部分:数据访问层实现 * 5.1 Repository接口 * 5.2 自定义Repository实现 * 第六部分:业务逻辑层实现