OpenClaw架构(1)- Device架构

把能力抽象成 device,就是把“函数式能力”升级为“系统级资源”,实现标准化接口、沙盒隔离、可调度、可组合、可安全共享的执行单元。


  1. 能力即资源(Capability-as-a-Resource)

    • 不再把能力当作一次性函数调用,而是可挂载、可调度、可复用的系统资源
    • Device 可以长期存在,有状态,可被多个 agent 调用。
  2. 统一接口 / 标准化 I/O

    • 每个 device 提供统一的输入、输出、状态和生命周期接口。
    • Agent 不关心内部实现,只通过接口交互。
  3. 独立沙盒隔离

    • 每个 device 在受控环境中运行,资源受限,权限明确,避免越权或影响系统其他部分。
    • 支持容器、进程隔离、语言沙盒等技术。
  4. 可替换性与可组合性

    • 不同实现的 device 可以互换(如 ModelDevice 用不同模型)。
    • Device 可串联、并行、广播,支持复杂流程编排。
  5. 资源调度与安全管理

    • Device 是系统资源,可做调度、监控、限流。
    • 权限控制、能力注册表、防止滥用,增强系统稳定性与安全性。
  6. 适用于多 Agent 协作

    • 在多 agent 系统里,device 是共享能力单元,支持点对点、广播和长生命周期任务。
    • 流式数据、事件驱动和 human loop 都能天然支持。

Device架构跟传统Agent架构区别

维度 传统 Agent OpenClaw Device 架构
① 分布式 / 安全 单进程,无设备身份 多节点、设备身份、配对、Token
② 能力模型 工具在代码里写死 能力由设备声明,运行时发现
③ 谁在执行 隐含:「当前进程」 显式:每次调用都绑定到某个 nodeId/device
④ 拓扑与生命周期 一个 Agent 实例 = 一个执行环境 一个 Agent = 协调多台设备;设备可离线/重连

2. 能力模型:声明式 vs 写死

传统:工具集是静态的,在代码里写死。
工具集在写代码时就定了tools = [run_shell, read_file, search_web]agent = create_agent(llm, tools)
Device 架构:工具集是当前在线设备能做什么的并集,是运行时发现的。
设备连上 Gateway 时上报 caps、commands
Gateway 不关心这些能力在设备上怎么实现(可以是本地函数、脚本、硬件)
Agent(LLM)看到的是「当前有哪些 node、各自能执行哪些 command」,再决定调用谁
所以差异不仅是「执行在远端」,而是:能力不是事先在中心写死的,而是由边缘设备声明、中心做发现与路由。这是能力模型的差异,不是「只是把调用从本地改成 RPC」。

3 . 执行主体是显式的(可问责、可路由)

传统:执行工具 = 在当前进程里调函数,「谁执行的」是隐含的(就是当前进程)。
Device 架构:每次调用都带目标节点,例如 node.invoke(nodeId, command, params)。
带来的不同:
路由选择:同一类能力可能有多台设备(例如多台相机),可以由策略或 LLM 选「在哪个 device 上执行」
问责:日志里可以明确是 deviceId=xxx 执行了某条命令
策略:可以按设备做权限/审计(例如只允许某几台设备执行 system.run)
所以差异不仅是「更安全」,而是执行主体从隐含变成显式的一等公民,从而支持多设备、策略和审计。

4. 拓扑与生命周期:一个 Agent,多台设备

传统:通常是「一个 Agent 进程 + 一套固定工具」,Agent 和执行环境是 1:1 或 1:1 个进程。
Device 架构:
一个 Gateway(一个逻辑上的「助手」)面对多台设备
设备可以随时上线/下线;同一台设备断线再连,用同一个 deviceId 识别
所以是「一个协调者 + 多台可进可出的执行端」的拓扑
因此差异不仅是「支持分布式部署」,而是系统建模的是「多设备」而不是「单进程」:设计重心是「设备」的注册、发现、路由、离线/重连,而不是「给这个进程加几个远程 RPC」。

通讯链路

概念

Node 是什么

Node = 一次已注册的、带能力的连接(session)
某个客户端(node-host、macOS 应用、iOS 应用等)通过 WebSocket 连上 Gateway,发 connect,带上:
身份:client(及可选的 device)
能力:caps、commands
Gateway 的 NodeRegistry 把这条连接记成一条 NodeSession,并给它一个 nodeId。
之后别人要在这台「机器/应用」上执行东西,就对 nodeId 发 node.invoke(nodeId, command, params)。
所以:
nodeId:这个「连接/端点」在 Gateway 里的唯一标识(通常就是带设备认证时的 device.id)。
node:拥有这个 nodeId 的、当前在线的这条连接;它上面挂着 caps、commands,能收 node.invoke.request 并执行对应命令。
一句话:node = 当前连在 Gateway 上的、带 nodeId 和一组 caps/commands 的能力端点。

  • Device:指有 Device 身份 的那一端(Ed25519、deviceId、配对),通常是某台物理机或应用(如跑 node-host 的树莓派、Mac 应用、iOS 应用)。它们连上 Gateway,注册为 Node,才能收 node.invoke.request
  • 大模型:是 Agent 里调用的 推理服务(如 Claude API、OpenAI API),没有连到 Gateway、没有 deviceId、也不收 node.invoke。它只是「在 Gateway 侧跑的一轮轮 LLM 调用」。

所以:大模型 = Agent 的推理引擎,不是 Device,也不是 Node。

  • Node Feishu:没有这种说法;Feishu 是 channel,不是 Node。
  • 大模型:是 Agent 的脑子,不是 Device;Device 指的是「能配对、能收 node.invoke 的那一端设备」。

所以:caps = 能力分类;commands = 该节点支持的具体 node.invoke 命令列表。

cap 含义(典型用法)
system 能跑系统命令等
browser 能做浏览器代理/自动化
camera 能拍照/录像
canvas 能展示/控制 Canvas
用户消息:"用 weather 查北京天气,然后把结果发到树莓派上显示"
                    │
                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│  Gateway:收消息 → 路由到会话 → 触发 Agent 运行                            │
└─────────────────────────────────────────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│  Agent (LLM)                                                             │
│  - 看到 system prompt 里的 Skills 列表(含 weather: "查询天气")           │
│  - 看到 Tools 列表(含 nodes, exec, message...)                         │
│  - 决定:先调 weather,再调 nodes 把结果发到树莓派                         │
└─────────────────────────────────────────────────────────────────────────┘
                    │
        ┌───────────┴───────────┐
        │                       │
        ▼                       ▼
  ① 用 Skill 查天气          ② 用 Node 显示结果
  ─────────────────          ─────────────────

┌─────────────────────┐    ┌─────────────────────┐
│  Skill:weather      │    │  内置工具:nodes     │
│                      │    │                     │
│  - 来自 workspace    │    │  - 来自 openclaw    │
│    里安装的 skill    │    │    内置 tools       │
│  - 执行方式:        │    │  - 执行方式:       │
│    跑 skill 的脚本/  │    │    callGatewayTool  │
│    或调 skill 的     │    │    ("node.invoke",  │
│    接口             │    │     { nodeId: 树莓派,│
│  - 不经过 Gateway   │    │       command:       │
│    node.invoke      │    │       "system.run"  │
│  - 返回:            │    │       或 "system.   │
│    "北京 晴 25°C"   │    │       notify", ...}) │
└──────────┬──────────┘    └──────────┬──────────┘
           │                          │
           │ 结果字符串                │ 需要 node 执行
           │                          ▼
           │                 ┌─────────────────────┐
           │                 │  Gateway             │
           │                 │  node.invoke         │
           │                 │  → 树莓派 node-host  │
           │                 │  → 执行 notify 或   │
           │                 │    run echo "北京…"  │
           │                 └─────────────────────┘
           │
           └──────────────┬─────────────────────────┘
                          │
                          ▼
               Agent 收到两次 tool 结果,组织成最终回复
                          │
                          ▼
               Gateway 把回复发回用户(如 Telegram)

Agent之间的通讯协议

「经过 Gateway 转发,agent 之间就不会直接通讯了,是不是就不用 A2A 协议了呢?」
若 A2A 指「谁连谁」:对,经 Gateway 转发本来就不是直连,所以不需要用 A2A 来做连接,可以不用。
若 A2A 指「消息内容/协议格式」:不是。经 Gateway 转发时,负载内容仍然可以、也建议用 A2A,这样 Agent–Agent 的语义是标准化的,和「经不经过 Gateway」无关。
所以:拓扑上不用 A2A(不直连);内容上可以继续用 A2A(消息格式)。 只有在你完全不需要和外界/标准互通时,才可以连「消息格式」也不用 A2A。

posted @ 2026-02-19 21:46  向着朝阳  阅读(231)  评论(0)    收藏  举报