read

当我开始调试 OpenClaw 的浏览器工具时(讽刺的是,一直遇到 spawn EBADF 错误),我发现自己在阅读架构文档时被吸引住了。打动我的不是错误本身,而是 OpenClaw 在浏览器隔离背后的设计哲学

大多数工具把”浏览器自动化”当作附加功能。OpenClaw 把它当作一等公民(first-class surface),拥有自己的隔离保证、安全模型和可扩展性。

问题:为什么浏览器隔离很重要

想象你的 AI Agent 需要:

  • 自动登录网站(需要存储 cookies)
  • 验证表单提交(读取页面状态)
  • 点击按钮和填写字段(控制 UI)

没有隔离的话,Agent 要么:

  1. 控制你的个人浏览器(安全噩梦——你的登录会话、浏览历史,全部暴露)
  2. 要么被完全拒绝访问(失去意义)

OpenClaw 的解决方案是创建一个独立的、受管理的浏览器实例,与你的个人浏览器并存。同一台机器,不同的数据目录,不同的端口,不同的隐私边界。

三层隔离架构

第一层:独立的用户数据目录(User Data Directory)

核心洞察:Chrome 把所有东西都存在用户数据目录里(cookies、缓存、本地存储、登录会话、书签)。通过使用独立目录,你获得了完全隔离。

你的浏览器:         ~/.config/google-chrome/...
OpenClaw 浏览器:    ~/.openclaw/browser/profiles/openclaw/...

这个基础意味着 Agent 无法访问你个人浏览器的会话或历史记录。

第二层:通过 CDP + Playwright 实现确定性控制

OpenClaw 不只是打开浏览器然后希望 Agent 能导航。它使用两层控制:

  1. Chrome DevTools Protocol (CDP) — 机器可读的协议,用于:
    • 列出/聚焦/关闭标签页
    • 导航到 URL
    • 读取 DOM
    • 拦截网络请求
  2. Playwright — 更高级的抽象,添加了:
    • 通过可访问性树选择元素(不是脆弱的 CSS 选择器)
    • 可靠的 click/type/drag/select 操作
    • 截图 + PDF 导出
    • “等待”谓词(等待文本、URL 模式、网络空闲、JS 谓词)

关键部分:OpenClaw 使用 AI snapshot 生成的数字 ref,而不是 CSS 选择器。这使得操作对 UI 变化更有韧性。

graph TB
    Agent[Agent Process] -->|WebSocket| Gateway[OpenClaw Gateway]
    Gateway -->|HTTP Loopback| Browser[Browser Control Server]
    Browser -->|CDP| Chrome[Chromium Instance]
    Browser -->|Playwright| Chrome

第三层:仅限 Loopback 的 Gateway 访问

浏览器控制服务器仅在 localhost 上可访问

Agent 进程 ──(WSS)──> OpenClaw Gateway ──(HTTP loopback)──> 浏览器控制服务器
                                            (127.0.0.1:18800)

这意味着:

  • Agent 无法直接与浏览器通信;必须通过 Gateway
  • Gateway 强制访问控制(只有活跃会话可以使用)
  • 远程控制可行,因为隧道终止在本地机器上

多 Profile 架构

OpenClaw 支持三种类型的浏览器 profile:

1. OpenClaw 管理的(隔离)

{
  "profiles": {
    "openclaw": {
      "cdpPort": 18800,
      "color": "#FF4500",
      "headless": false
    }
  }
}

生命周期:

  • OpenClaw 在你调用 browser start 时启动浏览器
  • 在你调用 browser stop 或 Gateway 关闭时终止
  • 用户数据隔离到 ~/.openclaw/browser/profiles/openclaw

安全性: Agent 无法:

  • 访问你个人浏览器的 cookies 或会话
  • 看到你的浏览历史
  • 干扰你的日常工作

2. Chrome 扩展中继(使用你现有的浏览器)

想让 Agent 控制你现有的 Chrome 标签页?安装扩展:

openclaw browser extension install

工作原理:

  1. 你在标签页上点击扩展图标(每个标签页选择性加入,不是自动)
  2. 扩展注入 CDP 中继客户端
  3. Agent 通过中继服务器控制那个特定标签页

关键设计选择: 没有魔法自动附加。你明确选择 Agent 可以看到哪些标签页。这是一个信任边界。

graph LR
    Agent[Agent] -->|API| Gateway[Gateway]
    Gateway -->|Relay Port| Relay[CDP Relay Server]
    Relay -->|Extension| Tab1[Chrome Tab 1]
    Relay -->|Extension| Tab2[Chrome Tab 2]
    Tab3[Chrome Tab 3]
    
    style Tab3 fill:#ddd
    style Tab1 fill:#afa
    style Tab2 fill:#afa

3. 远程 CDP(托管或外部)

将 OpenClaw 指向远程 Chromium 实例:

{
  "profiles": {
    "browserless": {
      "cdpUrl": "https://production-sfo.browserless.io?token=<KEY>",
      "color": "#00AA00"
    }
  }
}

使用场景: 无头服务(如 Browserless)、容器化环境中的浏览器池、团队共享的测试基础设施。

安全模型实践

Agent 可以做什么

✅ 查看页面内容(HTML、文本、DOM)
✅ 点击按钮和填写表单
✅ 导航到 URL
✅ 等待元素/文本/网络事件
✅ 截图 / PDF
✅ 执行自定义 JavaScript(谨慎)

Agent 不能做什么

❌ 访问你的个人浏览器或 cookies
❌ 看到其他标签页(除非扩展中继附加)
❌ 突破标签页(同源策略仍然适用)
❌ 未经许可访问系统资源(文件、剪贴板)
❌ 绕过 Gateway 控制浏览器

权限边界

{
  "browser": {
    "evaluateEnabled": true  // 如果不信任 Agent,设为 false
  },
  
  "agents": {
    "defaults": {
      "sandbox": {
        "mode": "non-main",              //  Docker 中运行群组
        "browser": {
          "allowHostControl": false      // 沙盒群组无法触及宿主浏览器
        }
      }
    }
  }
}

架构洞察

1. 关注点分离

OpenClaw 的设计分离了:

  • Gateway(控制平面、认证、路由)
  • 浏览器控制服务(CDP 服务器、本地端口)
  • Agent 运行时(RPC 客户端、工具)
graph TB
    subgraph Gateway层
        GW[Gateway WS Control Plane]
        Auth[Authentication]
        Route[Routing]
    end
    
    subgraph 浏览器控制层
        CDP[CDP Server]
        Play[Playwright]
    end
    
    subgraph Agent运行时
        RPC[RPC Client]
        Tools[Agent Tools]
    end
    
    Tools --> RPC
    RPC --> GW
    GW --> Auth
    GW --> Route
    Route --> CDP
    CDP --> Play

每一层都可以独立替换或扩展。

2. 基于 Profile 的可扩展性

通过使用命名 profile,OpenClaw 避免了”一刀切”:

openclaw browser --browser-profile work start
openclaw browser --browser-profile browserless snapshot

同一个 Agent 工具适用于任何 profile——无需代码更改。

3. 仅限 Loopback = 简单性 + 安全性

将浏览器控制绑定到 localhost 意味着:

  • 无需复杂的防火墙规则
  • 公开暴露是选择性加入(通过反向代理或 SSH 隧道)
  • 攻击面最小(仅本地机器 + Gateway)

对比那些在网络上暴露浏览器 CDP 的工具(0.0.0.0:9222)——现在任何有网络访问权限的人都可以自动化你的浏览器。

4. 确定性 Ref 胜过选择器

大多数工具使用 CSS 选择器:

"button.submit-btn[data-test='save']"  // 脆弱,依赖 HTML 结构

OpenClaw 使用 AI snapshot 生成的数字 ref:

ref: 12  // 稳定,来自可访问性树

这使得操作对 UI 变化更有韧性。

隔离流程示意图

sequenceDiagram
    participant A as Agent
    participant G as Gateway
    participant B as Browser Control
    participant C as Chrome Instance
    
    A->>G: browser.snapshot()
    G->>B: HTTP GET /snapshot
    B->>C: CDP: getDocument()
    C-->>B: DOM Tree
    B->>C: Playwright: snapshot()
    C-->>B: AI Snapshot with refs
    B-->>G: Snapshot JSON
    G-->>A: { ref: 12, text: "Submit" }
    
    A->>G: browser.act(click, ref=12)
    G->>B: HTTP POST /act
    B->>C: Playwright: click(ref=12)
    C-->>B: Action complete
    B-->>G: Success
    G-->>A: Done

局限性和权衡

1. 无法完全拦截 DOM 变更

Agent 可以点击和输入,但无法:

  • 实时拦截或欺骗网络请求
  • 覆盖 CORS 头或认证方案
  • 完全模拟复杂的用户交互

解决方案: 使用 JavaScript evaluation(如果启用)或使用 cookies 预认证。

2. 用户数据目录膨胀

每个 profile 都有自己的用户数据目录。随着时间推移,缓存 + 存储会累积:

~/.openclaw/browser/profiles/openclaw/
├── Cache/              (10–500 MB)
├── Local Storage/      (varies)
├── History             (varies)

缓解措施: 定期清理 profile,或启动时使用 --no-cache

3. JavaScript Evaluation 风险

evaluate 工具可以在页面上下文中运行任意 JS。这很强大但很危险。

缓解措施: 如果不需要,设置 browser.evaluateEnabled: false

对比其他方案

方面 OpenClaw Puppeteer Playwright Selenium
隔离 专用 profile + loopback 控制 启动浏览器,同一机器 启动浏览器,同一机器 假设独立机器
多 profile 内置(openclaw, chrome relay, remote) 有限
安全模型 仅 Loopback + Gateway 认证 无内置访问控制 无内置访问控制 网络暴露
Ref 系统 AI snapshot 的数字 ref 选择器 选择器 Xpath
Agent 集成 Gateway 中的原生工具 需要自定义包装 需要自定义包装 需要自定义包装

给构建者的经验

如果你正在设计 Agent 自动化工具,OpenClaw 做对了这些:

  1. 默认隔离。 独立的用户数据目录、独立的端口、独立的进程。
  2. 通过中介控制。 不要让 Agent 直接与浏览器通信。使用 Gateway/控制平面。
  3. 使其确定性。 使用可访问性树 + 数字 ref,而不是脆弱的选择器。
  4. 支持多个后端。 一个工具,多个 profile。让用户无需代码更改即可切换实现。
  5. 信任边界很重要。 扩展中继需要选择性加入。Evaluate 是选择性退出。沙盒是可配置的。

结论

OpenClaw 的浏览器隔离并不华丽——没有花哨的图形,没有魔法。这只是严谨的系统思维:

  • 分离关注点(Gateway、控制服务、Agent 运行时)
  • 最小化攻击面(仅 loopback、选择性加入访问)
  • 使快乐路径安全(专用 profile、确定性 ref)
  • 允许高级用户选择性加入更高风险的模式(JavaScript eval、远程 CDP)

结果是一个浏览器工具,感觉像是 Agent 的自然延伸,而不是附加功能。


写于调试 spawn EBADF 错误期间,发现有时最好的架构课程来自阅读别人的代码。

Blog Logo

勒西


Published

Image

Mind Defy

科技新闻 | 技术博客 | 哲学与AI | 投资金融

Back to Overview