返回博客

OpenClaw 源码解读(8):系统底层控制

2026年3月18日

OpenClaw 是如何成为了一个能看、能听、还能帮你敲键盘的实体管家。


在上一篇文章中,我们聊了 OpenClaw 是如何通过跨平台语音唤醒,长出“耳朵”和“嘴巴”的。但这距离一个真正的“全能 AI 管家”还有一段距离。

试想这样一个场景:你正在外面喝咖啡,突然想起来家里电脑上有一个重要进程不知道跑完没有。你对手机里的 Agent 说:“帮我看看家里 Mac 的屏幕,如果跑完了就帮我关机。”

要实现这个场景,Agent 必须拥有突破纯软件沙箱、直接调用底层硬件和系统命令的能力。这就是 OpenClaw 中非常硬核的 Device Nodes(设备节点)架构。今天,老金就带大家深入源码,看看这条从云端大脑直达你电脑底层的“神经通路”是怎么打通的。

Node 协议:设备如何成为 Agent 的“手脚”?

在 OpenClaw 的世界观里,你的 MacBook、iPhone 甚至是一台吃灰的安卓备用机,都可以运行一个“伴随应用(Companion App)”。当这些应用启动时,它们会作为 Node(节点)加入到 Gateway 的网络中。

这里面最核心的是设备配对与长连接机制。为了保证安全,不是随便哪个设备连上网关就能执行命令的。

// src/core/nodes/NodeManager.ts (源码概念简化版)

export class NodeManager {
  /**
   * 处理 Node 节点的 WebSocket 接入请求
   */
  public async handleNodeConnection(socket: WebSocket, req: IncomingMessage) {
    // 1. 提取握手头部的设备 Token 和公钥
    const deviceToken = req.headers['x-node-token'];
    const deviceId = req.headers['x-device-id'];

    // 2. 验证配对状态 (DM Pair 机制)
    const isPaired = await PairingService.verifyDevice(deviceId, deviceToken);
    if (!isPaired) {
      socket.close(4001, 'Unauthorized Device Node');
      return;
    }

    // 3. 注册 Node 会话,维持心跳
    const nodeSession = new NodeSession(deviceId, socket);
    this.activeNodes.set(deviceId, nodeSession);
    
    // 4. 监听来自 Node 的硬件状态上报 (电量、位置等)
    nodeSession.on('status_update', (status) => this.updateNodeStatus(deviceId, status));
  }
}

一旦设备配对成功并建立了 WebSocket 连接,这台设备就正式成为了 Agent 可以调用的一个物理终端。

宿主调用链:node.invoke 命令执行全流程

当 Agent 决定要控制你的设备时(比如获取摄像头画面),它不会直接写底层代码,而是通过调用内置的工具触发一个极其重要的核心协议:node.invoke。

这是一个类似于 RPC(远程过程调用)的机制。我们来看看一条指令是如何跨越云端落地的。

// src/core/tools/nodes/NodeInvokeTool.ts (源码概念简化版)

export class NodeInvokeTool extends Tool {
  name = 'node_invoke';
  description = '向指定的物理设备节点发送底层系统指令。';

  async execute(params: { targetNodeId: string, command: string, args: any }, context: ToolContext) {
    const node = NodeManager.getNode(params.targetNodeId);
    
    // 向目标设备下发指令
    const response = await node.sendAndWait({
      action: 'invoke',
      payload: {
        command: params.command, // 例如:'screen.capture', 'system.run'
        args: params.args
      }
    });

    return response.result;
  }
}

Agent 发出指令后,Gateway 只是个传话筒,真正执行脏活累活的,是运行在你设备上的原生伴随应用。

打破沙箱:硬件能力与 macOS TCC 权限体系

做过苹果生态开发的朋友肯定知道,macOS 和 iOS 对用户隐私的保护到了极其严苛的程度。你要调用摄像头、麦克风、录制屏幕,甚至获取当前定位,都必须面对大名鼎鼎的 TCC (Transparency, Consent, and Control) 权限控制子系统。

OpenClaw 的 Mac 端节点(使用 Swift 开发)是如何优雅地接住 node.invoke 并打通 TCC 权限的呢?我们深入到 Swift 源码看一看:

// apps/apple/OpenClawNode/Commands/NodeCommandDispatcher.swift (源码概念简化版)

class NodeCommandDispatcher {
    func handleInvoke(command: String, args: [String: Any]) async throws -> Any {
        switch command {
        case "screen.capture":
            return try await performScreenCapture()
        case "system.run":
            let script = args["script"] as? String ?? ""
            return try await executeLocalScript(script)
        case "location.get":
            return try await fetchCurrentLocation()
        default:
            throw CommandError.unknownCommand
        }
    }
    
    // 以屏幕录制为例,深究 TCC 权限打通
    private func performScreenCapture() async throws -> String {
        // 1. 检查 macOS 屏幕录制权限 (TCC: NSScreenCapture)
        guard CGPreflightScreenCaptureAccess() else {
            // 如果没权限,主动触发系统设置弹窗,并向 Gateway 返回需要授权的状态
            CGRequestScreenCaptureAccess()
            throw CommandError.permissionDenied(reason: "Please allow Screen Recording in System Settings.")
        }
        
        // 2. 权限校验通过,调用原生 API 截取屏幕
        let screenshot = NativeScreenRecorder.takeSnapshot()
        
        // 3. 转为 Base64 返回给 Gateway
        return screenshot.toBase64()
    }
}

高危操作:system.run 的边界

在众多 node.invoke 命令中,最强大也最危险的莫过于 system.run。它允许 Agent 直接在你的宿主机上执行 Bash 脚本(比如 ls -la、git pull 或者是更复杂的环境配置)。

为了防止误操作或被恶意注入,OpenClaw 在端侧做了严格的限制:

  • 沙箱逃逸确认: 即使是主人的 Agent 发出的 system.run,如果是极具破坏性的命令(如 rm -rf),端侧应用会弹出一个原生的确认框,必须主人点击“允许”才能放行。

  • 环境变量隔离: Agent 执行的脚本运行在一个受限的环境变量子进程中,无法直接窃取用户的系统级 Keychain 或敏感凭证。

总结

OpenClaw 的 Device Nodes 架构,本质上是在云端的 AI 大脑和本地的物理硬件之间,架设了一道安全的桥梁。

  • WebSocket 与 DM Pair 确保了桥梁的私密性。

  • node.invoke 协议 标准化了跨端调用的数据结构。

  • 原生端的精细化权限管理(如苹果的 TCC 打通) 则守住了系统安全的最后一道防线。

有了这些,你的 AI 助手就不再是飘在云端的一串代码,而是真正落地到了你的电脑和手机里,成为了一个能看、能听、还能帮你敲键盘的实体管家。

到这里,OpenClaw 的核心功能实现我们已经基本摸透了。但作为一个要在生产环境中长期运行的项目,如何部署它?

下一篇,我们将进入本系列的最后一个阶段:安全、部署与运维篇。敬请期待,我们下期见!