云端 OpenClaw 远程执行本地进程原理机制详解:Gateway、approvals 与 system.run 到底谁在判定、谁在执行?

云端 OpenClaw 远程执行本地进程原理机制详解:Gateway、approvals 与 system.run 到底谁在判定、谁在执行?

前言

在使用 OpenClaw 搭建"云端 Gateway + 本地 Windows 节点"的远程执行体系时,最容易混淆的一件事,不是命令本身怎么写,而是命令到底是谁决定能不能执行,谁又真正负责把它跑起来

很多人在刚接触这套架构时,脑子里往往会把几个概念混在一起:

  • 以为云端 Gateway 已经设置成 tools.exec.host=node,那命令就一定能直接在本地执行;
  • 以为 system.run 既是执行器,也是审批器;
  • 以为白名单只要在云端配一次,就对所有节点通用;
  • 以为 node.list 能看到节点,就说明 nodes run 一定能成功;
  • 以为 SSH 隧道通了,就代表整条远程执行链路已经完全打通。

实际上,这些理解都只看到了局部,没有把 OpenClaw 的控制面、执行面、安全联锁、协议分层放在一个统一的框架里看。

这篇文章就围绕一个核心问题展开:

OpenClaw 的远程命令执行,到底是如何从"云端发起请求"一步步走到"本地机器真正启动进程"的?

如果要用一句最直白的话概括整套机制,那就是:

Gateway 负责调度和下令,node 负责暴露本机能力,本地 approvals 负责决定这台机器最后是否同意执行,而 system.run 负责真正把命令跑起来。

这四者不是一个东西,也不是同一层逻辑。只有把它们彻底拆开,很多现象才能解释得通。


一、先把最容易混淆的三层拆开

在 OpenClaw 的远程执行体系里,最值得先建立的不是某个具体命令,而是"分层思维"。

从原理上看,至少要把下面三层分开理解:

  1. 云端 Gateway 的默认执行策略层
  2. 本地执行主机上的 approvals / allowlist 层
  3. 真正落到主机上执行的 system.run 层

很多问题之所以越排越乱,根本原因就在于把这三层混成了一层,以为"能连上节点 = 节点一定能执行 = system.run 已经有权限跑命令"。

实际上并不是这样。

更准确地说,OpenClaw 的设计是一个典型的"控制平面与执行平面分离"架构:

  • 控制面在 Gateway 一侧,负责决定请求该发给谁、按什么规则发、是否要求审批;
  • 执行面在 node 一侧,负责把本机真实能力暴露给 Gateway;
  • 主机侧安全联锁又独立存在于执行主机本机上,作为最后一道安全闸门;
  • system.run 只是执行动作的最终落点,并不是前面所有策略判断的替代品。

所以,要真正读懂"再结合 approvals 去调用 system.run"这句话,首先就要知道:

system.run 不是先执行再审批,而是前面所有策略都通过之后,才有机会真正启动进程。


二、第一层:云端 Gateway 的默认执行策略到底在管什么

先看第一层,也就是最上层的Gateway 默认执行策略

在你的这套部署中,像 tools.exec.hosttools.exec.securitytools.exec.asktools.exec.node 这几个配置,实际上都属于这一层。它们定义的不是"某台主机上的本地规则",而是控制面默认想怎么发起执行请求

1.1 tools.exec.host:决定默认执行位置

这个配置决定的是:

  • 到 sandbox 执行;
  • 到 gateway 所在机器执行;
  • 还是发给某台 node 执行。

也就是说,它解决的是一个最顶层的问题:

默认把执行请求发到哪里。

它只是"调度意图",不是最终执行结果。

1.2 tools.exec.security:决定默认安全模式

这个配置不是在本地机器上直接执行白名单,而是定义 Gateway 在形成执行请求时默认遵循什么安全策略,比如:

  • deny
  • allowlist
  • full

它表达的是控制面对于执行请求的默认安全态度

1.3 tools.exec.ask:决定默认是否弹审批

这个配置决定在控制面层面,遇到执行请求时要不要交互确认。例如:

  • 始终不提示;
  • 未命中规则时提示;
  • 总是提示。

本质上它解决的是:

在请求进入执行面之前,控制面是否希望引入用户交互式审批。

1.4 tools.exec.node:决定默认目标节点

当执行目标是 node 时,这个配置负责指定默认发给哪一台节点。

它解决的不是权限问题,而是路由问题

1.5 这一层的本质:定义"默认执行意图"

因此,把这几个配置合起来看,就能发现一个很重要的结论:

tools.exec.* 本质上是在定义 Gateway 这一侧的默认执行意图,而不是对执行主机作最终裁决。

也就是说,即便你已经把云端 Gateway 配成"默认发到 node、默认走 allowlist、默认不 ask",它也只代表:

  • 请求会优先往 node 发;
  • 安全模型按 allowlist 预期处理;
  • 控制面默认不额外交互。

但这还远远没有走到"命令一定会在 Windows 上成功执行"那一步。


三、第二层:什么是本地 approvals,它为什么才是主机侧最后一道闸门

理解了 Gateway 的默认策略之后,接下来要看第二层:执行主机本地的 approvals

这是很多人第一次接触时最容易忽略,但实际上最关键的一层。

3.1 approvals 不是云端全局规则,而是执行主机本地规则

所谓"本地 approvals",最直接的理解就是:

真正负责执行命令的那台机器,自己本地保存的一份命令运行规则文件。

如果你的执行主机是 Windows 节点,那么这份文件通常就在 Windows 用户目录下,例如:

text 复制代码
C:\Users\你的用户名\.openclaw\exec-approvals.json

这说明一件非常重要的事:

approvals 不是放在云端 Gateway 上给所有机器通用的全局白名单,而是每一台执行主机各自持有的一份本地规则。

换句话说,谁负责真正落地执行,谁就有自己的审批文件。

3.2 approvals 管的不是"模型想不想执行",而是"这台机器愿不愿意执行"

这层的意义必须说透。

大模型、CLI、Gateway 都可以形成"执行请求",但真正承担风险的是执行主机本身。因为一旦命令落地,它影响的是那台机器上的:

  • 文件系统;
  • 用户目录;
  • 桌面环境;
  • 本地脚本;
  • 系统命令;
  • 甚至某些可访问的网络资源。

所以 approvals 的本质不是模型侧行为约束,而是资产拥有者视角下的主机安全联锁

可以把它理解成一句非常白的话:

云端可以"建议执行",但本地机器有权说"这条命令我不接"。

3.3 为什么 approvals 必须放在执行主机本地

这是 OpenClaw 这套设计最值得理解的地方之一。

如果所有审批都只放在云端,那就意味着:

  • 远端控制面一旦配置错误,可能直接影响所有执行主机;
  • 本地主机对自己资产的最后控制权会被削弱;
  • 安全边界会全部前移到远端,不符合"风险由资产拥有者最终把关"的原则。

而把 approvals 放在执行主机本地,就实现了一个非常典型、也非常合理的机制:

最后一道生死线不在控制面,而在实际承担风险的宿主机一侧。

这就是为什么说 approvals 是 node host 的 guardrail,是主机侧的 safety interlock。

3.4 approvals 里真正判定什么

这一层一般会包含类似下面这些维度:

  • security
  • ask
  • askFallback
  • allowlist
  • 按 agent 生效的规则

其中最敏感的,就是 allowlist

因为它直接决定:

哪些命令入口、哪些脚本、哪些可执行程序,允许在这台机器上被远程触发。

如果一个命令没有命中 allowlist,又没有可用的审批 UI,那它就会停在 approvals 这一层,而不是继续往下进入真正的执行层。

这也就是很多人会碰到的那种现象:

text 复制代码
approval required (approval UI not available)

这个报错的真正含义不是"system.run 坏了",而是:

命令在本地 approvals 这一关被拦住了,根本还没有机会真正落到 system.run。


四、第三层:system.run 到底是什么,它是不是"最终权限拥有者"

讲到这里,才轮到第三层,也就是很多人最先注意到、但最容易误解的 system.run

4.1 system.run 的本质:真实主机上的命令执行器

如果用一句话给它定性,那么最准确的说法是:

system.run 是执行器,不是裁判器。

它的职责非常单纯:

  • 在节点主机上启动一个真实的本地进程;
  • 把命令真正交给宿主机操作系统去运行;
  • 返回执行结果、错误信息或运行状态。

你可以把它类比成"远程桌面环境里的启动程序动作",也可以把它理解成"节点主机暴露出来的 CreateProcess 接口入口"。

它负责的是把命令跑起来,不是负责决定"这条命令是否应当被允许跑起来"。

4.2 为什么说 system.run 很敏感

因为一旦它被真正调用,落地的就不再是 OpenClaw 自己的内部逻辑,而是宿主机上的真实命令执行。

它理论上可能启动的对象包括但不限于:

  • 系统自带命令,如 where.exe
  • 用户自己编写的批处理脚本,如 paper_scan.cmd
  • PowerShell;
  • 其他被允许的本地二进制程序;
  • 依赖本地环境变量的命令入口。

这就是为什么 system.run 看似只是一个"命令执行能力",但它的权限边界非常敏感。因为它一旦真的被触发,本机真实资源就可能被访问或修改。

4.3 它不是"无限授权",而是"继承宿主机运行身份的能力"

这里必须纠正一个很常见的误区:

很多人会把 system.run 想象成一个天然拥有高权限的系统级执行器,仿佛只要通过了它,就等于自动拿到了这台机器的全部控制权。

这并不准确。

更严谨的理解应该是:

system.run 本身并不凭空创造权限,它继承的是 node host 运行账户在宿主机上的权限边界。

这意味着:

  • 如果 node host 是以普通用户身份启动的,那么 system.run 启动出来的进程通常也只是普通用户权限;
  • 如果 node host 可以访问当前用户目录、桌面、文献目录,那么 system.run 在规则允许的前提下,原则上也可能访问这些位置;
  • 如果某些操作需要管理员权限,而 node host 当前没有提权能力,那 system.run 也不会神奇地自动越权。

所以,system.run 的权限上限,大体上就等于:

启动 node host 的那个 Windows 用户本来能做什么。

4.4 为什么最佳实践不是直接放开 PowerShell,而是只放固定脚本入口

从工程实践角度看,最稳妥的做法通常不是 allowlist 一个功能极强的通用解释器,而是只允许固定用途的脚本入口,例如:

text 复制代码
paper_scan.cmd
paper_rename.cmd
paper_classify.cmd

这样做的好处非常明显:

  • 把执行能力收敛到你自己定义过的流程入口;
  • 降低远程任意命令拼接带来的风险;
  • 便于审计、回放、排错;
  • 更适合作为可控的自动化节点能力暴露给 Gateway。

所以,真正安全的思路从来不是"给 system.run 更多权力",而是:

system.run 只被允许走你定义好的、边界清晰的受控入口。


五、把整句话讲透:什么叫"再结合 approvals 去调用 system.run"

这是最值得拆开讲透的一句话。

原话听起来容易让人误解成一种线性直觉:

  • 先调用 system.run
  • 再看 approvals;
  • 不通过就拦掉。

但真实机制恰恰不是这样。

更准确的理解应该是:

控制面先决定原则上怎么发,本地主机再决定这条请求是否允许落地,只有两边都通过之后,system.run 才会被真正调用。

换句话说:

不是先跑了再审批,而是审批通过之后才真正执行。


六、按时序看完整判定链:一条命令是怎么一步步落地的

如果把整个过程按时间顺序展开,通常可以拆成下面 5 步。

第 1 步:模型、CLI 或自动化流程形成执行请求

一切的起点,都是某个控制面主体发起了一个"希望执行命令"的请求。这个主体可能是:

  • 模型驱动的操作;
  • CLI 命令,如 openclaw nodes run
  • 自动化任务;
  • UI 上的某次执行动作。

这一阶段还没有真正碰到执行主机,只是生成了一个执行意图

第 2 步:Gateway 根据 tools.exec.* 看默认策略

接下来,Gateway 会先根据自己的默认配置来判断:

  • 这条请求应该发到 sandbox、gateway 还是 node;
  • 安全模式默认是什么;
  • 遇到执行是否需要弹审批;
  • 默认目标 node 是哪一台。

注意,这一步仍然只是控制面判断。

它解决的是"原则上应该怎么发 ",不是"执行主机是否最终同意执行"。

第 3 步:Gateway 把请求转发给目标 node

当目标是某台 node 时,Gateway 会把这条请求通过与 node 的连接通道发过去。

这一步体现的是控制面与能力宿主之间的转发关系。

也就是说,Gateway 并不是自己替 node 执行命令,而是:

把控制面形成的执行请求,交给具备相应能力的 node host。

第 4 步:node 在本机读取 exec-approvals.json 再判一次

到了这一步,事情才真正进入主机侧安全联锁。

node 会根据本机的 approvals 规则再做一次判断,包括:

  • 这条命令是否符合本地 security 策略;
  • 是否命中 allowlist;
  • 是否需要 ask
  • 未命中时是否走 askFallback
  • 当前环境有没有可用审批 UI。

这一关非常关键,因为它代表的是:

即使 Gateway 愿意发,本地执行主机也仍然可以拒绝。

第 5 步:前面都通过后,node 才真正调用 system.run

只有在前面所有条件都通过后,才会真正落到最终执行层。

也就是:

  • node 调用 system.run
  • 宿主机启动本地进程;
  • 返回真实执行结果。

这一步才叫"命令真正落地"。

因此,整条链路最准确的白话版可以概括成一句:

先在控制面决定原则上允不允许发,再在执行主机决定这台机器到底准不准跑,最后才真正启动进程。


七、为什么 node.list 能成功,不代表 nodes run 一定成功

这是远程执行场景里最常见、也最容易让人误判的问题之一。

很多人看到:

  • gateway call node.list 能拿到节点;
  • 节点状态是 paired;
  • 节点状态是 connected;

就会自然得出一个错误结论:

既然节点在线,那执行命令肯定没问题。

其实这个推理跳过了很多层。

7.1 node.list 成功,只能说明"节点注册与连接层"是通的

node.list 正常返回时,它最多只能说明:

  • SSH 隧道大概率没问题;
  • Gateway 本身在工作;
  • 节点确实已经注册到 Gateway;
  • 当前节点连接状态正常;
  • Gateway 能看到节点的能力声明。

但这些都还只是"能看到节点",不等于"能成功调起节点能力执行命令"。

7.2 nodes run 失败,可能卡在更后的任意一层

nodes run 真正失败的位置,可能在后面很多层里:

  • CLI 当前版本的节点命令调用通道本身存在不稳定;
  • Gateway 到 node 的具体命令分发过程中断;
  • 节点能力声明与调用不匹配;
  • approvals 未命中 allowlist;
  • 审批 UI 不可用导致卡在 approval required
  • 本机命令入口不存在;
  • system.run 启动目标进程失败。

因此,node.listnodes run 根本不是同一个层次的成功标准。

一个是在看:

我能不能看到节点。

另一个是在看:

我能不能穿过整条执行链,最终让命令在主机上真的跑起来。

这两者之间隔着:

  • 协议层;
  • 角色层;
  • 能力层;
  • 主机审批层;
  • 最终执行层。

所以,node.list 能成功,只能证明"前几层没问题",绝不能直接推出"命令执行链已经完全打通"。


八、所谓"远距离通信协议层级需要对应",到底是什么意思

很多人在排查远程节点问题时,会说一句很抽象的话:

协议层级需要对应。

这句话如果不拆开,很容易流于空泛。其实它背后讲的是一整套分层链路。

要把它说清楚,可以从下往上分成六层来看。


九、第一层:网络可达层------先解决"能不能连到"

这是最底层。

例如你的架构里,可能是这样的:

  • 云端 Gateway 监听在云服务器 127.0.0.1:18789
  • Windows 本地通过 SSH 隧道,把本地 18790 映射到云端 127.0.0.1:18789

这一层的职责只有一个:

让本地 node 看起来像是在连本地端口,实际上流量通过 SSH 转发到云端 Gateway。

注意,这一层只解决了"TCP 路能不能打通"。

它解决不了下面这些问题:

  • Gateway 协议是否正确;
  • WebSocket 是否握手成功;
  • 鉴权是否通过;
  • 角色是否匹配;
  • 节点能力是否存在;
  • approvals 是否放行。

所以网络通,不代表执行通。


十、第二层:WebSocket 连接层------不是裸 TCP,而是承载会话语义的连接

node host 并不是向某个随便的 TCP 端口发送字符串,而是要连接到 Gateway WebSocket

这意味着 SSH 隧道里承载的,不是"裸 TCP 上随便发点字节",而是:

WebSocket over forwarded TCP

也就是说,网络可达只是基础,真正进入 OpenClaw 通信语义的起点是 WebSocket 连接建立成功。

如果这一层失败,哪怕端口是通的,node 也没法变成一个真正挂接到 Gateway 上的能力宿主。


十一、第三层:Gateway 协议层------连上了,不代表会说"同一种话"

即使 WebSocket 连上了,也还不够。

因为在 WebSocket 之上,OpenClaw 还有自己的一套消息协议。

从抽象上看,这一层会涉及类似这样的消息结构:

  • Request:请求某个方法调用;
  • Response:返回成功或失败;
  • Event:推送某类状态事件。

也就是说,SSH 隧道和 WebSocket 只是通信管道,而 Gateway 协议层才是真正约定:

  • 消息长什么样;
  • 谁发请求;
  • 谁回响应;
  • 如何标识方法、参数、结果和错误;
  • 初始握手时如何表明身份和能力。

所以,"协议层级需要对应"在这里的第一重含义就是:

链路打通了,不代表双方已经能用同一种协议语义正常通信。


十二、第四层:角色与作用域层------为什么 CLI 和 node 同样连着 Gateway,干的事却完全不同

继续往上,就进入角色层

在这套体系中,虽然很多东西都连接到同一个 Gateway,但它们并不是同一种身份。

例如可以粗略区分为两类:

  • operator:CLI、UI、automation 这类控制面客户端;
  • node:暴露能力的宿主,例如 system、browser、screen 等。

这个区分非常关键,因为它决定了:

  • 谁负责发请求;
  • 谁负责提供能力;
  • 谁拥有读取、写入、管理、配对等不同范围的操作权;
  • 谁可以注册自身能力,谁只是去调用别人的能力。

所以,即使 CLI 和 node 同样都"连着 Gateway",两者在体系里的角色完全不同:

  • CLI 更像调度者、管理者、调用者;
  • node 更像资源宿主、能力提供者、执行者。

这也是为什么不能简单地把"连上 Gateway"理解成"所有连接对象都拥有同样的能力"。


十三、第五层:节点能力声明层------节点在线,不代表什么命令都能接

再往上,是很多人经常忽视的一层:节点能力声明

node 被 Gateway 看到,只代表这台机器已经作为一个能力宿主接入了系统。但它真正能做什么,还要看它对外声明了哪些能力和命令。

例如某个节点可能声明:

  • caps: browser, system
  • commands: browser.proxy, system.run, system.run.prepare, system.which

这表示 Gateway 不是"想给它发什么就发什么",而是只能调用它明确声明过的命令入口

因此,如果某个节点只声明了浏览器代理能力,却没有声明 system.run,那它即使在线,也不具备执行本地命令的能力。

所以这里又出现一个非常关键的判断:

节点在线 ≠ 节点具备目标能力。

要真正能执行命令,还必须满足:

  • 节点在线;
  • 节点已配对;
  • 节点声明了 system.run
  • 命令分发正确到这台节点。

十四、第六层:主机审批层------这才是"能不能真的落地"的最后裁决

在前面所有层都通过后,最后仍然要回到主机本地 approvals。

这一步的意义可以总结成一句:

即使控制面通了、协议通了、角色对了、能力也存在,本地机器仍然保有最终拒绝权。

这是整套架构最稳的地方,也是最容易被忽略的地方。

因为在很多远程控制系统里,人们习惯把"控制面已经授权"理解成"执行面必然服从"。但 OpenClaw 这里并不是这样的逻辑。

它保留了一条非常明确的原则:

宿主机对自己的命令执行拥有最终同意权。

也正因为有这一层,系统才能做到在远程调度和本地主机安全之间取得平衡。


十五、把整条链浓缩成一句真正准确的话

如果把前面六层再压缩成一句最准确的话,那就是:

隧道层、WebSocket 层、Gateway 协议层、角色/作用域层、节点能力层、主机审批层,必须一层层都通过,最后 system.run 才会真正落地执行。

这句话看似长,但它恰恰解释了远程执行中最常见的误区:

  • 不是"能连上"就等于"能执行";
  • 不是"能看到节点"就等于"能下发命令";
  • 不是"声明了 system.run"就等于"这台主机愿意执行";
  • 不是"Gateway 默认允许"就等于"本地 approvals 会放行"。

只有把这些层分开,排障思路才会变得清晰。


十六、最容易出现的几个误区,一次讲透

误区 1:Gateway 配成 host=node 就等于节点一定能执行

错误原因在于把"调度目标"当成了"执行结果"。

host=node 只能说明默认往节点发,不代表本地 approvals 一定放行,也不代表节点一定声明了正确能力,更不代表目标命令一定存在。

误区 2:system.run 自己决定权限

system.run 不是自带无限权限的神秘接口。它只是在 node host 的宿主环境里启动进程,权限边界取决于运行 node host 的那个本地账户。

误区 3:云端安全策略能替代本地 approvals

不能。云端策略解决的是"控制面怎么发",本地 approvals 解决的是"宿主机愿不愿意接"。这两者不是重复关系,而是串联关系。

误区 4:SSH 隧道通了,远程执行就没问题了

SSH 隧道只解决网络可达,后面还有 WebSocket、协议、角色、能力、审批等层次。

误区 5:node.list 正常,nodes run 失败一定是架构错了

不一定。很多情况下更可能是:

  • 节点命令调用链不稳定;
  • 能力分发存在问题;
  • approvals 未命中;
  • 审批 UI 缺失;
  • 本地命令入口未放行或不存在。

十七、从安全设计角度看,这套机制为什么合理

如果把 OpenClaw 这套设计放到更一般的软件架构视角去看,会发现它其实非常像成熟系统里常见的"多层联锁"思想。

17.1 控制面与执行面分离

这样做的好处是:

  • 调度逻辑集中;
  • 执行能力分布式暴露;
  • 不同宿主机可以拥有不同能力与不同安全边界;
  • 节点侧可以根据自己的风险暴露程度设置本地审批规则。

17.2 本地宿主机保有最终决定权

这避免了"远端控制面一旦出错,所有本地主机被一锅端"的风险。

17.3 白名单而不是全开放

从安全角度看,远程自动化系统最怕的不是"功能不够强",而是"边界不清"。

system.run 收缩为少量固定入口脚本,实际上是在把"通用执行器"改造成"受控流程触发器"。这比直接开放一个通用 shell 要稳得多。

17.4 多层串联比单层放权更可审计

当系统分成:

  • 调度层;
  • 协议层;
  • 能力层;
  • 审批层;
  • 执行层;

每一层都可以成为排障点、审计点、日志点。这对线上系统稳定性和安全性都非常重要。


十八、实战建议:如何把 system.run 用得既稳又可控

如果目标是让 OpenClaw 在本地 Windows 节点上执行自动化流程,又不想把风险放大,比较推荐的思路不是"尽可能开放",而是"尽可能收敛"。

18.1 不要优先开放通用解释器

例如不要一上来就把 PowerShell、cmd 的任意执行能力完全放开。

因为这等于把 system.run 变成一个泛用远程 shell,安全边界会非常大。

18.2 优先只开放固定用途脚本

更好的做法是围绕任务设计稳定入口,例如:

text 复制代码
paper_scan.cmd
paper_rename.cmd
paper_classify.cmd

每个脚本只干一类事,参数也尽可能收敛。这样既方便 allowlist 管控,也方便后续扩展自动化流程。

18.3 把复杂逻辑放进脚本,不要放进远程拼接命令

让远端只触发入口,把真正复杂的业务逻辑固化在本地脚本里,会比远程拼接长命令稳定得多,也安全得多。

18.4 排障时一定分层看问题

不要一看到执行失败就只盯着 system.run。正确做法应该是按层往下排:

  1. 网络层通不通;
  2. WebSocket 是否已连上;
  3. Gateway 是否能看到节点;
  4. 节点是否已 paired / connected;
  5. 节点是否声明了目标 command;
  6. 本地 approvals 是否命中 allowlist;
  7. 目标命令入口在宿主机上是否真实存在;
  8. node host 运行身份是否具备足够权限。

只有这样,问题定位才会高效。


十九、一个帮助理解的总流程图

下面用一个简单的 ASCII 流程图,把这整套机制串起来:

text 复制代码
[模型 / CLI / 自动化]
          |
          v
[Gateway 控制面]
  - 读取 tools.exec.host
  - 读取 tools.exec.security
  - 读取 tools.exec.ask
  - 读取 tools.exec.node
          |
          v
[将请求转发给目标 node]
          |
          v
[node host 本机]
  - 读取 exec-approvals.json
  - 校验 security / ask / allowlist
          |
   通过?  |----------------------否-------------------->
          |                                          [approval required / reject]
          v
[调用 system.run]
          |
          v
[Windows 本地真实进程启动]
          |
          v
[返回执行结果]

这个图最重要的意义,是把"谁负责什么"彻底分开:

  • Gateway 负责调度与默认策略
  • node 负责承接请求与暴露本机能力
  • approvals 负责主机侧最终放行
  • system.run 负责真正执行

二十、结语:真正应该记住的不是命令,而是判定链

很多人学习远程执行系统时,最先关注的是命令怎么写、端口怎么转发、节点怎么配对。但从长期来看,真正决定你是否能把系统用稳、排障排准、边界管住的,不是这些表层操作,而是对整条执行判定链的理解。

OpenClaw 这套机制的关键,不在于某一个点多么复杂,而在于它把"调度""能力暴露""本地审批""真实执行"明确拆成了不同层。

也正因为这种分层足够清晰,它才具有两个非常重要的优点:

一方面,控制面可以统一调度云端与本地节点,具备良好的扩展性;另一方面,本地宿主机又始终保有最后一道安全控制权,不会因为远端一个配置就把执行权完全放飞。

所以,最后只需要记住一句最核心的话:

Gateway 负责"调度和下令",node 负责"暴露本机能力",本地 approvals 负责"这台机器最后是否同意执行",而 system.run 负责"真的把命令跑起来"。其中任意一层没过,命令都不会真正落地。

这句话理解透了,OpenClaw 远程执行的大部分原理和排障逻辑,基本也就通了。


附:一段最简明的总结,适合作为文章摘要或开头导语

在 OpenClaw 的远程执行架构中,云端 Gateway 负责根据 tools.exec.* 配置形成默认执行策略,决定请求原则上发往哪里、按什么安全模式处理、是否需要审批;目标 node 负责作为能力宿主接收请求,并在本机读取 exec-approvals.json 做最后一道主机侧判定;只有当控制面策略与本地 approvals 同时放行后,节点才真正调用 system.run 在宿主机上启动本地进程。因此,system.run 是最终执行者而不是最终裁判者,SSH 隧道打通、节点在线、node.list 成功都不等于命令一定能落地执行,真正的执行链必须依次通过网络层、WebSocket 层、Gateway 协议层、角色/作用域层、节点能力层和主机审批层。

相关推荐
行者..................2 小时前
第2课:恢复出厂、掌握 Linux 基础命令并完成首次 GCC 编译
linux·qt·driver
竹之却2 小时前
国内外主流大模型全面解析(2026版)
服务器·大模型·国内外主流大模型·openclaw·云养虾
源远流长jerry2 小时前
RDMA Memory Region (MR) 机制详解:地址转换与内存保护
linux·服务器·网络·tcp/ip·架构·mr
c++逐梦人2 小时前
Linux进程信号
linux·服务器
清水白石0082 小时前
协程不是线程:深入理解 Python async/await 运行机制
java·linux·python
fengpan20042 小时前
ubuntu下vscode使用串口
linux·运维·服务器
IMPYLH2 小时前
Linux 的 cut 命令
linux·运维·服务器·数据库
草莓熊Lotso3 小时前
MySQL 内置函数指南:日期、字符串、数学函数实战
android·java·linux·运维·数据库·c++·mysql
艾莉丝努力练剑3 小时前
【Linux信号】Linux进程信号(上):信号产生方式和闹钟
linux·运维·服务器·c++·人工智能·ubuntu·云原生