Nodes 架构:物理设备接入原理(macOS / iOS / Android / 树莓派)
第36章:Nodes 架构:物理设备接入原理(macOS / iOS / Android / 树莓派)
概述
OpenClaw 的 Node 体系是整个系统中最具独特性的设计之一。它将真实的物理设备——无论是你桌面的 Mac、口袋里的 iPhone、Android 手机,还是角落里静默运行的树莓派——全部纳入 Agent 的感知和执行范围。本章从架构原理出发,系统讲解 Node 的设计意图、连接机制、能力声明系统和各平台能力矩阵,帮助你真正理解"让 AI Agent 具备肉身"意味着什么。
36.1 Node 的设计定位:为什么需要物理设备节点
在纯云端 AI Agent 的架构中,Agent 的感知边界止步于 API——它可以调用搜索、读取文件、执行代码,但对物理世界无能为力。它不知道你的房间温度,无法拍下当前的画面,也无法在你的手机上发送一条短信。
OpenClaw 的 Node 架构解决了这个边界问题。其核心思想是:
物理设备本身就是 Agent 的感知器官和执行肢体。
Node 不是一个独立的 AI——它是一个能力提供者(Capability Provider)。它连接到 Gateway 后,声明自己能做什么,然后等待 Agent 的调用。当 Agent 需要"拍一张照片"时,它通过 Gateway 将工具调用路由到持有 camera.* 能力的 iOS Node;当 Agent 需要"在服务器上运行一条 Shell 命令"时,它路由到拥有 system.run 能力的 Headless Node。
这种设计带来三个核心优势:
- 能力可组合:不同设备的能力可以在同一个 Agent 会话中叠加使用。
- 安全边界清晰:每个 Node 仅声明并暴露其明确支持的能力,不存在隐式的超权限访问。
- 架构水平扩展:增加一个新设备节点不需要修改 Gateway 或 Agent 核心,只需完成配对流程即可。
36.2 WebSocket 连接机制:role:"node"
Node 通过 WebSocket 协议连接到 Gateway,连接时携带特殊的 role 字段标识自身身份。
连接握手流程
Node 发起 WebSocket 连接
→ URL: ws://<gateway-host>:18789/ws
→ 握手消息携带:
{
"role": "node",
"nodeId": "<唯一标识符>",
"displayName": "Hexin's iPhone 15 Pro",
"platform": "ios",
"capabilities": [ ... ]
}
Gateway 响应:
→ 验证 nodeId 是否已授权
→ 返回 { "status": "approved" } 或 { "status": "pending" }
→ 若 pending,Node 进入等待状态,直到管理员执行 approve
连接状态机
[未配对] ──approve──→ [已配对/在线]
↑ ↓
└──────断线超时───── [离线/待重连]
Node 与 Gateway 之间维持心跳(默认 30 秒间隔),Gateway 在检测到 Node 断线时,会将其状态标记为 offline,此时路由到该 Node 的工具调用将返回错误或触发 fallback 逻辑。
节点 ID 生成规则
每个 Node 在首次连接时生成一个持久化的 UUID 作为 nodeId,该 ID 存储在设备本地(iOS Keychain / Android Keystore / macOS Keychain),重启后保持不变。这确保了 Gateway 可以识别"同一设备重新上线"而不是"一个全新的陌生设备"。
36.3 Capability 声明系统
Capability 声明系统是 Node 架构的核心机制。它解决了一个基本问题:Gateway 如何知道某个 Node 能做什么?
声明格式
每个 Capability 由命名空间和操作组成,采用 namespace.action 格式:
{
"capabilities": [
"camera.snap",
"camera.record",
"camera.screenshot",
"location.get",
"screen.record"
]
}
声明的完整生命周期
1. Node 建立 WebSocket 连接
2. Node 发送 capabilities 列表(静态声明)
3. Gateway 将声明写入内存注册表
4. Agent 发起工具调用,指定所需 capability
5. Gateway 查询注册表,找到持有该 capability 的在线 Node
6. Gateway 将工具调用路由到目标 Node
7. Node 执行并返回结果
8. Node 断线时,Gateway 从注册表中移除其所有 capability 条目
能力路由的选择策略
当多个 Node 声明了相同的 capability 时(例如两部 iPhone 都连接了),Gateway 按以下策略选择:
- 指定 nodeId:Agent 调用时显式指定
targetNodeId,精确路由。 - 优先级权重:Node 连接时可声明
priority字段,值越大优先级越高。 - 最近活跃:默认策略,选择最近有通信活动的 Node。
- Round-Robin:在配置中启用
routing: "round-robin"时使用。
动态能力更新
Node 在运行时可以通过发送 capability_update 消息来动态修改其声明的能力列表。常见场景:摄像头权限被用户在系统设置中撤销后,iOS Node 主动移除 camera.* 相关能力。
{
"type": "capability_update",
"add": [],
"remove": ["camera.snap", "camera.record"]
}
36.4 设备配对完整流程
步骤一:Node 发起连接请求
在目标设备上安装并启动 OpenClaw Node 客户端(iOS/Android App 或 macOS 菜单栏应用)。Node 会自动尝试连接到配置的 Gateway 地址,首次连接进入 pending 状态。
步骤二:列出待审批设备
在 Gateway 主机上执行:
openclaw devices list
输出示例:
ID DISPLAY NAME PLATFORM STATUS REQUESTED
req-a1b2 Hexin's iPhone 15 Pro ios pending 2026-04-26 09:15:33
req-c3d4 Raspberry Pi 4B headless pending 2026-04-26 09:16:01
req-e5f6 Hexin's MacBook Pro macos pending 2026-04-26 09:16:45
步骤三:审批设备
openclaw devices approve req-a1b2
输出:
✓ Device approved: Hexin's iPhone 15 Pro (req-a1b2)
Node ID assigned: node-7f8a9b0c
Capabilities registered: 5
可以批量审批:
openclaw devices approve req-a1b2 req-c3d4 req-e5f6
步骤四:验证节点状态
openclaw nodes status
输出示例:
NODE ID DISPLAY NAME PLATFORM STATUS CAPABILITIES LAST SEEN
node-7f8a9b0c Hexin's iPhone 15 Pro ios online 5 just now
node-2d3e4f50 Raspberry Pi 4B headless online 2 just now
node-9a8b7c6d Hexin's MacBook Pro macos online 6 just now
步骤五(可选):检查特定节点能力
openclaw nodes status --node node-7f8a9b0c --verbose
Node: Hexin's iPhone 15 Pro (node-7f8a9b0c)
Platform: ios | Status: online | Uptime: 2m 34s
Capabilities:
✓ camera.snap 拍摄静态照片
✓ camera.record 录制视频(≤60s mp4)
✓ camera.screenshot 截取屏幕截图
✓ location.get 获取 GPS 位置
✓ screen.record 屏幕录制(≤60s)
36.5 各平台能力矩阵详解
macOS Node 能力
| 能力标识 | 说明 |
|---|---|
system.run |
在 macOS 上执行 Shell 命令 |
system.which |
查找可执行文件路径 |
system.notify |
发送系统通知(Notification Center) |
execApprovals |
命令执行审批(需 Human 确认) |
canvas.* |
控制 OpenClaw Canvas 画布 UI |
macOS Node 是"本地自动化"的核心。system.run 赋予 Agent 在你的 Mac 上执行任意 Shell 命令的能力(受 execApprovals 机制约束),canvas.* 则允许 Agent 以视觉化方式在画布上渲染内容。
iOS Node 能力
| 能力标识 | 说明 |
|---|---|
canvas.* |
Canvas UI 控制 |
camera.snap |
拍摄静态照片 |
camera.record |
录制视频(最长 60 秒,mp4 格式) |
camera.screenshot |
截取当前屏幕截图 |
screen.record |
屏幕录制(最长 60 秒) |
location.get |
获取当前 GPS 坐标 |
iOS 平台的沙盒机制使得 system.run 无法实现,但摄像头和位置能力使 iOS Node 成为最佳的"现场感知设备"。
Android Node 能力
Android Node 继承了 iOS 的全部能力,并额外提供:
| 能力标识 | 说明 |
|---|---|
device.status |
获取设备状态(电量/信号/存储) |
device.info |
获取设备硬件信息 |
device.permissions |
查询运行时权限状态 |
device.health |
设备健康度报告 |
notifications.list |
列出当前通知栏通知 |
notifications.actions |
对通知执行操作(已读/删除) |
photos.latest |
获取最新照片 |
contacts.search |
搜索联系人 |
contacts.add |
添加联系人 |
calendar.events |
读取日历事件 |
calendar.add |
创建日历事件 |
callLog.search |
搜索通话记录 |
sms.send |
发送短信 |
sms.search |
搜索短信记录 |
motion.activity |
获取运动状态(步行/骑行/驾车) |
motion.pedometer |
获取计步数据 |
Android 的开放性使其成为能力最丰富的 Node 平台。
Headless Node 能力(树莓派 / 服务器)
| 能力标识 | 说明 |
|---|---|
system.run |
远程 Shell 命令执行 |
system.which |
查找可执行文件 |
Headless Node 的强大不在于能力数量,而在于 system.run 的无限延伸性——通过 Shell,它可以间接控制 GPIO、读取传感器、触发脚本,将任何可编程的硬件行为纳入 Agent 的执行范围。
36.6 Android 特有能力的应用场景
Android 的额外能力开辟了一系列在传统 AI Agent 中难以实现的场景:
场景一:智能助理日程整合
用户: "把下周三的牙医预约加到日历,顺便给诊所发条确认短信"
Agent:
1. calendar.add → 创建日历事件 "牙医预约 周三 14:00"
2. contacts.search → 搜索 "牙医诊所" 获取电话号码
3. sms.send → 发送 "您好,确认下周三14:00的预约,谢谢"
场景二:健康数据追踪
用户: "今天走了多少步?和本周平均值对比"
Agent:
1. motion.pedometer → 获取今日步数: 8,432
2. motion.pedometer (批量) → 获取本周每日步数
3. 计算均值并生成对比报告
场景三:设备健康监控
定时任务 (每6小时):
1. device.health → 获取健康报告
2. device.status → 检查电量/存储
3. 若存储 < 10% → 通知用户清理
4. 若电量 < 20% → 发送提醒
场景四:通知智能过滤
用户: "帮我整理今天所有的银行通知"
Agent:
1. notifications.list → 获取所有通知
2. 过滤出发件方为银行 App 的条目
3. 提取金额/时间/类型信息
4. 汇总成结构化报告
36.7 Node 与 Agent 的交互模式
直接工具调用模式
这是最常见的模式。Agent 在推理过程中决定需要某项能力,直接通过 Tool Use 机制调用:
{
"tool": "node_invoke",
"parameters": {
"capability": "camera.snap",
"nodeId": "node-7f8a9b0c",
"options": {
"quality": "high",
"flash": "auto"
}
}
}
流式结果传输模式
对于 camera.record 和 screen.record 等产生大文件的能力,Node 采用分块流式传输:
Node → Gateway → Agent:
chunk_1: { "type": "media_chunk", "index": 0, "data": "<base64>" }
chunk_2: { "type": "media_chunk", "index": 1, "data": "<base64>" }
...
final: { "type": "media_complete", "totalSize": 2048576, "format": "mp4" }
事件推送模式(Node → Agent)
Node 可以主动向 Agent 推送事件,无需 Agent 轮询:
{
"type": "node_event",
"source": "node-7f8a9b0c",
"event": "location_update",
"data": {
"lat": 31.2304,
"lng": 121.4737,
"accuracy": 5.0
}
}
这种模式用于 location.get 的持续追踪场景。
Sub-Agent 代理模式
在复杂任务中,主 Agent 可以将"操作 Node"的子任务委托给 Sub-Agent:
主 Agent: "拍三张不同角度的照片,合并成全景"
→ 委派 Sub-Agent-1: camera.snap (角度A)
→ 委派 Sub-Agent-2: camera.snap (角度B)
→ 委派 Sub-Agent-3: camera.snap (角度C)
→ 主 Agent 汇总结果执行合并
36.8 Node 的安全考量
配对验证机制
配对流程的每一步都有安全保障:
- 首次连接不自动信任:所有新 Node 都进入
pending状态,必须由管理员显式approve。 - nodeId 绑定:审批后,
nodeId与设备硬件绑定(通过系统 Keychain/Keystore),伪造身份需要物理访问设备。 - TLS 加密传输:所有 WebSocket 通信通过 TLS 加密(配合 Tailscale 时使用 WireGuard 加密隧道)。
能力声明最小化原则
Node 应遵循最小权限原则,只声明实际需要的能力:
// 错误示范:声明所有能力
{ "capabilities": ["camera.*", "location.*", "sms.*", "contacts.*"] }
// 正确示范:按需声明
{ "capabilities": ["camera.snap", "location.get"] }
execApprovals:命令执行的人工审批
对于 system.run 这类高危能力,OpenClaw 提供了 execApprovals 机制:
{
"execApprovals": {
"enabled": true,
"requireApproval": ["rm", "sudo", "curl", "wget", "chmod"],
"autoApprove": ["ls", "pwd", "echo", "cat"]
}
}
当 Agent 试图执行 requireApproval 列表中的命令时,执行会暂停,在 Control UI 的审批队列中出现待确认项,等待人工批准后才继续。
能力吊销
管理员可以随时吊销特定 Node 的特定能力:
# 临时禁用某 Node 的短信发送能力
openclaw nodes capability revoke node-xxxx sms.send
# 完全断开某 Node
openclaw nodes disconnect node-xxxx
36.9 小结
Node 架构是 OpenClaw 从"纯软件 Agent"向"物理世界感知 Agent"进化的关键设计。通过 WebSocket role:"node" 连接机制、结构化的 Capability 声明系统和严格的配对审批流程,OpenClaw 在保持安全边界清晰的同时,将物理设备的感知和执行能力无缝融入 Agent 的工具调用体系。
下一章将进入实战:如何将树莓派配置为一个 24/7 持续在线的 Always-On Agent Node。
下一章:第37章 — 边缘计算实战:树莓派 24/7 Always-On Agent Node 完整搭建