Browser Automation for Coding Agents:六种架构方案深度对比

Playwright、Claude Code、Cursor、VS Code、OpenCode、OpenClaw,到底是如何让 AI 控制浏览器的?

表面上,它们都在做 Browser Automation。

但深入研究之后会发现,真正决定一个 Browser Agent 能力边界的,并不是它有多少个 clicktypescreenshot 工具,而是一个更加底层的问题:

这个浏览器,到底是谁的?

对于 Coding Agent 来说,这个问题尤其重要。

如果 Agent 只是打开一个全新的浏览器,那么实现起来并不困难。Playwright 已经提供了非常成熟的基础设施。

但如果用户说:

"帮我打开我已经登录的 GitHub,找到这个项目,然后修改 Issue。"

事情马上变得复杂。

因为这里真正需要的不是一个"浏览器",而是:

用户正在使用、并且已经登录的浏览器。

这也是为什么 Claude Code、Cursor、OpenCode、OpenClaw 等方案最终走出了完全不同的架构路线。

本文将从 Browser Ownership、Transport、Tool Layer、Element Reference、Security、Verify Loop 六个维度,对这些方案进行一次系统比较,并最终讨论:

如果我们自己实现一个 Coding Agent,Browser Automation 应该怎么设计?


一、先给结论:Browser Automation 有三种架构

把 Playwright、Claude Code、Cursor、VS Code、OpenCode 和 OpenClaw 放在一起研究,会发现它们实际上可以归结为三种模式。
#mermaid-svg-pO8ZCgxd2TBFtNsx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pO8ZCgxd2TBFtNsx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pO8ZCgxd2TBFtNsx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pO8ZCgxd2TBFtNsx .error-icon{fill:#552222;}#mermaid-svg-pO8ZCgxd2TBFtNsx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pO8ZCgxd2TBFtNsx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pO8ZCgxd2TBFtNsx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pO8ZCgxd2TBFtNsx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pO8ZCgxd2TBFtNsx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pO8ZCgxd2TBFtNsx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pO8ZCgxd2TBFtNsx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pO8ZCgxd2TBFtNsx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pO8ZCgxd2TBFtNsx .marker.cross{stroke:#333333;}#mermaid-svg-pO8ZCgxd2TBFtNsx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pO8ZCgxd2TBFtNsx p{margin:0;}#mermaid-svg-pO8ZCgxd2TBFtNsx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pO8ZCgxd2TBFtNsx .cluster-label text{fill:#333;}#mermaid-svg-pO8ZCgxd2TBFtNsx .cluster-label span{color:#333;}#mermaid-svg-pO8ZCgxd2TBFtNsx .cluster-label span p{background-color:transparent;}#mermaid-svg-pO8ZCgxd2TBFtNsx .label text,#mermaid-svg-pO8ZCgxd2TBFtNsx span{fill:#333;color:#333;}#mermaid-svg-pO8ZCgxd2TBFtNsx .node rect,#mermaid-svg-pO8ZCgxd2TBFtNsx .node circle,#mermaid-svg-pO8ZCgxd2TBFtNsx .node ellipse,#mermaid-svg-pO8ZCgxd2TBFtNsx .node polygon,#mermaid-svg-pO8ZCgxd2TBFtNsx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pO8ZCgxd2TBFtNsx .rough-node .label text,#mermaid-svg-pO8ZCgxd2TBFtNsx .node .label text,#mermaid-svg-pO8ZCgxd2TBFtNsx .image-shape .label,#mermaid-svg-pO8ZCgxd2TBFtNsx .icon-shape .label{text-anchor:middle;}#mermaid-svg-pO8ZCgxd2TBFtNsx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pO8ZCgxd2TBFtNsx .rough-node .label,#mermaid-svg-pO8ZCgxd2TBFtNsx .node .label,#mermaid-svg-pO8ZCgxd2TBFtNsx .image-shape .label,#mermaid-svg-pO8ZCgxd2TBFtNsx .icon-shape .label{text-align:center;}#mermaid-svg-pO8ZCgxd2TBFtNsx .node.clickable{cursor:pointer;}#mermaid-svg-pO8ZCgxd2TBFtNsx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pO8ZCgxd2TBFtNsx .arrowheadPath{fill:#333333;}#mermaid-svg-pO8ZCgxd2TBFtNsx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pO8ZCgxd2TBFtNsx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pO8ZCgxd2TBFtNsx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pO8ZCgxd2TBFtNsx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pO8ZCgxd2TBFtNsx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pO8ZCgxd2TBFtNsx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pO8ZCgxd2TBFtNsx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pO8ZCgxd2TBFtNsx .cluster text{fill:#333;}#mermaid-svg-pO8ZCgxd2TBFtNsx .cluster span{color:#333;}#mermaid-svg-pO8ZCgxd2TBFtNsx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pO8ZCgxd2TBFtNsx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pO8ZCgxd2TBFtNsx rect.text{fill:none;stroke-width:0;}#mermaid-svg-pO8ZCgxd2TBFtNsx .icon-shape,#mermaid-svg-pO8ZCgxd2TBFtNsx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pO8ZCgxd2TBFtNsx .icon-shape p,#mermaid-svg-pO8ZCgxd2TBFtNsx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pO8ZCgxd2TBFtNsx .icon-shape .label rect,#mermaid-svg-pO8ZCgxd2TBFtNsx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pO8ZCgxd2TBFtNsx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pO8ZCgxd2TBFtNsx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pO8ZCgxd2TBFtNsx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} AI Agent
Managed Browser
Embedded Browser
User Browser
Playwright
OpenClaw openclaw
Cursor
VS Code WebView
Claude Code
OpenClaw chrome / user

1. Agent 自己启动 Browser

典型方案:

  • Playwright
  • OpenClaw openclaw profile

Browser 是 Agent 自己创建和管理的。

优点:

  • 控制力强
  • 环境隔离
  • 不需要安装扩展
  • 可以自由配置 Browser
  • 容易实现自动化

缺点也非常明显:

拿不到用户日常浏览器的登录态。


2. IDE 内嵌 Browser

典型方案:

  • Cursor
  • VS Code WebView

架构是:
#mermaid-svg-KC9NMpolwmftOdEA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KC9NMpolwmftOdEA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KC9NMpolwmftOdEA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KC9NMpolwmftOdEA .error-icon{fill:#552222;}#mermaid-svg-KC9NMpolwmftOdEA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KC9NMpolwmftOdEA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KC9NMpolwmftOdEA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KC9NMpolwmftOdEA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KC9NMpolwmftOdEA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KC9NMpolwmftOdEA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KC9NMpolwmftOdEA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KC9NMpolwmftOdEA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KC9NMpolwmftOdEA .marker.cross{stroke:#333333;}#mermaid-svg-KC9NMpolwmftOdEA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KC9NMpolwmftOdEA p{margin:0;}#mermaid-svg-KC9NMpolwmftOdEA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KC9NMpolwmftOdEA .cluster-label text{fill:#333;}#mermaid-svg-KC9NMpolwmftOdEA .cluster-label span{color:#333;}#mermaid-svg-KC9NMpolwmftOdEA .cluster-label span p{background-color:transparent;}#mermaid-svg-KC9NMpolwmftOdEA .label text,#mermaid-svg-KC9NMpolwmftOdEA span{fill:#333;color:#333;}#mermaid-svg-KC9NMpolwmftOdEA .node rect,#mermaid-svg-KC9NMpolwmftOdEA .node circle,#mermaid-svg-KC9NMpolwmftOdEA .node ellipse,#mermaid-svg-KC9NMpolwmftOdEA .node polygon,#mermaid-svg-KC9NMpolwmftOdEA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KC9NMpolwmftOdEA .rough-node .label text,#mermaid-svg-KC9NMpolwmftOdEA .node .label text,#mermaid-svg-KC9NMpolwmftOdEA .image-shape .label,#mermaid-svg-KC9NMpolwmftOdEA .icon-shape .label{text-anchor:middle;}#mermaid-svg-KC9NMpolwmftOdEA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KC9NMpolwmftOdEA .rough-node .label,#mermaid-svg-KC9NMpolwmftOdEA .node .label,#mermaid-svg-KC9NMpolwmftOdEA .image-shape .label,#mermaid-svg-KC9NMpolwmftOdEA .icon-shape .label{text-align:center;}#mermaid-svg-KC9NMpolwmftOdEA .node.clickable{cursor:pointer;}#mermaid-svg-KC9NMpolwmftOdEA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KC9NMpolwmftOdEA .arrowheadPath{fill:#333333;}#mermaid-svg-KC9NMpolwmftOdEA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KC9NMpolwmftOdEA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KC9NMpolwmftOdEA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KC9NMpolwmftOdEA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KC9NMpolwmftOdEA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KC9NMpolwmftOdEA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KC9NMpolwmftOdEA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KC9NMpolwmftOdEA .cluster text{fill:#333;}#mermaid-svg-KC9NMpolwmftOdEA .cluster span{color:#333;}#mermaid-svg-KC9NMpolwmftOdEA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KC9NMpolwmftOdEA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KC9NMpolwmftOdEA rect.text{fill:none;stroke-width:0;}#mermaid-svg-KC9NMpolwmftOdEA .icon-shape,#mermaid-svg-KC9NMpolwmftOdEA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KC9NMpolwmftOdEA .icon-shape p,#mermaid-svg-KC9NMpolwmftOdEA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KC9NMpolwmftOdEA .icon-shape .label rect,#mermaid-svg-KC9NMpolwmftOdEA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KC9NMpolwmftOdEA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KC9NMpolwmftOdEA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KC9NMpolwmftOdEA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent
IDE
Embedded Browser / WebView
Web Page

优点是浏览器与 IDE 深度集成。

但是:

这个 Browser 属于 IDE,而不是用户。

因此,它通常也没有用户 Chrome 中的 Cookie、Session 和登录状态。


3. 接管用户日常 Browser

典型方案:

  • Claude Code
  • OpenClaw chrome
  • OpenClaw user

架构:
#mermaid-svg-Hx5gSMtzDyqWHJdQ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .error-icon{fill:#552222;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .marker.cross{stroke:#333333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Hx5gSMtzDyqWHJdQ p{margin:0;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .cluster-label text{fill:#333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .cluster-label span{color:#333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .cluster-label span p{background-color:transparent;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .label text,#mermaid-svg-Hx5gSMtzDyqWHJdQ span{fill:#333;color:#333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .node rect,#mermaid-svg-Hx5gSMtzDyqWHJdQ .node circle,#mermaid-svg-Hx5gSMtzDyqWHJdQ .node ellipse,#mermaid-svg-Hx5gSMtzDyqWHJdQ .node polygon,#mermaid-svg-Hx5gSMtzDyqWHJdQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .rough-node .label text,#mermaid-svg-Hx5gSMtzDyqWHJdQ .node .label text,#mermaid-svg-Hx5gSMtzDyqWHJdQ .image-shape .label,#mermaid-svg-Hx5gSMtzDyqWHJdQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .rough-node .label,#mermaid-svg-Hx5gSMtzDyqWHJdQ .node .label,#mermaid-svg-Hx5gSMtzDyqWHJdQ .image-shape .label,#mermaid-svg-Hx5gSMtzDyqWHJdQ .icon-shape .label{text-align:center;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .node.clickable{cursor:pointer;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .arrowheadPath{fill:#333333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Hx5gSMtzDyqWHJdQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hx5gSMtzDyqWHJdQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Hx5gSMtzDyqWHJdQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .cluster text{fill:#333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .cluster span{color:#333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Hx5gSMtzDyqWHJdQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .icon-shape,#mermaid-svg-Hx5gSMtzDyqWHJdQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .icon-shape p,#mermaid-svg-Hx5gSMtzDyqWHJdQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .icon-shape .label rect,#mermaid-svg-Hx5gSMtzDyqWHJdQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hx5gSMtzDyqWHJdQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Hx5gSMtzDyqWHJdQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Hx5gSMtzDyqWHJdQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent
Browser Bridge
User Chrome
Logged-in Web Page

这种模式最大的优势是:

可以直接利用用户已经登录的浏览器状态。

GitHub、Google、Jira、Slack 以及企业内部 Web 系统都可以直接复用现有 Session。

但与此同时,它也是最复杂的一种方案。


二、为什么"控制用户 Chrome"这么难?

很多人第一次做 Browser Agent 时,都会想到:

javascript 复制代码
chromium.connectOverCDP(...)

Playwright 确实提供了 connectOverCDP,可以连接一个已经运行的 Chromium Browser。官方文档也明确说明,它通过 Chrome DevTools Protocol 附着到现有浏览器实例。

问题是:

普通用户正常启动的 Chrome,并不等于一个对外开放 CDP Endpoint 的 Chrome。

如果 Chrome 没有启动:

text 复制代码
--remote-debugging-port

或者:

text 复制代码
--remote-debugging-pipe

那么外部进程通常不能直接接管它。

因此:
#mermaid-svg-nx4W3Zv7KU82Wa9X{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nx4W3Zv7KU82Wa9X .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nx4W3Zv7KU82Wa9X .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nx4W3Zv7KU82Wa9X .error-icon{fill:#552222;}#mermaid-svg-nx4W3Zv7KU82Wa9X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nx4W3Zv7KU82Wa9X .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nx4W3Zv7KU82Wa9X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nx4W3Zv7KU82Wa9X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nx4W3Zv7KU82Wa9X .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nx4W3Zv7KU82Wa9X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nx4W3Zv7KU82Wa9X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nx4W3Zv7KU82Wa9X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nx4W3Zv7KU82Wa9X .marker.cross{stroke:#333333;}#mermaid-svg-nx4W3Zv7KU82Wa9X svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nx4W3Zv7KU82Wa9X p{margin:0;}#mermaid-svg-nx4W3Zv7KU82Wa9X .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nx4W3Zv7KU82Wa9X .cluster-label text{fill:#333;}#mermaid-svg-nx4W3Zv7KU82Wa9X .cluster-label span{color:#333;}#mermaid-svg-nx4W3Zv7KU82Wa9X .cluster-label span p{background-color:transparent;}#mermaid-svg-nx4W3Zv7KU82Wa9X .label text,#mermaid-svg-nx4W3Zv7KU82Wa9X span{fill:#333;color:#333;}#mermaid-svg-nx4W3Zv7KU82Wa9X .node rect,#mermaid-svg-nx4W3Zv7KU82Wa9X .node circle,#mermaid-svg-nx4W3Zv7KU82Wa9X .node ellipse,#mermaid-svg-nx4W3Zv7KU82Wa9X .node polygon,#mermaid-svg-nx4W3Zv7KU82Wa9X .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nx4W3Zv7KU82Wa9X .rough-node .label text,#mermaid-svg-nx4W3Zv7KU82Wa9X .node .label text,#mermaid-svg-nx4W3Zv7KU82Wa9X .image-shape .label,#mermaid-svg-nx4W3Zv7KU82Wa9X .icon-shape .label{text-anchor:middle;}#mermaid-svg-nx4W3Zv7KU82Wa9X .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nx4W3Zv7KU82Wa9X .rough-node .label,#mermaid-svg-nx4W3Zv7KU82Wa9X .node .label,#mermaid-svg-nx4W3Zv7KU82Wa9X .image-shape .label,#mermaid-svg-nx4W3Zv7KU82Wa9X .icon-shape .label{text-align:center;}#mermaid-svg-nx4W3Zv7KU82Wa9X .node.clickable{cursor:pointer;}#mermaid-svg-nx4W3Zv7KU82Wa9X .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nx4W3Zv7KU82Wa9X .arrowheadPath{fill:#333333;}#mermaid-svg-nx4W3Zv7KU82Wa9X .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nx4W3Zv7KU82Wa9X .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nx4W3Zv7KU82Wa9X .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nx4W3Zv7KU82Wa9X .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nx4W3Zv7KU82Wa9X .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nx4W3Zv7KU82Wa9X .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nx4W3Zv7KU82Wa9X .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nx4W3Zv7KU82Wa9X .cluster text{fill:#333;}#mermaid-svg-nx4W3Zv7KU82Wa9X .cluster span{color:#333;}#mermaid-svg-nx4W3Zv7KU82Wa9X div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nx4W3Zv7KU82Wa9X .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nx4W3Zv7KU82Wa9X rect.text{fill:none;stroke-width:0;}#mermaid-svg-nx4W3Zv7KU82Wa9X .icon-shape,#mermaid-svg-nx4W3Zv7KU82Wa9X .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nx4W3Zv7KU82Wa9X .icon-shape p,#mermaid-svg-nx4W3Zv7KU82Wa9X .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nx4W3Zv7KU82Wa9X .icon-shape .label rect,#mermaid-svg-nx4W3Zv7KU82Wa9X .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nx4W3Zv7KU82Wa9X .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nx4W3Zv7KU82Wa9X .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nx4W3Zv7KU82Wa9X :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} connectOverCDP()
External Agent
Normally Started Chrome
No Debugging Endpoint

这也是为什么"接管用户 Chrome"最终往往需要:

Chrome Extension

因为 Extension 本身就在 Chrome 内部,可以使用 Chrome 提供的浏览器调试能力。


三、Playwright:Browser Automation 的地基

如果整个 Browser Agent 技术栈是一栋楼,那么:

Playwright 更像是地基。

它不是 Agent,而是 Browser Automation Framework。

典型架构:
#mermaid-svg-4N9TdhLtyrRICRFm{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4N9TdhLtyrRICRFm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4N9TdhLtyrRICRFm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4N9TdhLtyrRICRFm .error-icon{fill:#552222;}#mermaid-svg-4N9TdhLtyrRICRFm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4N9TdhLtyrRICRFm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4N9TdhLtyrRICRFm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4N9TdhLtyrRICRFm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4N9TdhLtyrRICRFm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4N9TdhLtyrRICRFm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4N9TdhLtyrRICRFm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4N9TdhLtyrRICRFm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4N9TdhLtyrRICRFm .marker.cross{stroke:#333333;}#mermaid-svg-4N9TdhLtyrRICRFm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4N9TdhLtyrRICRFm p{margin:0;}#mermaid-svg-4N9TdhLtyrRICRFm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4N9TdhLtyrRICRFm .cluster-label text{fill:#333;}#mermaid-svg-4N9TdhLtyrRICRFm .cluster-label span{color:#333;}#mermaid-svg-4N9TdhLtyrRICRFm .cluster-label span p{background-color:transparent;}#mermaid-svg-4N9TdhLtyrRICRFm .label text,#mermaid-svg-4N9TdhLtyrRICRFm span{fill:#333;color:#333;}#mermaid-svg-4N9TdhLtyrRICRFm .node rect,#mermaid-svg-4N9TdhLtyrRICRFm .node circle,#mermaid-svg-4N9TdhLtyrRICRFm .node ellipse,#mermaid-svg-4N9TdhLtyrRICRFm .node polygon,#mermaid-svg-4N9TdhLtyrRICRFm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4N9TdhLtyrRICRFm .rough-node .label text,#mermaid-svg-4N9TdhLtyrRICRFm .node .label text,#mermaid-svg-4N9TdhLtyrRICRFm .image-shape .label,#mermaid-svg-4N9TdhLtyrRICRFm .icon-shape .label{text-anchor:middle;}#mermaid-svg-4N9TdhLtyrRICRFm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4N9TdhLtyrRICRFm .rough-node .label,#mermaid-svg-4N9TdhLtyrRICRFm .node .label,#mermaid-svg-4N9TdhLtyrRICRFm .image-shape .label,#mermaid-svg-4N9TdhLtyrRICRFm .icon-shape .label{text-align:center;}#mermaid-svg-4N9TdhLtyrRICRFm .node.clickable{cursor:pointer;}#mermaid-svg-4N9TdhLtyrRICRFm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4N9TdhLtyrRICRFm .arrowheadPath{fill:#333333;}#mermaid-svg-4N9TdhLtyrRICRFm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4N9TdhLtyrRICRFm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4N9TdhLtyrRICRFm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4N9TdhLtyrRICRFm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4N9TdhLtyrRICRFm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4N9TdhLtyrRICRFm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4N9TdhLtyrRICRFm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4N9TdhLtyrRICRFm .cluster text{fill:#333;}#mermaid-svg-4N9TdhLtyrRICRFm .cluster span{color:#333;}#mermaid-svg-4N9TdhLtyrRICRFm div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4N9TdhLtyrRICRFm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4N9TdhLtyrRICRFm rect.text{fill:none;stroke-width:0;}#mermaid-svg-4N9TdhLtyrRICRFm .icon-shape,#mermaid-svg-4N9TdhLtyrRICRFm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4N9TdhLtyrRICRFm .icon-shape p,#mermaid-svg-4N9TdhLtyrRICRFm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4N9TdhLtyrRICRFm .icon-shape .label rect,#mermaid-svg-4N9TdhLtyrRICRFm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4N9TdhLtyrRICRFm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4N9TdhLtyrRICRFm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4N9TdhLtyrRICRFm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} CDP / Pipe
Inject
Agent
Playwright
Chromium
Web Page
Injected Script

Playwright 自己启动 Chromium,因此:

Browser 的生命周期和控制权都掌握在 Playwright 手里。

这也是为什么它可以提供非常完整的能力:

  • navigation
  • click
  • type
  • fill
  • locator
  • auto-waiting
  • screenshot
  • network interception
  • trace

但它默认创建的是独立 Browser Profile。

所以:

text 复制代码
Playwright Browser
        ≠
User Chrome

这意味着:

text 复制代码
User Chrome
 ├── GitHub Login
 ├── Google Login
 └── Jira Login

Playwright Browser
 ├── No GitHub Login
 ├── No Google Login
 └── No Jira Login

这并不是 Playwright 的缺陷。

恰恰相反,这是一个非常合理的安全边界。


四、Playwright 最值得学习的设计:Stable Ref

Browser Agent 最大的问题之一是:

LLM 如何准确地告诉 Browser "点击哪个元素"?

最简单的方案是坐标:

text 复制代码
x = 523
y = 281

但坐标非常脆弱。

只要:

  • 页面滚动
  • 窗口大小变化
  • Layout 变化
  • 浏览器缩放

坐标就可能失效。

所以现代 Browser Agent 更倾向于:
#mermaid-svg-xqMOexZd2F58LVS9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xqMOexZd2F58LVS9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xqMOexZd2F58LVS9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xqMOexZd2F58LVS9 .error-icon{fill:#552222;}#mermaid-svg-xqMOexZd2F58LVS9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xqMOexZd2F58LVS9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xqMOexZd2F58LVS9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xqMOexZd2F58LVS9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xqMOexZd2F58LVS9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xqMOexZd2F58LVS9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xqMOexZd2F58LVS9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xqMOexZd2F58LVS9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xqMOexZd2F58LVS9 .marker.cross{stroke:#333333;}#mermaid-svg-xqMOexZd2F58LVS9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xqMOexZd2F58LVS9 p{margin:0;}#mermaid-svg-xqMOexZd2F58LVS9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xqMOexZd2F58LVS9 .cluster-label text{fill:#333;}#mermaid-svg-xqMOexZd2F58LVS9 .cluster-label span{color:#333;}#mermaid-svg-xqMOexZd2F58LVS9 .cluster-label span p{background-color:transparent;}#mermaid-svg-xqMOexZd2F58LVS9 .label text,#mermaid-svg-xqMOexZd2F58LVS9 span{fill:#333;color:#333;}#mermaid-svg-xqMOexZd2F58LVS9 .node rect,#mermaid-svg-xqMOexZd2F58LVS9 .node circle,#mermaid-svg-xqMOexZd2F58LVS9 .node ellipse,#mermaid-svg-xqMOexZd2F58LVS9 .node polygon,#mermaid-svg-xqMOexZd2F58LVS9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xqMOexZd2F58LVS9 .rough-node .label text,#mermaid-svg-xqMOexZd2F58LVS9 .node .label text,#mermaid-svg-xqMOexZd2F58LVS9 .image-shape .label,#mermaid-svg-xqMOexZd2F58LVS9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-xqMOexZd2F58LVS9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xqMOexZd2F58LVS9 .rough-node .label,#mermaid-svg-xqMOexZd2F58LVS9 .node .label,#mermaid-svg-xqMOexZd2F58LVS9 .image-shape .label,#mermaid-svg-xqMOexZd2F58LVS9 .icon-shape .label{text-align:center;}#mermaid-svg-xqMOexZd2F58LVS9 .node.clickable{cursor:pointer;}#mermaid-svg-xqMOexZd2F58LVS9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xqMOexZd2F58LVS9 .arrowheadPath{fill:#333333;}#mermaid-svg-xqMOexZd2F58LVS9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xqMOexZd2F58LVS9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xqMOexZd2F58LVS9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xqMOexZd2F58LVS9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xqMOexZd2F58LVS9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xqMOexZd2F58LVS9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xqMOexZd2F58LVS9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xqMOexZd2F58LVS9 .cluster text{fill:#333;}#mermaid-svg-xqMOexZd2F58LVS9 .cluster span{color:#333;}#mermaid-svg-xqMOexZd2F58LVS9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xqMOexZd2F58LVS9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xqMOexZd2F58LVS9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-xqMOexZd2F58LVS9 .icon-shape,#mermaid-svg-xqMOexZd2F58LVS9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xqMOexZd2F58LVS9 .icon-shape p,#mermaid-svg-xqMOexZd2F58LVS9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xqMOexZd2F58LVS9 .icon-shape .label rect,#mermaid-svg-xqMOexZd2F58LVS9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xqMOexZd2F58LVS9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xqMOexZd2F58LVS9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xqMOexZd2F58LVS9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Web Page
DOM
Accessibility Tree
AI Snapshot
Element Ref
Browser Action

例如:

text 复制代码
button "Submit" [e5]
textbox "Username" [e6]
link "Settings" [e7]

然后 Agent 可以执行:

text 复制代码
click e5

为什么 Ref 很重要?

假设 Agent 连续执行:

text 复制代码
Snapshot
↓
Click
↓
Snapshot
↓
Type
↓
Snapshot
↓
Click

如果每一次 Snapshot 都重新生成完全不同的 ref:

text 复制代码
e1
e2
e3

模型很容易失去上下文。

因此,一个好的 Ref 系统应该尽可能保持稳定。

Playwright 的设计很值得借鉴:

Ref 与元素本身关联,而不是简单地维护一张全局 ID 表。

如果元素的:

text 复制代码
role
+
name

没有发生变化,就可以复用原来的 ref。

这实际上解决的是一个非常重要的问题:

如何让 LLM 在多轮交互中保持对页面元素的稳定认知。


五、Claude Code:为了拿到登录态,采用了三跳架构

Claude Code 选择了完全不同的路线。

它的目标不是创建一个新的 Browser,而是:

控制用户已经登录的 Chrome。

因此架构变成:
#mermaid-svg-VuUoy6fxsOBUg1fW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VuUoy6fxsOBUg1fW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VuUoy6fxsOBUg1fW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VuUoy6fxsOBUg1fW .error-icon{fill:#552222;}#mermaid-svg-VuUoy6fxsOBUg1fW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VuUoy6fxsOBUg1fW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VuUoy6fxsOBUg1fW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VuUoy6fxsOBUg1fW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VuUoy6fxsOBUg1fW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VuUoy6fxsOBUg1fW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VuUoy6fxsOBUg1fW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VuUoy6fxsOBUg1fW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VuUoy6fxsOBUg1fW .marker.cross{stroke:#333333;}#mermaid-svg-VuUoy6fxsOBUg1fW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VuUoy6fxsOBUg1fW p{margin:0;}#mermaid-svg-VuUoy6fxsOBUg1fW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VuUoy6fxsOBUg1fW .cluster-label text{fill:#333;}#mermaid-svg-VuUoy6fxsOBUg1fW .cluster-label span{color:#333;}#mermaid-svg-VuUoy6fxsOBUg1fW .cluster-label span p{background-color:transparent;}#mermaid-svg-VuUoy6fxsOBUg1fW .label text,#mermaid-svg-VuUoy6fxsOBUg1fW span{fill:#333;color:#333;}#mermaid-svg-VuUoy6fxsOBUg1fW .node rect,#mermaid-svg-VuUoy6fxsOBUg1fW .node circle,#mermaid-svg-VuUoy6fxsOBUg1fW .node ellipse,#mermaid-svg-VuUoy6fxsOBUg1fW .node polygon,#mermaid-svg-VuUoy6fxsOBUg1fW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VuUoy6fxsOBUg1fW .rough-node .label text,#mermaid-svg-VuUoy6fxsOBUg1fW .node .label text,#mermaid-svg-VuUoy6fxsOBUg1fW .image-shape .label,#mermaid-svg-VuUoy6fxsOBUg1fW .icon-shape .label{text-anchor:middle;}#mermaid-svg-VuUoy6fxsOBUg1fW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VuUoy6fxsOBUg1fW .rough-node .label,#mermaid-svg-VuUoy6fxsOBUg1fW .node .label,#mermaid-svg-VuUoy6fxsOBUg1fW .image-shape .label,#mermaid-svg-VuUoy6fxsOBUg1fW .icon-shape .label{text-align:center;}#mermaid-svg-VuUoy6fxsOBUg1fW .node.clickable{cursor:pointer;}#mermaid-svg-VuUoy6fxsOBUg1fW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VuUoy6fxsOBUg1fW .arrowheadPath{fill:#333333;}#mermaid-svg-VuUoy6fxsOBUg1fW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VuUoy6fxsOBUg1fW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VuUoy6fxsOBUg1fW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VuUoy6fxsOBUg1fW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VuUoy6fxsOBUg1fW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VuUoy6fxsOBUg1fW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VuUoy6fxsOBUg1fW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VuUoy6fxsOBUg1fW .cluster text{fill:#333;}#mermaid-svg-VuUoy6fxsOBUg1fW .cluster span{color:#333;}#mermaid-svg-VuUoy6fxsOBUg1fW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VuUoy6fxsOBUg1fW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VuUoy6fxsOBUg1fW rect.text{fill:none;stroke-width:0;}#mermaid-svg-VuUoy6fxsOBUg1fW .icon-shape,#mermaid-svg-VuUoy6fxsOBUg1fW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VuUoy6fxsOBUg1fW .icon-shape p,#mermaid-svg-VuUoy6fxsOBUg1fW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VuUoy6fxsOBUg1fW .icon-shape .label rect,#mermaid-svg-VuUoy6fxsOBUg1fW .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VuUoy6fxsOBUg1fW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VuUoy6fxsOBUg1fW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VuUoy6fxsOBUg1fW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} stdio
Unix Socket
Native Messaging
chrome.debugger
Claude Code
claude-in-chrome MCP
Native Host
Chrome Extension
User Chrome
Chrome Tab

为什么这么复杂?

因为:

text 复制代码
Claude Code
      ↓
Chrome

这条路通常走不通。

真正拥有 Chrome 内部调试权限的是 Extension。

所以必须:

text 复制代码
Claude Code
    ↓
MCP
    ↓
Native Host
    ↓
Chrome Extension
    ↓
chrome.debugger
    ↓
Chrome

也就是说:

这三跳不是为了炫技,而是为了跨越 Chrome 的安全边界。


六、Claude Code 的优势与代价

Claude Code 的优势非常明显:

优势

  • 可以使用用户已经登录的 Chrome
  • 可以访问真实 Web App
  • Browser Automation 与 Agent 深度集成
  • 有完整的 Browser Tool 集合

例如:

text 复制代码
read_page
get_page_text
find
form_input
computer
navigate
javascript_tool
screenshot
tabs
...

但它的一个架构代价也非常明显:

Browser Tool Layer 与 Extension Protocol 耦合比较紧。

它使用自己的:

text 复制代码
execute_tool

协议。

因此:
#mermaid-svg-zU2aIZScYHADGEHb{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zU2aIZScYHADGEHb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zU2aIZScYHADGEHb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zU2aIZScYHADGEHb .error-icon{fill:#552222;}#mermaid-svg-zU2aIZScYHADGEHb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zU2aIZScYHADGEHb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zU2aIZScYHADGEHb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zU2aIZScYHADGEHb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zU2aIZScYHADGEHb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zU2aIZScYHADGEHb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zU2aIZScYHADGEHb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zU2aIZScYHADGEHb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zU2aIZScYHADGEHb .marker.cross{stroke:#333333;}#mermaid-svg-zU2aIZScYHADGEHb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zU2aIZScYHADGEHb p{margin:0;}#mermaid-svg-zU2aIZScYHADGEHb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zU2aIZScYHADGEHb .cluster-label text{fill:#333;}#mermaid-svg-zU2aIZScYHADGEHb .cluster-label span{color:#333;}#mermaid-svg-zU2aIZScYHADGEHb .cluster-label span p{background-color:transparent;}#mermaid-svg-zU2aIZScYHADGEHb .label text,#mermaid-svg-zU2aIZScYHADGEHb span{fill:#333;color:#333;}#mermaid-svg-zU2aIZScYHADGEHb .node rect,#mermaid-svg-zU2aIZScYHADGEHb .node circle,#mermaid-svg-zU2aIZScYHADGEHb .node ellipse,#mermaid-svg-zU2aIZScYHADGEHb .node polygon,#mermaid-svg-zU2aIZScYHADGEHb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zU2aIZScYHADGEHb .rough-node .label text,#mermaid-svg-zU2aIZScYHADGEHb .node .label text,#mermaid-svg-zU2aIZScYHADGEHb .image-shape .label,#mermaid-svg-zU2aIZScYHADGEHb .icon-shape .label{text-anchor:middle;}#mermaid-svg-zU2aIZScYHADGEHb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zU2aIZScYHADGEHb .rough-node .label,#mermaid-svg-zU2aIZScYHADGEHb .node .label,#mermaid-svg-zU2aIZScYHADGEHb .image-shape .label,#mermaid-svg-zU2aIZScYHADGEHb .icon-shape .label{text-align:center;}#mermaid-svg-zU2aIZScYHADGEHb .node.clickable{cursor:pointer;}#mermaid-svg-zU2aIZScYHADGEHb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zU2aIZScYHADGEHb .arrowheadPath{fill:#333333;}#mermaid-svg-zU2aIZScYHADGEHb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zU2aIZScYHADGEHb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zU2aIZScYHADGEHb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zU2aIZScYHADGEHb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zU2aIZScYHADGEHb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zU2aIZScYHADGEHb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zU2aIZScYHADGEHb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zU2aIZScYHADGEHb .cluster text{fill:#333;}#mermaid-svg-zU2aIZScYHADGEHb .cluster span{color:#333;}#mermaid-svg-zU2aIZScYHADGEHb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zU2aIZScYHADGEHb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zU2aIZScYHADGEHb rect.text{fill:none;stroke-width:0;}#mermaid-svg-zU2aIZScYHADGEHb .icon-shape,#mermaid-svg-zU2aIZScYHADGEHb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zU2aIZScYHADGEHb .icon-shape p,#mermaid-svg-zU2aIZScYHADGEHb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zU2aIZScYHADGEHb .icon-shape .label rect,#mermaid-svg-zU2aIZScYHADGEHb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zU2aIZScYHADGEHb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zU2aIZScYHADGEHb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zU2aIZScYHADGEHb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Claude Browser Tools
execute_tool Protocol
Chrome Extension
Chrome

这种设计当然可以工作。

但如果未来需要增加:

text 复制代码
Remote Browser
Managed Browser
Playwright Browser
Another Extension

就需要继续考虑这些不同 Transport 如何适配 Tool Layer。

这正是后面 OpenClaw 设计值得关注的地方。


七、Cursor:不接管用户 Chrome,而是自己拥有一个 Browser

Cursor 采取了第三条路线:

我不控制你的 Chrome,我直接在 IDE 里提供一个 Browser。

架构:
#mermaid-svg-EMkTabIe4g5zpv2C{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EMkTabIe4g5zpv2C .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EMkTabIe4g5zpv2C .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EMkTabIe4g5zpv2C .error-icon{fill:#552222;}#mermaid-svg-EMkTabIe4g5zpv2C .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EMkTabIe4g5zpv2C .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EMkTabIe4g5zpv2C .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EMkTabIe4g5zpv2C .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EMkTabIe4g5zpv2C .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EMkTabIe4g5zpv2C .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EMkTabIe4g5zpv2C .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EMkTabIe4g5zpv2C .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EMkTabIe4g5zpv2C .marker.cross{stroke:#333333;}#mermaid-svg-EMkTabIe4g5zpv2C svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EMkTabIe4g5zpv2C p{margin:0;}#mermaid-svg-EMkTabIe4g5zpv2C .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-EMkTabIe4g5zpv2C .cluster-label text{fill:#333;}#mermaid-svg-EMkTabIe4g5zpv2C .cluster-label span{color:#333;}#mermaid-svg-EMkTabIe4g5zpv2C .cluster-label span p{background-color:transparent;}#mermaid-svg-EMkTabIe4g5zpv2C .label text,#mermaid-svg-EMkTabIe4g5zpv2C span{fill:#333;color:#333;}#mermaid-svg-EMkTabIe4g5zpv2C .node rect,#mermaid-svg-EMkTabIe4g5zpv2C .node circle,#mermaid-svg-EMkTabIe4g5zpv2C .node ellipse,#mermaid-svg-EMkTabIe4g5zpv2C .node polygon,#mermaid-svg-EMkTabIe4g5zpv2C .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-EMkTabIe4g5zpv2C .rough-node .label text,#mermaid-svg-EMkTabIe4g5zpv2C .node .label text,#mermaid-svg-EMkTabIe4g5zpv2C .image-shape .label,#mermaid-svg-EMkTabIe4g5zpv2C .icon-shape .label{text-anchor:middle;}#mermaid-svg-EMkTabIe4g5zpv2C .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-EMkTabIe4g5zpv2C .rough-node .label,#mermaid-svg-EMkTabIe4g5zpv2C .node .label,#mermaid-svg-EMkTabIe4g5zpv2C .image-shape .label,#mermaid-svg-EMkTabIe4g5zpv2C .icon-shape .label{text-align:center;}#mermaid-svg-EMkTabIe4g5zpv2C .node.clickable{cursor:pointer;}#mermaid-svg-EMkTabIe4g5zpv2C .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-EMkTabIe4g5zpv2C .arrowheadPath{fill:#333333;}#mermaid-svg-EMkTabIe4g5zpv2C .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-EMkTabIe4g5zpv2C .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-EMkTabIe4g5zpv2C .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EMkTabIe4g5zpv2C .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-EMkTabIe4g5zpv2C .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EMkTabIe4g5zpv2C .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-EMkTabIe4g5zpv2C .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-EMkTabIe4g5zpv2C .cluster text{fill:#333;}#mermaid-svg-EMkTabIe4g5zpv2C .cluster span{color:#333;}#mermaid-svg-EMkTabIe4g5zpv2C div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-EMkTabIe4g5zpv2C .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-EMkTabIe4g5zpv2C rect.text{fill:none;stroke-width:0;}#mermaid-svg-EMkTabIe4g5zpv2C .icon-shape,#mermaid-svg-EMkTabIe4g5zpv2C .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EMkTabIe4g5zpv2C .icon-shape p,#mermaid-svg-EMkTabIe4g5zpv2C .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-EMkTabIe4g5zpv2C .icon-shape .label rect,#mermaid-svg-EMkTabIe4g5zpv2C .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EMkTabIe4g5zpv2C .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-EMkTabIe4g5zpv2C .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-EMkTabIe4g5zpv2C :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} MCP
CDP
Inject Script
Cursor Agent
Browser Automation Extension
Electron WebView
Web Page

这里有一个非常重要的区别:

text 复制代码
Cursor Browser
      ≠
User Chrome

Cursor 的 Browser 是 IDE 自己控制的 WebView。

因此:

  • 可以深度集成 IDE
  • 不需要额外安装 Chrome
  • 可以控制 Browser 生命周期
  • 可以持久化 Browser Profile

但:

无法天然复用用户日常 Chrome 的登录态。


八、Cursor 最值得学习的其实不是 Browser,而是 Tool Design

Cursor 的 Browser Tool 设计非常值得 Coding Agent 借鉴。

它不是使用一个巨大的:

text 复制代码
computer()

而是拆成:

text 复制代码
browser_navigate
browser_snapshot
browser_click
browser_mouse_click_xy
browser_type
browser_fill
browser_select_option
browser_press_key
browser_scroll
browser_drag
browser_get_bounding_box
browser_highlight
browser_tabs
browser_cdp
browser_take_screenshot
browser_lock

这体现了一个很重要的 Agent Tool 设计原则:

Tool Schema 越清晰、职责越单一,模型越容易正确调用。


九、Cursor 的 Stale Ref 设计

Cursor 在 Ref 上又做了一层保护。

例如:

text 复制代码
ref = e5
element = "Submit button"

执行的时候不仅检查:

text 复制代码
e5

还会检查:

text 复制代码
当前 e5
是否仍然是 Submit button?

如果页面发生了变化:

text 复制代码
Stale element reference

然后要求:

text 复制代码
Take a new snapshot.

这个设计解决了一个非常现实的问题:

Snapshot 没过期,不代表 DOM 没发生变化。

例如:

text 复制代码
React Re-render
SPA State Update
DOM Reuse
Modal Change
Dynamic Content

都可能导致:

text 复制代码
old ref
    ↓
different element

因此,一个更可靠的 Ref 系统应该是:

text 复制代码
Ref
+
Semantic Validation

而不是只有:

text 复制代码
Ref

十、Cursor 的另一个优秀设计:Action + Screenshot

Cursor 很多操作支持:

text 复制代码
take_screenshot_afterwards

因此:
#mermaid-svg-DpT6VDmL0WnQJaqs{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DpT6VDmL0WnQJaqs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DpT6VDmL0WnQJaqs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DpT6VDmL0WnQJaqs .error-icon{fill:#552222;}#mermaid-svg-DpT6VDmL0WnQJaqs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DpT6VDmL0WnQJaqs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DpT6VDmL0WnQJaqs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DpT6VDmL0WnQJaqs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DpT6VDmL0WnQJaqs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DpT6VDmL0WnQJaqs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DpT6VDmL0WnQJaqs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DpT6VDmL0WnQJaqs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DpT6VDmL0WnQJaqs .marker.cross{stroke:#333333;}#mermaid-svg-DpT6VDmL0WnQJaqs svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DpT6VDmL0WnQJaqs p{margin:0;}#mermaid-svg-DpT6VDmL0WnQJaqs .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DpT6VDmL0WnQJaqs .cluster-label text{fill:#333;}#mermaid-svg-DpT6VDmL0WnQJaqs .cluster-label span{color:#333;}#mermaid-svg-DpT6VDmL0WnQJaqs .cluster-label span p{background-color:transparent;}#mermaid-svg-DpT6VDmL0WnQJaqs .label text,#mermaid-svg-DpT6VDmL0WnQJaqs span{fill:#333;color:#333;}#mermaid-svg-DpT6VDmL0WnQJaqs .node rect,#mermaid-svg-DpT6VDmL0WnQJaqs .node circle,#mermaid-svg-DpT6VDmL0WnQJaqs .node ellipse,#mermaid-svg-DpT6VDmL0WnQJaqs .node polygon,#mermaid-svg-DpT6VDmL0WnQJaqs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DpT6VDmL0WnQJaqs .rough-node .label text,#mermaid-svg-DpT6VDmL0WnQJaqs .node .label text,#mermaid-svg-DpT6VDmL0WnQJaqs .image-shape .label,#mermaid-svg-DpT6VDmL0WnQJaqs .icon-shape .label{text-anchor:middle;}#mermaid-svg-DpT6VDmL0WnQJaqs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DpT6VDmL0WnQJaqs .rough-node .label,#mermaid-svg-DpT6VDmL0WnQJaqs .node .label,#mermaid-svg-DpT6VDmL0WnQJaqs .image-shape .label,#mermaid-svg-DpT6VDmL0WnQJaqs .icon-shape .label{text-align:center;}#mermaid-svg-DpT6VDmL0WnQJaqs .node.clickable{cursor:pointer;}#mermaid-svg-DpT6VDmL0WnQJaqs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DpT6VDmL0WnQJaqs .arrowheadPath{fill:#333333;}#mermaid-svg-DpT6VDmL0WnQJaqs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DpT6VDmL0WnQJaqs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DpT6VDmL0WnQJaqs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DpT6VDmL0WnQJaqs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DpT6VDmL0WnQJaqs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DpT6VDmL0WnQJaqs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DpT6VDmL0WnQJaqs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DpT6VDmL0WnQJaqs .cluster text{fill:#333;}#mermaid-svg-DpT6VDmL0WnQJaqs .cluster span{color:#333;}#mermaid-svg-DpT6VDmL0WnQJaqs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DpT6VDmL0WnQJaqs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DpT6VDmL0WnQJaqs rect.text{fill:none;stroke-width:0;}#mermaid-svg-DpT6VDmL0WnQJaqs .icon-shape,#mermaid-svg-DpT6VDmL0WnQJaqs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DpT6VDmL0WnQJaqs .icon-shape p,#mermaid-svg-DpT6VDmL0WnQJaqs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DpT6VDmL0WnQJaqs .icon-shape .label rect,#mermaid-svg-DpT6VDmL0WnQJaqs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DpT6VDmL0WnQJaqs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DpT6VDmL0WnQJaqs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DpT6VDmL0WnQJaqs :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Browser Action
Screenshot
Visual Verification

而不是:
#mermaid-svg-uvA0lieYLFgljmTU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uvA0lieYLFgljmTU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uvA0lieYLFgljmTU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uvA0lieYLFgljmTU .error-icon{fill:#552222;}#mermaid-svg-uvA0lieYLFgljmTU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uvA0lieYLFgljmTU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uvA0lieYLFgljmTU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uvA0lieYLFgljmTU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uvA0lieYLFgljmTU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uvA0lieYLFgljmTU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uvA0lieYLFgljmTU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uvA0lieYLFgljmTU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uvA0lieYLFgljmTU .marker.cross{stroke:#333333;}#mermaid-svg-uvA0lieYLFgljmTU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uvA0lieYLFgljmTU p{margin:0;}#mermaid-svg-uvA0lieYLFgljmTU .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uvA0lieYLFgljmTU .cluster-label text{fill:#333;}#mermaid-svg-uvA0lieYLFgljmTU .cluster-label span{color:#333;}#mermaid-svg-uvA0lieYLFgljmTU .cluster-label span p{background-color:transparent;}#mermaid-svg-uvA0lieYLFgljmTU .label text,#mermaid-svg-uvA0lieYLFgljmTU span{fill:#333;color:#333;}#mermaid-svg-uvA0lieYLFgljmTU .node rect,#mermaid-svg-uvA0lieYLFgljmTU .node circle,#mermaid-svg-uvA0lieYLFgljmTU .node ellipse,#mermaid-svg-uvA0lieYLFgljmTU .node polygon,#mermaid-svg-uvA0lieYLFgljmTU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uvA0lieYLFgljmTU .rough-node .label text,#mermaid-svg-uvA0lieYLFgljmTU .node .label text,#mermaid-svg-uvA0lieYLFgljmTU .image-shape .label,#mermaid-svg-uvA0lieYLFgljmTU .icon-shape .label{text-anchor:middle;}#mermaid-svg-uvA0lieYLFgljmTU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uvA0lieYLFgljmTU .rough-node .label,#mermaid-svg-uvA0lieYLFgljmTU .node .label,#mermaid-svg-uvA0lieYLFgljmTU .image-shape .label,#mermaid-svg-uvA0lieYLFgljmTU .icon-shape .label{text-align:center;}#mermaid-svg-uvA0lieYLFgljmTU .node.clickable{cursor:pointer;}#mermaid-svg-uvA0lieYLFgljmTU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uvA0lieYLFgljmTU .arrowheadPath{fill:#333333;}#mermaid-svg-uvA0lieYLFgljmTU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uvA0lieYLFgljmTU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uvA0lieYLFgljmTU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uvA0lieYLFgljmTU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uvA0lieYLFgljmTU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uvA0lieYLFgljmTU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uvA0lieYLFgljmTU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uvA0lieYLFgljmTU .cluster text{fill:#333;}#mermaid-svg-uvA0lieYLFgljmTU .cluster span{color:#333;}#mermaid-svg-uvA0lieYLFgljmTU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uvA0lieYLFgljmTU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uvA0lieYLFgljmTU rect.text{fill:none;stroke-width:0;}#mermaid-svg-uvA0lieYLFgljmTU .icon-shape,#mermaid-svg-uvA0lieYLFgljmTU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uvA0lieYLFgljmTU .icon-shape p,#mermaid-svg-uvA0lieYLFgljmTU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uvA0lieYLFgljmTU .icon-shape .label rect,#mermaid-svg-uvA0lieYLFgljmTU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uvA0lieYLFgljmTU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uvA0lieYLFgljmTU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uvA0lieYLFgljmTU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Browser Action
Tool Result
LLM
Screenshot
Verification

第一种方式明显减少了一次 Agent 往返。

更重要的是,它把:

Action 和 Verification

放到了一个非常紧密的闭环中。


十一、VS Code:一个非常好的反面教材

VS Code 本身并不是一个 Browser Automation Framework。

它提供了:

  • Simple Browser
  • js-debug

但这两个东西恰好可以帮助我们理解 Browser Automation 的边界。


Simple Browser:能显示,不代表能控制

Simple Browser 本质上是:
#mermaid-svg-GIWN7IHQS6bCbeux{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GIWN7IHQS6bCbeux .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GIWN7IHQS6bCbeux .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GIWN7IHQS6bCbeux .error-icon{fill:#552222;}#mermaid-svg-GIWN7IHQS6bCbeux .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GIWN7IHQS6bCbeux .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GIWN7IHQS6bCbeux .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GIWN7IHQS6bCbeux .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GIWN7IHQS6bCbeux .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GIWN7IHQS6bCbeux .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GIWN7IHQS6bCbeux .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GIWN7IHQS6bCbeux .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GIWN7IHQS6bCbeux .marker.cross{stroke:#333333;}#mermaid-svg-GIWN7IHQS6bCbeux svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GIWN7IHQS6bCbeux p{margin:0;}#mermaid-svg-GIWN7IHQS6bCbeux .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GIWN7IHQS6bCbeux .cluster-label text{fill:#333;}#mermaid-svg-GIWN7IHQS6bCbeux .cluster-label span{color:#333;}#mermaid-svg-GIWN7IHQS6bCbeux .cluster-label span p{background-color:transparent;}#mermaid-svg-GIWN7IHQS6bCbeux .label text,#mermaid-svg-GIWN7IHQS6bCbeux span{fill:#333;color:#333;}#mermaid-svg-GIWN7IHQS6bCbeux .node rect,#mermaid-svg-GIWN7IHQS6bCbeux .node circle,#mermaid-svg-GIWN7IHQS6bCbeux .node ellipse,#mermaid-svg-GIWN7IHQS6bCbeux .node polygon,#mermaid-svg-GIWN7IHQS6bCbeux .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GIWN7IHQS6bCbeux .rough-node .label text,#mermaid-svg-GIWN7IHQS6bCbeux .node .label text,#mermaid-svg-GIWN7IHQS6bCbeux .image-shape .label,#mermaid-svg-GIWN7IHQS6bCbeux .icon-shape .label{text-anchor:middle;}#mermaid-svg-GIWN7IHQS6bCbeux .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GIWN7IHQS6bCbeux .rough-node .label,#mermaid-svg-GIWN7IHQS6bCbeux .node .label,#mermaid-svg-GIWN7IHQS6bCbeux .image-shape .label,#mermaid-svg-GIWN7IHQS6bCbeux .icon-shape .label{text-align:center;}#mermaid-svg-GIWN7IHQS6bCbeux .node.clickable{cursor:pointer;}#mermaid-svg-GIWN7IHQS6bCbeux .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GIWN7IHQS6bCbeux .arrowheadPath{fill:#333333;}#mermaid-svg-GIWN7IHQS6bCbeux .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GIWN7IHQS6bCbeux .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GIWN7IHQS6bCbeux .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GIWN7IHQS6bCbeux .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GIWN7IHQS6bCbeux .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GIWN7IHQS6bCbeux .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GIWN7IHQS6bCbeux .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GIWN7IHQS6bCbeux .cluster text{fill:#333;}#mermaid-svg-GIWN7IHQS6bCbeux .cluster span{color:#333;}#mermaid-svg-GIWN7IHQS6bCbeux div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GIWN7IHQS6bCbeux .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GIWN7IHQS6bCbeux rect.text{fill:none;stroke-width:0;}#mermaid-svg-GIWN7IHQS6bCbeux .icon-shape,#mermaid-svg-GIWN7IHQS6bCbeux .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GIWN7IHQS6bCbeux .icon-shape p,#mermaid-svg-GIWN7IHQS6bCbeux .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GIWN7IHQS6bCbeux .icon-shape .label rect,#mermaid-svg-GIWN7IHQS6bCbeux .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GIWN7IHQS6bCbeux .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GIWN7IHQS6bCbeux .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GIWN7IHQS6bCbeux :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} VS Code
WebView
IFrame
Web Page

它可以:

展示网页。

但是:

展示网页和自动化网页完全是两回事。

跨源隔离意味着扩展宿主不能随意读取 iframe 内部 DOM。

因此:

text 复制代码
Web Preview
      ≠
Browser Automation

这是 Browser Agent 架构设计中非常重要的一条原则。


十二、OpenCode:不自己造 Browser

OpenCode 的选择非常工程化:

如果 Browser Automation 不是你的核心差异化能力,就不要自己实现。

它自己提供:

text 复制代码
read
edit
write
grep
glob
lsp
bash
webfetch
websearch
task
skill
...

而 Browser Automation 则通过:

Playwright MCP

来实现。

架构:
#mermaid-svg-TA9XevGrzittpy7r{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TA9XevGrzittpy7r .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TA9XevGrzittpy7r .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TA9XevGrzittpy7r .error-icon{fill:#552222;}#mermaid-svg-TA9XevGrzittpy7r .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TA9XevGrzittpy7r .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TA9XevGrzittpy7r .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TA9XevGrzittpy7r .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TA9XevGrzittpy7r .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TA9XevGrzittpy7r .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TA9XevGrzittpy7r .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TA9XevGrzittpy7r .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TA9XevGrzittpy7r .marker.cross{stroke:#333333;}#mermaid-svg-TA9XevGrzittpy7r svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TA9XevGrzittpy7r p{margin:0;}#mermaid-svg-TA9XevGrzittpy7r .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TA9XevGrzittpy7r .cluster-label text{fill:#333;}#mermaid-svg-TA9XevGrzittpy7r .cluster-label span{color:#333;}#mermaid-svg-TA9XevGrzittpy7r .cluster-label span p{background-color:transparent;}#mermaid-svg-TA9XevGrzittpy7r .label text,#mermaid-svg-TA9XevGrzittpy7r span{fill:#333;color:#333;}#mermaid-svg-TA9XevGrzittpy7r .node rect,#mermaid-svg-TA9XevGrzittpy7r .node circle,#mermaid-svg-TA9XevGrzittpy7r .node ellipse,#mermaid-svg-TA9XevGrzittpy7r .node polygon,#mermaid-svg-TA9XevGrzittpy7r .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TA9XevGrzittpy7r .rough-node .label text,#mermaid-svg-TA9XevGrzittpy7r .node .label text,#mermaid-svg-TA9XevGrzittpy7r .image-shape .label,#mermaid-svg-TA9XevGrzittpy7r .icon-shape .label{text-anchor:middle;}#mermaid-svg-TA9XevGrzittpy7r .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TA9XevGrzittpy7r .rough-node .label,#mermaid-svg-TA9XevGrzittpy7r .node .label,#mermaid-svg-TA9XevGrzittpy7r .image-shape .label,#mermaid-svg-TA9XevGrzittpy7r .icon-shape .label{text-align:center;}#mermaid-svg-TA9XevGrzittpy7r .node.clickable{cursor:pointer;}#mermaid-svg-TA9XevGrzittpy7r .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TA9XevGrzittpy7r .arrowheadPath{fill:#333333;}#mermaid-svg-TA9XevGrzittpy7r .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TA9XevGrzittpy7r .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TA9XevGrzittpy7r .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TA9XevGrzittpy7r .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TA9XevGrzittpy7r .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TA9XevGrzittpy7r .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TA9XevGrzittpy7r .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TA9XevGrzittpy7r .cluster text{fill:#333;}#mermaid-svg-TA9XevGrzittpy7r .cluster span{color:#333;}#mermaid-svg-TA9XevGrzittpy7r div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TA9XevGrzittpy7r .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TA9XevGrzittpy7r rect.text{fill:none;stroke-width:0;}#mermaid-svg-TA9XevGrzittpy7r .icon-shape,#mermaid-svg-TA9XevGrzittpy7r .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TA9XevGrzittpy7r .icon-shape p,#mermaid-svg-TA9XevGrzittpy7r .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TA9XevGrzittpy7r .icon-shape .label rect,#mermaid-svg-TA9XevGrzittpy7r .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TA9XevGrzittpy7r .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TA9XevGrzittpy7r .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TA9XevGrzittpy7r :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} OpenCode
Playwright MCP
Playwright
Browser
Web Page

这个方案的优势:

  • 实现成本低
  • 复用成熟 Browser Automation
  • OpenCode 不需要维护 Browser Engine

代价:

  • 集成度较低
  • Tool Result 依赖 MCP
  • Browser 权限依赖 MCP
  • 用户需要配置 MCP
  • Browser Profile 与 Agent 本身相对独立

因此它实际上回答了一个非常重要的工程问题:

什么时候应该自己造?

答案是:

只有当 Browser Automation 本身就是你的产品差异化能力时,才值得自己造。


十三、OpenClaw:最值得研究的 Browser Architecture

如果这六个方案里面只选择一个重点研究,我认为:

OpenClaw 最值得借鉴。

不是因为它 Tool 最多,而是因为它解决了一个非常关键的架构问题:

不同 Browser Source,能不能共享同一套 Browser Tool Layer?

OpenClaw 给出的答案是:

可以。


十四、OpenClaw 的三个 Browser Profile

OpenClaw 当前的 Browser 模型支持不同类型的 Browser Profile,包括托管 Browser、已有 Chrome Session 和远程 CDP 等。官方文档也明确区分了 openclawuserchrome 三种典型模式。

可以把它理解成:
#mermaid-svg-KiTcoWRx1EIzahAP{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KiTcoWRx1EIzahAP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KiTcoWRx1EIzahAP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KiTcoWRx1EIzahAP .error-icon{fill:#552222;}#mermaid-svg-KiTcoWRx1EIzahAP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KiTcoWRx1EIzahAP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KiTcoWRx1EIzahAP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KiTcoWRx1EIzahAP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KiTcoWRx1EIzahAP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KiTcoWRx1EIzahAP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KiTcoWRx1EIzahAP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KiTcoWRx1EIzahAP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KiTcoWRx1EIzahAP .marker.cross{stroke:#333333;}#mermaid-svg-KiTcoWRx1EIzahAP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KiTcoWRx1EIzahAP p{margin:0;}#mermaid-svg-KiTcoWRx1EIzahAP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KiTcoWRx1EIzahAP .cluster-label text{fill:#333;}#mermaid-svg-KiTcoWRx1EIzahAP .cluster-label span{color:#333;}#mermaid-svg-KiTcoWRx1EIzahAP .cluster-label span p{background-color:transparent;}#mermaid-svg-KiTcoWRx1EIzahAP .label text,#mermaid-svg-KiTcoWRx1EIzahAP span{fill:#333;color:#333;}#mermaid-svg-KiTcoWRx1EIzahAP .node rect,#mermaid-svg-KiTcoWRx1EIzahAP .node circle,#mermaid-svg-KiTcoWRx1EIzahAP .node ellipse,#mermaid-svg-KiTcoWRx1EIzahAP .node polygon,#mermaid-svg-KiTcoWRx1EIzahAP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KiTcoWRx1EIzahAP .rough-node .label text,#mermaid-svg-KiTcoWRx1EIzahAP .node .label text,#mermaid-svg-KiTcoWRx1EIzahAP .image-shape .label,#mermaid-svg-KiTcoWRx1EIzahAP .icon-shape .label{text-anchor:middle;}#mermaid-svg-KiTcoWRx1EIzahAP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KiTcoWRx1EIzahAP .rough-node .label,#mermaid-svg-KiTcoWRx1EIzahAP .node .label,#mermaid-svg-KiTcoWRx1EIzahAP .image-shape .label,#mermaid-svg-KiTcoWRx1EIzahAP .icon-shape .label{text-align:center;}#mermaid-svg-KiTcoWRx1EIzahAP .node.clickable{cursor:pointer;}#mermaid-svg-KiTcoWRx1EIzahAP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KiTcoWRx1EIzahAP .arrowheadPath{fill:#333333;}#mermaid-svg-KiTcoWRx1EIzahAP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KiTcoWRx1EIzahAP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KiTcoWRx1EIzahAP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KiTcoWRx1EIzahAP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KiTcoWRx1EIzahAP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KiTcoWRx1EIzahAP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KiTcoWRx1EIzahAP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KiTcoWRx1EIzahAP .cluster text{fill:#333;}#mermaid-svg-KiTcoWRx1EIzahAP .cluster span{color:#333;}#mermaid-svg-KiTcoWRx1EIzahAP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KiTcoWRx1EIzahAP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KiTcoWRx1EIzahAP rect.text{fill:none;stroke-width:0;}#mermaid-svg-KiTcoWRx1EIzahAP .icon-shape,#mermaid-svg-KiTcoWRx1EIzahAP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KiTcoWRx1EIzahAP .icon-shape p,#mermaid-svg-KiTcoWRx1EIzahAP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KiTcoWRx1EIzahAP .icon-shape .label rect,#mermaid-svg-KiTcoWRx1EIzahAP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KiTcoWRx1EIzahAP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KiTcoWRx1EIzahAP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KiTcoWRx1EIzahAP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} OpenClaw Agent
openclaw
user
chrome
Managed Browser
User Chrome

Chrome DevTools MCP
User Chrome

Chrome Extension

openclaw

独立、隔离的 Browser。

text 复制代码
Agent
 ↓
OpenClaw Browser

不需要扩展。

适合:

  • 自动化测试
  • Web Scraping
  • 普通网页任务
  • 不需要用户登录态的任务

user

连接用户真实 Chrome Session。

优势:

可以复用登录状态。

但首次连接可能需要用户在电脑前批准 Remote Debugging。


chrome

通过 Chrome Extension 控制用户已经登录的 Chrome。

这是非常有意思的一条路线。

OpenClaw 官方文档明确说明,Chrome Extension 通过 chrome.debugger 控制已经登录的 Chrome,并通过本地 loopback WebSocket relay 与 Browser Control Service 通信。


十五、OpenClaw 最核心的设计:CDP Relay

这是整个调研里我认为最值得借鉴的架构设计

架构:
#mermaid-svg-Ykh22yLsWGRTRyw2{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ykh22yLsWGRTRyw2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ykh22yLsWGRTRyw2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ykh22yLsWGRTRyw2 .error-icon{fill:#552222;}#mermaid-svg-Ykh22yLsWGRTRyw2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ykh22yLsWGRTRyw2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ykh22yLsWGRTRyw2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ykh22yLsWGRTRyw2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ykh22yLsWGRTRyw2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ykh22yLsWGRTRyw2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ykh22yLsWGRTRyw2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ykh22yLsWGRTRyw2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ykh22yLsWGRTRyw2 .marker.cross{stroke:#333333;}#mermaid-svg-Ykh22yLsWGRTRyw2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ykh22yLsWGRTRyw2 p{margin:0;}#mermaid-svg-Ykh22yLsWGRTRyw2 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Ykh22yLsWGRTRyw2 .cluster-label text{fill:#333;}#mermaid-svg-Ykh22yLsWGRTRyw2 .cluster-label span{color:#333;}#mermaid-svg-Ykh22yLsWGRTRyw2 .cluster-label span p{background-color:transparent;}#mermaid-svg-Ykh22yLsWGRTRyw2 .label text,#mermaid-svg-Ykh22yLsWGRTRyw2 span{fill:#333;color:#333;}#mermaid-svg-Ykh22yLsWGRTRyw2 .node rect,#mermaid-svg-Ykh22yLsWGRTRyw2 .node circle,#mermaid-svg-Ykh22yLsWGRTRyw2 .node ellipse,#mermaid-svg-Ykh22yLsWGRTRyw2 .node polygon,#mermaid-svg-Ykh22yLsWGRTRyw2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ykh22yLsWGRTRyw2 .rough-node .label text,#mermaid-svg-Ykh22yLsWGRTRyw2 .node .label text,#mermaid-svg-Ykh22yLsWGRTRyw2 .image-shape .label,#mermaid-svg-Ykh22yLsWGRTRyw2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Ykh22yLsWGRTRyw2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Ykh22yLsWGRTRyw2 .rough-node .label,#mermaid-svg-Ykh22yLsWGRTRyw2 .node .label,#mermaid-svg-Ykh22yLsWGRTRyw2 .image-shape .label,#mermaid-svg-Ykh22yLsWGRTRyw2 .icon-shape .label{text-align:center;}#mermaid-svg-Ykh22yLsWGRTRyw2 .node.clickable{cursor:pointer;}#mermaid-svg-Ykh22yLsWGRTRyw2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Ykh22yLsWGRTRyw2 .arrowheadPath{fill:#333333;}#mermaid-svg-Ykh22yLsWGRTRyw2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Ykh22yLsWGRTRyw2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Ykh22yLsWGRTRyw2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ykh22yLsWGRTRyw2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Ykh22yLsWGRTRyw2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ykh22yLsWGRTRyw2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Ykh22yLsWGRTRyw2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ykh22yLsWGRTRyw2 .cluster text{fill:#333;}#mermaid-svg-Ykh22yLsWGRTRyw2 .cluster span{color:#333;}#mermaid-svg-Ykh22yLsWGRTRyw2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Ykh22yLsWGRTRyw2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ykh22yLsWGRTRyw2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Ykh22yLsWGRTRyw2 .icon-shape,#mermaid-svg-Ykh22yLsWGRTRyw2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ykh22yLsWGRTRyw2 .icon-shape p,#mermaid-svg-Ykh22yLsWGRTRyw2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Ykh22yLsWGRTRyw2 .icon-shape .label rect,#mermaid-svg-Ykh22yLsWGRTRyw2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ykh22yLsWGRTRyw2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ykh22yLsWGRTRyw2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ykh22yLsWGRTRyw2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} CDP over WebSocket
WebSocket
chrome.debugger
Agent / CLI / MCP
Browser Control Service
CDP Relay
Chrome Extension
User Chrome
Chrome Tab

关键点在于:

Relay 对上层提供标准 CDP Endpoint。

OpenClaw 官方文档目前也明确描述了这一结构:控制服务启动 loopback relay,relay 对 OpenClaw 提供 CDP endpoint,同时通过 WebSocket 与 MV3 Extension 通信。

因此对于上层来说:

text 复制代码
Playwright
      ↓
connectOverCDP()
      ↓
CDP Relay
      ↓
Chrome Extension
      ↓
chrome.debugger
      ↓
User Chrome

Playwright 并不需要知道:

后面到底是一个真实 CDP Browser,还是一个 Chrome Extension。


十六、为什么 CDP Relay 如此重要?

假设我们有三个 Browser:

text 复制代码
Managed Browser
User Chrome
Remote Browser

传统设计可能是:
#mermaid-svg-Idy8yVyFljg65Wgh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Idy8yVyFljg65Wgh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Idy8yVyFljg65Wgh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Idy8yVyFljg65Wgh .error-icon{fill:#552222;}#mermaid-svg-Idy8yVyFljg65Wgh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Idy8yVyFljg65Wgh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Idy8yVyFljg65Wgh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Idy8yVyFljg65Wgh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Idy8yVyFljg65Wgh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Idy8yVyFljg65Wgh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Idy8yVyFljg65Wgh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Idy8yVyFljg65Wgh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Idy8yVyFljg65Wgh .marker.cross{stroke:#333333;}#mermaid-svg-Idy8yVyFljg65Wgh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Idy8yVyFljg65Wgh p{margin:0;}#mermaid-svg-Idy8yVyFljg65Wgh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Idy8yVyFljg65Wgh .cluster-label text{fill:#333;}#mermaid-svg-Idy8yVyFljg65Wgh .cluster-label span{color:#333;}#mermaid-svg-Idy8yVyFljg65Wgh .cluster-label span p{background-color:transparent;}#mermaid-svg-Idy8yVyFljg65Wgh .label text,#mermaid-svg-Idy8yVyFljg65Wgh span{fill:#333;color:#333;}#mermaid-svg-Idy8yVyFljg65Wgh .node rect,#mermaid-svg-Idy8yVyFljg65Wgh .node circle,#mermaid-svg-Idy8yVyFljg65Wgh .node ellipse,#mermaid-svg-Idy8yVyFljg65Wgh .node polygon,#mermaid-svg-Idy8yVyFljg65Wgh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Idy8yVyFljg65Wgh .rough-node .label text,#mermaid-svg-Idy8yVyFljg65Wgh .node .label text,#mermaid-svg-Idy8yVyFljg65Wgh .image-shape .label,#mermaid-svg-Idy8yVyFljg65Wgh .icon-shape .label{text-anchor:middle;}#mermaid-svg-Idy8yVyFljg65Wgh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Idy8yVyFljg65Wgh .rough-node .label,#mermaid-svg-Idy8yVyFljg65Wgh .node .label,#mermaid-svg-Idy8yVyFljg65Wgh .image-shape .label,#mermaid-svg-Idy8yVyFljg65Wgh .icon-shape .label{text-align:center;}#mermaid-svg-Idy8yVyFljg65Wgh .node.clickable{cursor:pointer;}#mermaid-svg-Idy8yVyFljg65Wgh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Idy8yVyFljg65Wgh .arrowheadPath{fill:#333333;}#mermaid-svg-Idy8yVyFljg65Wgh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Idy8yVyFljg65Wgh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Idy8yVyFljg65Wgh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Idy8yVyFljg65Wgh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Idy8yVyFljg65Wgh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Idy8yVyFljg65Wgh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Idy8yVyFljg65Wgh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Idy8yVyFljg65Wgh .cluster text{fill:#333;}#mermaid-svg-Idy8yVyFljg65Wgh .cluster span{color:#333;}#mermaid-svg-Idy8yVyFljg65Wgh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Idy8yVyFljg65Wgh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Idy8yVyFljg65Wgh rect.text{fill:none;stroke-width:0;}#mermaid-svg-Idy8yVyFljg65Wgh .icon-shape,#mermaid-svg-Idy8yVyFljg65Wgh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Idy8yVyFljg65Wgh .icon-shape p,#mermaid-svg-Idy8yVyFljg65Wgh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Idy8yVyFljg65Wgh .icon-shape .label rect,#mermaid-svg-Idy8yVyFljg65Wgh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Idy8yVyFljg65Wgh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Idy8yVyFljg65Wgh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Idy8yVyFljg65Wgh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent
Tool Layer A
Tool Layer B
Tool Layer C
Managed Browser
User Chrome
Remote Browser

这意味着:

text 复制代码
Snapshot
Ref
Click
Type
Screenshot
Navigation

都可能需要实现多遍。

而 CDP Relay 可以把架构变成:
#mermaid-svg-hGfOO46daRWDS1Wa{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hGfOO46daRWDS1Wa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hGfOO46daRWDS1Wa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hGfOO46daRWDS1Wa .error-icon{fill:#552222;}#mermaid-svg-hGfOO46daRWDS1Wa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hGfOO46daRWDS1Wa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hGfOO46daRWDS1Wa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hGfOO46daRWDS1Wa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hGfOO46daRWDS1Wa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hGfOO46daRWDS1Wa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hGfOO46daRWDS1Wa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hGfOO46daRWDS1Wa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hGfOO46daRWDS1Wa .marker.cross{stroke:#333333;}#mermaid-svg-hGfOO46daRWDS1Wa svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hGfOO46daRWDS1Wa p{margin:0;}#mermaid-svg-hGfOO46daRWDS1Wa .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hGfOO46daRWDS1Wa .cluster-label text{fill:#333;}#mermaid-svg-hGfOO46daRWDS1Wa .cluster-label span{color:#333;}#mermaid-svg-hGfOO46daRWDS1Wa .cluster-label span p{background-color:transparent;}#mermaid-svg-hGfOO46daRWDS1Wa .label text,#mermaid-svg-hGfOO46daRWDS1Wa span{fill:#333;color:#333;}#mermaid-svg-hGfOO46daRWDS1Wa .node rect,#mermaid-svg-hGfOO46daRWDS1Wa .node circle,#mermaid-svg-hGfOO46daRWDS1Wa .node ellipse,#mermaid-svg-hGfOO46daRWDS1Wa .node polygon,#mermaid-svg-hGfOO46daRWDS1Wa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hGfOO46daRWDS1Wa .rough-node .label text,#mermaid-svg-hGfOO46daRWDS1Wa .node .label text,#mermaid-svg-hGfOO46daRWDS1Wa .image-shape .label,#mermaid-svg-hGfOO46daRWDS1Wa .icon-shape .label{text-anchor:middle;}#mermaid-svg-hGfOO46daRWDS1Wa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hGfOO46daRWDS1Wa .rough-node .label,#mermaid-svg-hGfOO46daRWDS1Wa .node .label,#mermaid-svg-hGfOO46daRWDS1Wa .image-shape .label,#mermaid-svg-hGfOO46daRWDS1Wa .icon-shape .label{text-align:center;}#mermaid-svg-hGfOO46daRWDS1Wa .node.clickable{cursor:pointer;}#mermaid-svg-hGfOO46daRWDS1Wa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hGfOO46daRWDS1Wa .arrowheadPath{fill:#333333;}#mermaid-svg-hGfOO46daRWDS1Wa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hGfOO46daRWDS1Wa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hGfOO46daRWDS1Wa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hGfOO46daRWDS1Wa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hGfOO46daRWDS1Wa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hGfOO46daRWDS1Wa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hGfOO46daRWDS1Wa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hGfOO46daRWDS1Wa .cluster text{fill:#333;}#mermaid-svg-hGfOO46daRWDS1Wa .cluster span{color:#333;}#mermaid-svg-hGfOO46daRWDS1Wa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hGfOO46daRWDS1Wa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hGfOO46daRWDS1Wa rect.text{fill:none;stroke-width:0;}#mermaid-svg-hGfOO46daRWDS1Wa .icon-shape,#mermaid-svg-hGfOO46daRWDS1Wa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hGfOO46daRWDS1Wa .icon-shape p,#mermaid-svg-hGfOO46daRWDS1Wa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hGfOO46daRWDS1Wa .icon-shape .label rect,#mermaid-svg-hGfOO46daRWDS1Wa .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hGfOO46daRWDS1Wa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hGfOO46daRWDS1Wa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hGfOO46daRWDS1Wa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent
Unified Browser Tool Layer
Unified CDP Interface
Managed Browser
CDP Relay
Remote Browser
Chrome Extension
User Chrome

这样:

Browser Source 只是不同的 Endpoint。

Tool Layer 不需要变化。


十七、这是 OpenClaw 比自定义 Tool Protocol 更漂亮的地方

Claude Code 的模式更接近:
#mermaid-svg-rWSSiWBpbirkpQfb{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rWSSiWBpbirkpQfb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rWSSiWBpbirkpQfb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rWSSiWBpbirkpQfb .error-icon{fill:#552222;}#mermaid-svg-rWSSiWBpbirkpQfb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rWSSiWBpbirkpQfb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rWSSiWBpbirkpQfb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rWSSiWBpbirkpQfb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rWSSiWBpbirkpQfb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rWSSiWBpbirkpQfb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rWSSiWBpbirkpQfb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rWSSiWBpbirkpQfb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rWSSiWBpbirkpQfb .marker.cross{stroke:#333333;}#mermaid-svg-rWSSiWBpbirkpQfb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rWSSiWBpbirkpQfb p{margin:0;}#mermaid-svg-rWSSiWBpbirkpQfb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rWSSiWBpbirkpQfb .cluster-label text{fill:#333;}#mermaid-svg-rWSSiWBpbirkpQfb .cluster-label span{color:#333;}#mermaid-svg-rWSSiWBpbirkpQfb .cluster-label span p{background-color:transparent;}#mermaid-svg-rWSSiWBpbirkpQfb .label text,#mermaid-svg-rWSSiWBpbirkpQfb span{fill:#333;color:#333;}#mermaid-svg-rWSSiWBpbirkpQfb .node rect,#mermaid-svg-rWSSiWBpbirkpQfb .node circle,#mermaid-svg-rWSSiWBpbirkpQfb .node ellipse,#mermaid-svg-rWSSiWBpbirkpQfb .node polygon,#mermaid-svg-rWSSiWBpbirkpQfb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rWSSiWBpbirkpQfb .rough-node .label text,#mermaid-svg-rWSSiWBpbirkpQfb .node .label text,#mermaid-svg-rWSSiWBpbirkpQfb .image-shape .label,#mermaid-svg-rWSSiWBpbirkpQfb .icon-shape .label{text-anchor:middle;}#mermaid-svg-rWSSiWBpbirkpQfb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rWSSiWBpbirkpQfb .rough-node .label,#mermaid-svg-rWSSiWBpbirkpQfb .node .label,#mermaid-svg-rWSSiWBpbirkpQfb .image-shape .label,#mermaid-svg-rWSSiWBpbirkpQfb .icon-shape .label{text-align:center;}#mermaid-svg-rWSSiWBpbirkpQfb .node.clickable{cursor:pointer;}#mermaid-svg-rWSSiWBpbirkpQfb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rWSSiWBpbirkpQfb .arrowheadPath{fill:#333333;}#mermaid-svg-rWSSiWBpbirkpQfb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rWSSiWBpbirkpQfb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rWSSiWBpbirkpQfb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rWSSiWBpbirkpQfb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rWSSiWBpbirkpQfb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rWSSiWBpbirkpQfb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rWSSiWBpbirkpQfb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rWSSiWBpbirkpQfb .cluster text{fill:#333;}#mermaid-svg-rWSSiWBpbirkpQfb .cluster span{color:#333;}#mermaid-svg-rWSSiWBpbirkpQfb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rWSSiWBpbirkpQfb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rWSSiWBpbirkpQfb rect.text{fill:none;stroke-width:0;}#mermaid-svg-rWSSiWBpbirkpQfb .icon-shape,#mermaid-svg-rWSSiWBpbirkpQfb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rWSSiWBpbirkpQfb .icon-shape p,#mermaid-svg-rWSSiWBpbirkpQfb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rWSSiWBpbirkpQfb .icon-shape .label rect,#mermaid-svg-rWSSiWBpbirkpQfb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rWSSiWBpbirkpQfb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rWSSiWBpbirkpQfb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rWSSiWBpbirkpQfb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Browser Tool
Custom execute_tool
Chrome Extension
Chrome

而 OpenClaw 更接近:
#mermaid-svg-UklZPSqDyevizf1Y{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UklZPSqDyevizf1Y .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UklZPSqDyevizf1Y .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UklZPSqDyevizf1Y .error-icon{fill:#552222;}#mermaid-svg-UklZPSqDyevizf1Y .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UklZPSqDyevizf1Y .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UklZPSqDyevizf1Y .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UklZPSqDyevizf1Y .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UklZPSqDyevizf1Y .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UklZPSqDyevizf1Y .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UklZPSqDyevizf1Y .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UklZPSqDyevizf1Y .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UklZPSqDyevizf1Y .marker.cross{stroke:#333333;}#mermaid-svg-UklZPSqDyevizf1Y svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UklZPSqDyevizf1Y p{margin:0;}#mermaid-svg-UklZPSqDyevizf1Y .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UklZPSqDyevizf1Y .cluster-label text{fill:#333;}#mermaid-svg-UklZPSqDyevizf1Y .cluster-label span{color:#333;}#mermaid-svg-UklZPSqDyevizf1Y .cluster-label span p{background-color:transparent;}#mermaid-svg-UklZPSqDyevizf1Y .label text,#mermaid-svg-UklZPSqDyevizf1Y span{fill:#333;color:#333;}#mermaid-svg-UklZPSqDyevizf1Y .node rect,#mermaid-svg-UklZPSqDyevizf1Y .node circle,#mermaid-svg-UklZPSqDyevizf1Y .node ellipse,#mermaid-svg-UklZPSqDyevizf1Y .node polygon,#mermaid-svg-UklZPSqDyevizf1Y .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UklZPSqDyevizf1Y .rough-node .label text,#mermaid-svg-UklZPSqDyevizf1Y .node .label text,#mermaid-svg-UklZPSqDyevizf1Y .image-shape .label,#mermaid-svg-UklZPSqDyevizf1Y .icon-shape .label{text-anchor:middle;}#mermaid-svg-UklZPSqDyevizf1Y .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UklZPSqDyevizf1Y .rough-node .label,#mermaid-svg-UklZPSqDyevizf1Y .node .label,#mermaid-svg-UklZPSqDyevizf1Y .image-shape .label,#mermaid-svg-UklZPSqDyevizf1Y .icon-shape .label{text-align:center;}#mermaid-svg-UklZPSqDyevizf1Y .node.clickable{cursor:pointer;}#mermaid-svg-UklZPSqDyevizf1Y .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UklZPSqDyevizf1Y .arrowheadPath{fill:#333333;}#mermaid-svg-UklZPSqDyevizf1Y .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UklZPSqDyevizf1Y .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UklZPSqDyevizf1Y .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UklZPSqDyevizf1Y .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UklZPSqDyevizf1Y .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UklZPSqDyevizf1Y .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UklZPSqDyevizf1Y .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UklZPSqDyevizf1Y .cluster text{fill:#333;}#mermaid-svg-UklZPSqDyevizf1Y .cluster span{color:#333;}#mermaid-svg-UklZPSqDyevizf1Y div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UklZPSqDyevizf1Y .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UklZPSqDyevizf1Y rect.text{fill:none;stroke-width:0;}#mermaid-svg-UklZPSqDyevizf1Y .icon-shape,#mermaid-svg-UklZPSqDyevizf1Y .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UklZPSqDyevizf1Y .icon-shape p,#mermaid-svg-UklZPSqDyevizf1Y .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UklZPSqDyevizf1Y .icon-shape .label rect,#mermaid-svg-UklZPSqDyevizf1Y .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UklZPSqDyevizf1Y .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UklZPSqDyevizf1Y .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UklZPSqDyevizf1Y :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Browser Tool
Standard CDP
CDP Endpoint
Chrome

区别在于:

前者把 Tool Layer 与 Transport 强绑定;后者把 Tool Layer 与 Transport 解耦。

如果以后需要增加:

text 复制代码
Browserless
Remote Chromium
Cloud Browser
Local Browser
User Chrome

第二种架构明显更加自然。


十八、OpenClaw 的另一个经验:Extension 必须足够薄

Browser Extension 非常容易变成一个"巨大的业务逻辑容器"。

例如:

text 复制代码
1000 lines
Service Worker
State Machine
Session Management
Protocol Logic
Business Logic
...

最终很难测试和维护。

OpenClaw 的架构思路则更接近:
#mermaid-svg-4vuGLpHPyOwIWbKm{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4vuGLpHPyOwIWbKm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4vuGLpHPyOwIWbKm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4vuGLpHPyOwIWbKm .error-icon{fill:#552222;}#mermaid-svg-4vuGLpHPyOwIWbKm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4vuGLpHPyOwIWbKm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4vuGLpHPyOwIWbKm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4vuGLpHPyOwIWbKm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4vuGLpHPyOwIWbKm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4vuGLpHPyOwIWbKm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4vuGLpHPyOwIWbKm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4vuGLpHPyOwIWbKm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4vuGLpHPyOwIWbKm .marker.cross{stroke:#333333;}#mermaid-svg-4vuGLpHPyOwIWbKm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4vuGLpHPyOwIWbKm p{margin:0;}#mermaid-svg-4vuGLpHPyOwIWbKm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4vuGLpHPyOwIWbKm .cluster-label text{fill:#333;}#mermaid-svg-4vuGLpHPyOwIWbKm .cluster-label span{color:#333;}#mermaid-svg-4vuGLpHPyOwIWbKm .cluster-label span p{background-color:transparent;}#mermaid-svg-4vuGLpHPyOwIWbKm .label text,#mermaid-svg-4vuGLpHPyOwIWbKm span{fill:#333;color:#333;}#mermaid-svg-4vuGLpHPyOwIWbKm .node rect,#mermaid-svg-4vuGLpHPyOwIWbKm .node circle,#mermaid-svg-4vuGLpHPyOwIWbKm .node ellipse,#mermaid-svg-4vuGLpHPyOwIWbKm .node polygon,#mermaid-svg-4vuGLpHPyOwIWbKm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4vuGLpHPyOwIWbKm .rough-node .label text,#mermaid-svg-4vuGLpHPyOwIWbKm .node .label text,#mermaid-svg-4vuGLpHPyOwIWbKm .image-shape .label,#mermaid-svg-4vuGLpHPyOwIWbKm .icon-shape .label{text-anchor:middle;}#mermaid-svg-4vuGLpHPyOwIWbKm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4vuGLpHPyOwIWbKm .rough-node .label,#mermaid-svg-4vuGLpHPyOwIWbKm .node .label,#mermaid-svg-4vuGLpHPyOwIWbKm .image-shape .label,#mermaid-svg-4vuGLpHPyOwIWbKm .icon-shape .label{text-align:center;}#mermaid-svg-4vuGLpHPyOwIWbKm .node.clickable{cursor:pointer;}#mermaid-svg-4vuGLpHPyOwIWbKm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4vuGLpHPyOwIWbKm .arrowheadPath{fill:#333333;}#mermaid-svg-4vuGLpHPyOwIWbKm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4vuGLpHPyOwIWbKm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4vuGLpHPyOwIWbKm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4vuGLpHPyOwIWbKm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4vuGLpHPyOwIWbKm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4vuGLpHPyOwIWbKm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4vuGLpHPyOwIWbKm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4vuGLpHPyOwIWbKm .cluster text{fill:#333;}#mermaid-svg-4vuGLpHPyOwIWbKm .cluster span{color:#333;}#mermaid-svg-4vuGLpHPyOwIWbKm div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4vuGLpHPyOwIWbKm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4vuGLpHPyOwIWbKm rect.text{fill:none;stroke-width:0;}#mermaid-svg-4vuGLpHPyOwIWbKm .icon-shape,#mermaid-svg-4vuGLpHPyOwIWbKm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4vuGLpHPyOwIWbKm .icon-shape p,#mermaid-svg-4vuGLpHPyOwIWbKm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4vuGLpHPyOwIWbKm .icon-shape .label rect,#mermaid-svg-4vuGLpHPyOwIWbKm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4vuGLpHPyOwIWbKm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4vuGLpHPyOwIWbKm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4vuGLpHPyOwIWbKm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Thin Chrome Extension
WebSocket Client
chrome.debugger
Tab Group Management
Host / Gateway
CDP Target Synthesis
Session Mapping
Pairing Logic
Iframe Session

原则非常清楚:

Extension 负责浏览器内部能力,Host 负责复杂逻辑。

OpenClaw 官方文档也说明 Extension 主要负责 chrome.debugger、CDP 转发和标签页组管理,而 relay 在本地提供 CDP endpoint。

这是一条非常值得记住的工程原则:

Chrome Extension 应该是 Thin Client,而不是 Browser Automation Engine。


十九、Native Messaging:应该只解决 Pairing

另一个值得借鉴的设计是:

Native Messaging 不应该承担所有 Browser Data Traffic。

更合理的方式是:
#mermaid-svg-KLvvAmn8WX1VOcil{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KLvvAmn8WX1VOcil .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KLvvAmn8WX1VOcil .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KLvvAmn8WX1VOcil .error-icon{fill:#552222;}#mermaid-svg-KLvvAmn8WX1VOcil .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KLvvAmn8WX1VOcil .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KLvvAmn8WX1VOcil .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KLvvAmn8WX1VOcil .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KLvvAmn8WX1VOcil .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KLvvAmn8WX1VOcil .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KLvvAmn8WX1VOcil .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KLvvAmn8WX1VOcil .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KLvvAmn8WX1VOcil .marker.cross{stroke:#333333;}#mermaid-svg-KLvvAmn8WX1VOcil svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KLvvAmn8WX1VOcil p{margin:0;}#mermaid-svg-KLvvAmn8WX1VOcil .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KLvvAmn8WX1VOcil .cluster-label text{fill:#333;}#mermaid-svg-KLvvAmn8WX1VOcil .cluster-label span{color:#333;}#mermaid-svg-KLvvAmn8WX1VOcil .cluster-label span p{background-color:transparent;}#mermaid-svg-KLvvAmn8WX1VOcil .label text,#mermaid-svg-KLvvAmn8WX1VOcil span{fill:#333;color:#333;}#mermaid-svg-KLvvAmn8WX1VOcil .node rect,#mermaid-svg-KLvvAmn8WX1VOcil .node circle,#mermaid-svg-KLvvAmn8WX1VOcil .node ellipse,#mermaid-svg-KLvvAmn8WX1VOcil .node polygon,#mermaid-svg-KLvvAmn8WX1VOcil .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KLvvAmn8WX1VOcil .rough-node .label text,#mermaid-svg-KLvvAmn8WX1VOcil .node .label text,#mermaid-svg-KLvvAmn8WX1VOcil .image-shape .label,#mermaid-svg-KLvvAmn8WX1VOcil .icon-shape .label{text-anchor:middle;}#mermaid-svg-KLvvAmn8WX1VOcil .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KLvvAmn8WX1VOcil .rough-node .label,#mermaid-svg-KLvvAmn8WX1VOcil .node .label,#mermaid-svg-KLvvAmn8WX1VOcil .image-shape .label,#mermaid-svg-KLvvAmn8WX1VOcil .icon-shape .label{text-align:center;}#mermaid-svg-KLvvAmn8WX1VOcil .node.clickable{cursor:pointer;}#mermaid-svg-KLvvAmn8WX1VOcil .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KLvvAmn8WX1VOcil .arrowheadPath{fill:#333333;}#mermaid-svg-KLvvAmn8WX1VOcil .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KLvvAmn8WX1VOcil .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KLvvAmn8WX1VOcil .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KLvvAmn8WX1VOcil .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KLvvAmn8WX1VOcil .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KLvvAmn8WX1VOcil .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KLvvAmn8WX1VOcil .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KLvvAmn8WX1VOcil .cluster text{fill:#333;}#mermaid-svg-KLvvAmn8WX1VOcil .cluster span{color:#333;}#mermaid-svg-KLvvAmn8WX1VOcil div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KLvvAmn8WX1VOcil .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KLvvAmn8WX1VOcil rect.text{fill:none;stroke-width:0;}#mermaid-svg-KLvvAmn8WX1VOcil .icon-shape,#mermaid-svg-KLvvAmn8WX1VOcil .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KLvvAmn8WX1VOcil .icon-shape p,#mermaid-svg-KLvvAmn8WX1VOcil .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KLvvAmn8WX1VOcil .icon-shape .label rect,#mermaid-svg-KLvvAmn8WX1VOcil .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KLvvAmn8WX1VOcil .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KLvvAmn8WX1VOcil .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KLvvAmn8WX1VOcil :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Chrome Extension
Native Messaging
Pairing
WebSocket
CDP Relay

也就是说:

text 复制代码
Native Messaging
       ↓
Pairing / Bootstrap

WebSocket
       ↓
Normal Browser Traffic

这样 Native Host 不需要承担长期的数据连接和复杂生命周期管理。


二十、Browser Security:控制用户 Chrome 等于控制用户账号

这一点非常重要。

如果 Agent 可以操作:

text 复制代码
User Chrome

那么实际上 Agent 就可能操作:

text 复制代码
GitHub Account
Google Account
Slack
Jira
Internal Enterprise Systems
...

因此:

Browser Automation 的权限,本质上就是 Account-level 权限。

OpenClaw 目前的 Extension 设计里,使用 tab group 作为显式的授权边界:只有被加入 OpenClaw tab group 的标签页才会被 Agent 控制,移出该组即可撤销访问。

于是权限模型可以理解为:
#mermaid-svg-78fy8117vnEL08hF{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-78fy8117vnEL08hF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-78fy8117vnEL08hF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-78fy8117vnEL08hF .error-icon{fill:#552222;}#mermaid-svg-78fy8117vnEL08hF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-78fy8117vnEL08hF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-78fy8117vnEL08hF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-78fy8117vnEL08hF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-78fy8117vnEL08hF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-78fy8117vnEL08hF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-78fy8117vnEL08hF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-78fy8117vnEL08hF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-78fy8117vnEL08hF .marker.cross{stroke:#333333;}#mermaid-svg-78fy8117vnEL08hF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-78fy8117vnEL08hF p{margin:0;}#mermaid-svg-78fy8117vnEL08hF .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-78fy8117vnEL08hF .cluster-label text{fill:#333;}#mermaid-svg-78fy8117vnEL08hF .cluster-label span{color:#333;}#mermaid-svg-78fy8117vnEL08hF .cluster-label span p{background-color:transparent;}#mermaid-svg-78fy8117vnEL08hF .label text,#mermaid-svg-78fy8117vnEL08hF span{fill:#333;color:#333;}#mermaid-svg-78fy8117vnEL08hF .node rect,#mermaid-svg-78fy8117vnEL08hF .node circle,#mermaid-svg-78fy8117vnEL08hF .node ellipse,#mermaid-svg-78fy8117vnEL08hF .node polygon,#mermaid-svg-78fy8117vnEL08hF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-78fy8117vnEL08hF .rough-node .label text,#mermaid-svg-78fy8117vnEL08hF .node .label text,#mermaid-svg-78fy8117vnEL08hF .image-shape .label,#mermaid-svg-78fy8117vnEL08hF .icon-shape .label{text-anchor:middle;}#mermaid-svg-78fy8117vnEL08hF .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-78fy8117vnEL08hF .rough-node .label,#mermaid-svg-78fy8117vnEL08hF .node .label,#mermaid-svg-78fy8117vnEL08hF .image-shape .label,#mermaid-svg-78fy8117vnEL08hF .icon-shape .label{text-align:center;}#mermaid-svg-78fy8117vnEL08hF .node.clickable{cursor:pointer;}#mermaid-svg-78fy8117vnEL08hF .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-78fy8117vnEL08hF .arrowheadPath{fill:#333333;}#mermaid-svg-78fy8117vnEL08hF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-78fy8117vnEL08hF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-78fy8117vnEL08hF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-78fy8117vnEL08hF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-78fy8117vnEL08hF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-78fy8117vnEL08hF .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-78fy8117vnEL08hF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-78fy8117vnEL08hF .cluster text{fill:#333;}#mermaid-svg-78fy8117vnEL08hF .cluster span{color:#333;}#mermaid-svg-78fy8117vnEL08hF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-78fy8117vnEL08hF .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-78fy8117vnEL08hF rect.text{fill:none;stroke-width:0;}#mermaid-svg-78fy8117vnEL08hF .icon-shape,#mermaid-svg-78fy8117vnEL08hF .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-78fy8117vnEL08hF .icon-shape p,#mermaid-svg-78fy8117vnEL08hF .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-78fy8117vnEL08hF .icon-shape .label rect,#mermaid-svg-78fy8117vnEL08hF .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-78fy8117vnEL08hF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-78fy8117vnEL08hF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-78fy8117vnEL08hF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} User Chrome
Normal Tabs
Agent Shared Tabs
AI Agent

这比:

text 复制代码
Agent
 ↓
Entire Chrome

安全得多。


二十一、Browser Agent 真正的核心:Verify Loop

到这里我们已经讨论了:

  • Browser
  • CDP
  • Extension
  • Snapshot
  • Ref
  • Tool

但这些都只是基础设施。

真正让 Coding Agent 变得有用的是:

Verify Loop。

例如用户要求:

"修改登录页面,然后确保页面在 Chrome 中能够正常工作。"

一个真正成熟的 Coding Agent 应该执行:
#mermaid-svg-yyy3XY6PSeI9VDsi{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yyy3XY6PSeI9VDsi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yyy3XY6PSeI9VDsi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yyy3XY6PSeI9VDsi .error-icon{fill:#552222;}#mermaid-svg-yyy3XY6PSeI9VDsi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yyy3XY6PSeI9VDsi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yyy3XY6PSeI9VDsi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yyy3XY6PSeI9VDsi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yyy3XY6PSeI9VDsi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yyy3XY6PSeI9VDsi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yyy3XY6PSeI9VDsi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yyy3XY6PSeI9VDsi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yyy3XY6PSeI9VDsi .marker.cross{stroke:#333333;}#mermaid-svg-yyy3XY6PSeI9VDsi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yyy3XY6PSeI9VDsi p{margin:0;}#mermaid-svg-yyy3XY6PSeI9VDsi .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yyy3XY6PSeI9VDsi .cluster-label text{fill:#333;}#mermaid-svg-yyy3XY6PSeI9VDsi .cluster-label span{color:#333;}#mermaid-svg-yyy3XY6PSeI9VDsi .cluster-label span p{background-color:transparent;}#mermaid-svg-yyy3XY6PSeI9VDsi .label text,#mermaid-svg-yyy3XY6PSeI9VDsi span{fill:#333;color:#333;}#mermaid-svg-yyy3XY6PSeI9VDsi .node rect,#mermaid-svg-yyy3XY6PSeI9VDsi .node circle,#mermaid-svg-yyy3XY6PSeI9VDsi .node ellipse,#mermaid-svg-yyy3XY6PSeI9VDsi .node polygon,#mermaid-svg-yyy3XY6PSeI9VDsi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yyy3XY6PSeI9VDsi .rough-node .label text,#mermaid-svg-yyy3XY6PSeI9VDsi .node .label text,#mermaid-svg-yyy3XY6PSeI9VDsi .image-shape .label,#mermaid-svg-yyy3XY6PSeI9VDsi .icon-shape .label{text-anchor:middle;}#mermaid-svg-yyy3XY6PSeI9VDsi .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yyy3XY6PSeI9VDsi .rough-node .label,#mermaid-svg-yyy3XY6PSeI9VDsi .node .label,#mermaid-svg-yyy3XY6PSeI9VDsi .image-shape .label,#mermaid-svg-yyy3XY6PSeI9VDsi .icon-shape .label{text-align:center;}#mermaid-svg-yyy3XY6PSeI9VDsi .node.clickable{cursor:pointer;}#mermaid-svg-yyy3XY6PSeI9VDsi .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yyy3XY6PSeI9VDsi .arrowheadPath{fill:#333333;}#mermaid-svg-yyy3XY6PSeI9VDsi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yyy3XY6PSeI9VDsi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yyy3XY6PSeI9VDsi .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yyy3XY6PSeI9VDsi .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yyy3XY6PSeI9VDsi .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yyy3XY6PSeI9VDsi .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yyy3XY6PSeI9VDsi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yyy3XY6PSeI9VDsi .cluster text{fill:#333;}#mermaid-svg-yyy3XY6PSeI9VDsi .cluster span{color:#333;}#mermaid-svg-yyy3XY6PSeI9VDsi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yyy3XY6PSeI9VDsi .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yyy3XY6PSeI9VDsi rect.text{fill:none;stroke-width:0;}#mermaid-svg-yyy3XY6PSeI9VDsi .icon-shape,#mermaid-svg-yyy3XY6PSeI9VDsi .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yyy3XY6PSeI9VDsi .icon-shape p,#mermaid-svg-yyy3XY6PSeI9VDsi .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yyy3XY6PSeI9VDsi .icon-shape .label rect,#mermaid-svg-yyy3XY6PSeI9VDsi .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yyy3XY6PSeI9VDsi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yyy3XY6PSeI9VDsi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yyy3XY6PSeI9VDsi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Pass
Fail
Modify Code
Start Dev Server
Navigate
Snapshot
Browser Action
Screenshot
Verify
Fix Code
Task Complete

这才是:

Code → Browser → Verify → Fix → Verify


二十二、Browser Automation ≠ Browser Agent

这是我认为整篇文章最重要的结论。

Browser Automation 解决:

"我能不能操作网页?"

Browser Agent 解决:

"我能不能可靠地完成一个网页任务?"

两者完全不同。

例如:

text 复制代码
click()
type()
scroll()
screenshot()

只是 Automation。

而:

text 复制代码
Understand
   ↓
Act
   ↓
Observe
   ↓
Verify
   ↓
Fix
   ↓
Verify

才是 Agent。

因此:

真正成熟的 Browser Agent,核心不是 Tool 数量,而是 Agent Loop。


二十三、为什么 Skill 和 Prompt 同样重要?

Browser Automation 有一个非常典型的问题:

模型很容易在网页上不断重复失败操作。

例如:

text 复制代码
click
 ↓
failed
 ↓
click
 ↓
failed
 ↓
click
 ↓
failed
 ↓
...

这会快速消耗:

  • Token
  • Tool Calls
  • 时间
  • Browser State

所以 Browser Skill 应该明确告诉 Agent:

text 复制代码
If an action fails,
do not immediately repeat it.

First obtain new evidence:
- fresh snapshot
- new ref
- changed page state
- new hypothesis

可以进一步设置:

text 复制代码
Failure Budget = 4

即:
#mermaid-svg-4B3lg7UujRtmmQlC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4B3lg7UujRtmmQlC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4B3lg7UujRtmmQlC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4B3lg7UujRtmmQlC .error-icon{fill:#552222;}#mermaid-svg-4B3lg7UujRtmmQlC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4B3lg7UujRtmmQlC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4B3lg7UujRtmmQlC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4B3lg7UujRtmmQlC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4B3lg7UujRtmmQlC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4B3lg7UujRtmmQlC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4B3lg7UujRtmmQlC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4B3lg7UujRtmmQlC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4B3lg7UujRtmmQlC .marker.cross{stroke:#333333;}#mermaid-svg-4B3lg7UujRtmmQlC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4B3lg7UujRtmmQlC p{margin:0;}#mermaid-svg-4B3lg7UujRtmmQlC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4B3lg7UujRtmmQlC .cluster-label text{fill:#333;}#mermaid-svg-4B3lg7UujRtmmQlC .cluster-label span{color:#333;}#mermaid-svg-4B3lg7UujRtmmQlC .cluster-label span p{background-color:transparent;}#mermaid-svg-4B3lg7UujRtmmQlC .label text,#mermaid-svg-4B3lg7UujRtmmQlC span{fill:#333;color:#333;}#mermaid-svg-4B3lg7UujRtmmQlC .node rect,#mermaid-svg-4B3lg7UujRtmmQlC .node circle,#mermaid-svg-4B3lg7UujRtmmQlC .node ellipse,#mermaid-svg-4B3lg7UujRtmmQlC .node polygon,#mermaid-svg-4B3lg7UujRtmmQlC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4B3lg7UujRtmmQlC .rough-node .label text,#mermaid-svg-4B3lg7UujRtmmQlC .node .label text,#mermaid-svg-4B3lg7UujRtmmQlC .image-shape .label,#mermaid-svg-4B3lg7UujRtmmQlC .icon-shape .label{text-anchor:middle;}#mermaid-svg-4B3lg7UujRtmmQlC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4B3lg7UujRtmmQlC .rough-node .label,#mermaid-svg-4B3lg7UujRtmmQlC .node .label,#mermaid-svg-4B3lg7UujRtmmQlC .image-shape .label,#mermaid-svg-4B3lg7UujRtmmQlC .icon-shape .label{text-align:center;}#mermaid-svg-4B3lg7UujRtmmQlC .node.clickable{cursor:pointer;}#mermaid-svg-4B3lg7UujRtmmQlC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4B3lg7UujRtmmQlC .arrowheadPath{fill:#333333;}#mermaid-svg-4B3lg7UujRtmmQlC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4B3lg7UujRtmmQlC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4B3lg7UujRtmmQlC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4B3lg7UujRtmmQlC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4B3lg7UujRtmmQlC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4B3lg7UujRtmmQlC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4B3lg7UujRtmmQlC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4B3lg7UujRtmmQlC .cluster text{fill:#333;}#mermaid-svg-4B3lg7UujRtmmQlC .cluster span{color:#333;}#mermaid-svg-4B3lg7UujRtmmQlC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4B3lg7UujRtmmQlC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4B3lg7UujRtmmQlC rect.text{fill:none;stroke-width:0;}#mermaid-svg-4B3lg7UujRtmmQlC .icon-shape,#mermaid-svg-4B3lg7UujRtmmQlC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4B3lg7UujRtmmQlC .icon-shape p,#mermaid-svg-4B3lg7UujRtmmQlC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4B3lg7UujRtmmQlC .icon-shape .label rect,#mermaid-svg-4B3lg7UujRtmmQlC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4B3lg7UujRtmmQlC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4B3lg7UujRtmmQlC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4B3lg7UujRtmmQlC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Yes
No
Available
Exceeded
Browser Action
Success?
New Evidence
Retry Budget
Stop and Report
Continue

这个机制非常重要:

没有新证据,就不要重复同一个失败动作。


二十四、对白泽这样的 Coding Agent,有什么启示?

如果我们要自己实现 Browser Automation,我认为可以直接提炼出下面几个原则。


1. Tool Layer 只写一次

最重要的一条:

Browser Transport 和 Browser Tool Layer 必须解耦。

推荐:

text 复制代码
Browser Tool
      ↓
CDP
      ↓
Endpoint

而不是:

text 复制代码
Browser Tool
      ↓
Chrome Extension Protocol

这样以后可以增加:

text 复制代码
Managed Browser
User Chrome
Remote Browser
Cloud Browser

而不需要重新实现 Tool Layer。


2. Extension 必须 Thin

Extension 只负责:

text 复制代码
chrome.debugger
WebSocket
Tab Management

而:

text 复制代码
CDP Target
Session
Iframe
Protocol
Business Logic

都应该放到 Host。


3. Ref 应该采用多层防护

最理想的设计不是简单:

text 复制代码
ref = e5

而是:
#mermaid-svg-z1fV7kTpN4f2iUHC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-z1fV7kTpN4f2iUHC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-z1fV7kTpN4f2iUHC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-z1fV7kTpN4f2iUHC .error-icon{fill:#552222;}#mermaid-svg-z1fV7kTpN4f2iUHC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-z1fV7kTpN4f2iUHC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-z1fV7kTpN4f2iUHC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-z1fV7kTpN4f2iUHC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-z1fV7kTpN4f2iUHC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-z1fV7kTpN4f2iUHC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-z1fV7kTpN4f2iUHC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-z1fV7kTpN4f2iUHC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-z1fV7kTpN4f2iUHC .marker.cross{stroke:#333333;}#mermaid-svg-z1fV7kTpN4f2iUHC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-z1fV7kTpN4f2iUHC p{margin:0;}#mermaid-svg-z1fV7kTpN4f2iUHC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-z1fV7kTpN4f2iUHC .cluster-label text{fill:#333;}#mermaid-svg-z1fV7kTpN4f2iUHC .cluster-label span{color:#333;}#mermaid-svg-z1fV7kTpN4f2iUHC .cluster-label span p{background-color:transparent;}#mermaid-svg-z1fV7kTpN4f2iUHC .label text,#mermaid-svg-z1fV7kTpN4f2iUHC span{fill:#333;color:#333;}#mermaid-svg-z1fV7kTpN4f2iUHC .node rect,#mermaid-svg-z1fV7kTpN4f2iUHC .node circle,#mermaid-svg-z1fV7kTpN4f2iUHC .node ellipse,#mermaid-svg-z1fV7kTpN4f2iUHC .node polygon,#mermaid-svg-z1fV7kTpN4f2iUHC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-z1fV7kTpN4f2iUHC .rough-node .label text,#mermaid-svg-z1fV7kTpN4f2iUHC .node .label text,#mermaid-svg-z1fV7kTpN4f2iUHC .image-shape .label,#mermaid-svg-z1fV7kTpN4f2iUHC .icon-shape .label{text-anchor:middle;}#mermaid-svg-z1fV7kTpN4f2iUHC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-z1fV7kTpN4f2iUHC .rough-node .label,#mermaid-svg-z1fV7kTpN4f2iUHC .node .label,#mermaid-svg-z1fV7kTpN4f2iUHC .image-shape .label,#mermaid-svg-z1fV7kTpN4f2iUHC .icon-shape .label{text-align:center;}#mermaid-svg-z1fV7kTpN4f2iUHC .node.clickable{cursor:pointer;}#mermaid-svg-z1fV7kTpN4f2iUHC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-z1fV7kTpN4f2iUHC .arrowheadPath{fill:#333333;}#mermaid-svg-z1fV7kTpN4f2iUHC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-z1fV7kTpN4f2iUHC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-z1fV7kTpN4f2iUHC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-z1fV7kTpN4f2iUHC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-z1fV7kTpN4f2iUHC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-z1fV7kTpN4f2iUHC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-z1fV7kTpN4f2iUHC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-z1fV7kTpN4f2iUHC .cluster text{fill:#333;}#mermaid-svg-z1fV7kTpN4f2iUHC .cluster span{color:#333;}#mermaid-svg-z1fV7kTpN4f2iUHC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-z1fV7kTpN4f2iUHC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-z1fV7kTpN4f2iUHC rect.text{fill:none;stroke-width:0;}#mermaid-svg-z1fV7kTpN4f2iUHC .icon-shape,#mermaid-svg-z1fV7kTpN4f2iUHC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-z1fV7kTpN4f2iUHC .icon-shape p,#mermaid-svg-z1fV7kTpN4f2iUHC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-z1fV7kTpN4f2iUHC .icon-shape .label rect,#mermaid-svg-z1fV7kTpN4f2iUHC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-z1fV7kTpN4f2iUHC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-z1fV7kTpN4f2iUHC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-z1fV7kTpN4f2iUHC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} DOM Element
Stable Ref
Semantic Description
Snapshot TTL
IFrame Context

也就是:

text 复制代码
Stable Ref
+
Semantic Validation
+
Snapshot TTL
+
Iframe Awareness

4. Tool 粒度应该学习 Cursor

不要把所有能力都塞进:

text 复制代码
computer()

推荐:

text 复制代码
browser_navigate()
browser_snapshot()
browser_click()
browser_type()
browser_fill()
browser_scroll()
browser_press_key()
browser_screenshot()

每个 Tool:

text 复制代码
Narrow Schema
Clear Parameters
Predictable Behavior

让模型更容易调用正确。


5. Action 和 Verify 尽可能靠近

例如:

text 复制代码
browser_click
        ↓
screenshot
        ↓
verification

而不是:

text 复制代码
browser_click
        ↓
LLM
        ↓
screenshot
        ↓
LLM

这能够显著减少 Agent Loop。


6. Browser Skill 应该内置 Verify Loop

Browser Skill 不应该只是告诉模型:

text 复制代码
You can click buttons.

而应该告诉模型:

text 复制代码
Observe
 ↓
Plan
 ↓
Act
 ↓
Verify
 ↓
Recover

这才是 Browser Agent Skill。


7. 必须有 Failure Budget

例如:

text 复制代码
同一个失败动作
最多尝试 1 次

没有新证据
不要重复

连续 4 次失败
停止并报告

这样可以避免 Agent 在网页里无限循环。


二十五、最终架构

如果把整篇文章浓缩成一个最终架构,我认为应该是:
#mermaid-svg-LeJD6bD7PdTjDwvM{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LeJD6bD7PdTjDwvM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LeJD6bD7PdTjDwvM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LeJD6bD7PdTjDwvM .error-icon{fill:#552222;}#mermaid-svg-LeJD6bD7PdTjDwvM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LeJD6bD7PdTjDwvM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LeJD6bD7PdTjDwvM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LeJD6bD7PdTjDwvM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LeJD6bD7PdTjDwvM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LeJD6bD7PdTjDwvM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LeJD6bD7PdTjDwvM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LeJD6bD7PdTjDwvM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LeJD6bD7PdTjDwvM .marker.cross{stroke:#333333;}#mermaid-svg-LeJD6bD7PdTjDwvM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LeJD6bD7PdTjDwvM p{margin:0;}#mermaid-svg-LeJD6bD7PdTjDwvM .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LeJD6bD7PdTjDwvM .cluster-label text{fill:#333;}#mermaid-svg-LeJD6bD7PdTjDwvM .cluster-label span{color:#333;}#mermaid-svg-LeJD6bD7PdTjDwvM .cluster-label span p{background-color:transparent;}#mermaid-svg-LeJD6bD7PdTjDwvM .label text,#mermaid-svg-LeJD6bD7PdTjDwvM span{fill:#333;color:#333;}#mermaid-svg-LeJD6bD7PdTjDwvM .node rect,#mermaid-svg-LeJD6bD7PdTjDwvM .node circle,#mermaid-svg-LeJD6bD7PdTjDwvM .node ellipse,#mermaid-svg-LeJD6bD7PdTjDwvM .node polygon,#mermaid-svg-LeJD6bD7PdTjDwvM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LeJD6bD7PdTjDwvM .rough-node .label text,#mermaid-svg-LeJD6bD7PdTjDwvM .node .label text,#mermaid-svg-LeJD6bD7PdTjDwvM .image-shape .label,#mermaid-svg-LeJD6bD7PdTjDwvM .icon-shape .label{text-anchor:middle;}#mermaid-svg-LeJD6bD7PdTjDwvM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LeJD6bD7PdTjDwvM .rough-node .label,#mermaid-svg-LeJD6bD7PdTjDwvM .node .label,#mermaid-svg-LeJD6bD7PdTjDwvM .image-shape .label,#mermaid-svg-LeJD6bD7PdTjDwvM .icon-shape .label{text-align:center;}#mermaid-svg-LeJD6bD7PdTjDwvM .node.clickable{cursor:pointer;}#mermaid-svg-LeJD6bD7PdTjDwvM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LeJD6bD7PdTjDwvM .arrowheadPath{fill:#333333;}#mermaid-svg-LeJD6bD7PdTjDwvM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LeJD6bD7PdTjDwvM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LeJD6bD7PdTjDwvM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LeJD6bD7PdTjDwvM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LeJD6bD7PdTjDwvM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LeJD6bD7PdTjDwvM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LeJD6bD7PdTjDwvM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LeJD6bD7PdTjDwvM .cluster text{fill:#333;}#mermaid-svg-LeJD6bD7PdTjDwvM .cluster span{color:#333;}#mermaid-svg-LeJD6bD7PdTjDwvM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LeJD6bD7PdTjDwvM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LeJD6bD7PdTjDwvM rect.text{fill:none;stroke-width:0;}#mermaid-svg-LeJD6bD7PdTjDwvM .icon-shape,#mermaid-svg-LeJD6bD7PdTjDwvM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LeJD6bD7PdTjDwvM .icon-shape p,#mermaid-svg-LeJD6bD7PdTjDwvM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LeJD6bD7PdTjDwvM .icon-shape .label rect,#mermaid-svg-LeJD6bD7PdTjDwvM .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LeJD6bD7PdTjDwvM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LeJD6bD7PdTjDwvM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LeJD6bD7PdTjDwvM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} chrome.debugger
Pass
Fail
Coding Agent
Browser Skill / Workflow
Browser Tool Layer
Snapshot
Element Ref
Browser Actions
Screenshot
Unified CDP Interface
Managed Browser
Embedded Browser
CDP Relay
Chrome Extension
User Chrome
Verify
Fix Code
Task Complete

整个架构可以分成四层:

text 复制代码
┌─────────────────────────────────┐
│          Coding Agent           │
├─────────────────────────────────┤
│        Browser Skill            │
├─────────────────────────────────┤
│       Browser Tool Layer        │
├─────────────────────────────────┤
│        Unified CDP Layer        │
├─────────────────────────────────┤
│ Managed │ Embedded │ User Chrome│
└─────────────────────────────────┘

二十六、最终总结

研究这六个方案之后,我认为最值得记住的不是某个具体的 Browser Tool,而是下面几个架构原则。

第一:先决定 Browser Ownership

text 复制代码
Agent-owned
IDE-owned
User-owned

这个选择会直接影响:

text 复制代码
Login State
Isolation
Security
Control

第二:Transport 与 Tool Layer 解耦

如果可以统一到:

text 复制代码
CDP

就尽量不要让上层 Tool Layer 理解某一种 Extension Protocol。

OpenClaw 的 CDP Relay 是这方面非常好的例子。


第三:Extension 应该足够薄

Chrome Extension 最适合:

text 复制代码
Browser Permission
chrome.debugger
Message Forwarding
Tab Management

而不是承担整个 Browser Automation Engine。


第四:Ref 是 Browser Agent 的核心基础设施

一个好的 Ref 系统应该考虑:

text 复制代码
Stable Ref
+
Semantic Validation
+
TTL
+
Iframe

而不是简单的:

text 复制代码
element → integer

第五:Browser Tool 越多,不代表 Agent 越强

真正重要的是:

text 复制代码
Tool
 ↓
Observe
 ↓
Action
 ↓
Verify
 ↓
Fix

也就是:

Verify Loop


第六:Browser Automation 最终会成为 Coding Agent 的基础能力

未来 Coding Agent 不会只停留在:

text 复制代码
Read Code
 ↓
Edit Code
 ↓
Run Test

而会进一步变成:

text 复制代码
Read Code
 ↓
Edit Code
 ↓
Run Application
 ↓
Open Browser
 ↓
Interact with UI
 ↓
Verify Behavior
 ↓
Inspect Console / Network
 ↓
Fix Code
 ↓
Verify Again

最终:
#mermaid-svg-HR0coQDVnUg8mooh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HR0coQDVnUg8mooh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HR0coQDVnUg8mooh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HR0coQDVnUg8mooh .error-icon{fill:#552222;}#mermaid-svg-HR0coQDVnUg8mooh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HR0coQDVnUg8mooh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HR0coQDVnUg8mooh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HR0coQDVnUg8mooh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HR0coQDVnUg8mooh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HR0coQDVnUg8mooh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HR0coQDVnUg8mooh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HR0coQDVnUg8mooh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HR0coQDVnUg8mooh .marker.cross{stroke:#333333;}#mermaid-svg-HR0coQDVnUg8mooh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HR0coQDVnUg8mooh p{margin:0;}#mermaid-svg-HR0coQDVnUg8mooh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-HR0coQDVnUg8mooh .cluster-label text{fill:#333;}#mermaid-svg-HR0coQDVnUg8mooh .cluster-label span{color:#333;}#mermaid-svg-HR0coQDVnUg8mooh .cluster-label span p{background-color:transparent;}#mermaid-svg-HR0coQDVnUg8mooh .label text,#mermaid-svg-HR0coQDVnUg8mooh span{fill:#333;color:#333;}#mermaid-svg-HR0coQDVnUg8mooh .node rect,#mermaid-svg-HR0coQDVnUg8mooh .node circle,#mermaid-svg-HR0coQDVnUg8mooh .node ellipse,#mermaid-svg-HR0coQDVnUg8mooh .node polygon,#mermaid-svg-HR0coQDVnUg8mooh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HR0coQDVnUg8mooh .rough-node .label text,#mermaid-svg-HR0coQDVnUg8mooh .node .label text,#mermaid-svg-HR0coQDVnUg8mooh .image-shape .label,#mermaid-svg-HR0coQDVnUg8mooh .icon-shape .label{text-anchor:middle;}#mermaid-svg-HR0coQDVnUg8mooh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HR0coQDVnUg8mooh .rough-node .label,#mermaid-svg-HR0coQDVnUg8mooh .node .label,#mermaid-svg-HR0coQDVnUg8mooh .image-shape .label,#mermaid-svg-HR0coQDVnUg8mooh .icon-shape .label{text-align:center;}#mermaid-svg-HR0coQDVnUg8mooh .node.clickable{cursor:pointer;}#mermaid-svg-HR0coQDVnUg8mooh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HR0coQDVnUg8mooh .arrowheadPath{fill:#333333;}#mermaid-svg-HR0coQDVnUg8mooh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HR0coQDVnUg8mooh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HR0coQDVnUg8mooh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HR0coQDVnUg8mooh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HR0coQDVnUg8mooh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HR0coQDVnUg8mooh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HR0coQDVnUg8mooh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HR0coQDVnUg8mooh .cluster text{fill:#333;}#mermaid-svg-HR0coQDVnUg8mooh .cluster span{color:#333;}#mermaid-svg-HR0coQDVnUg8mooh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HR0coQDVnUg8mooh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HR0coQDVnUg8mooh rect.text{fill:none;stroke-width:0;}#mermaid-svg-HR0coQDVnUg8mooh .icon-shape,#mermaid-svg-HR0coQDVnUg8mooh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HR0coQDVnUg8mooh .icon-shape p,#mermaid-svg-HR0coQDVnUg8mooh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HR0coQDVnUg8mooh .icon-shape .label rect,#mermaid-svg-HR0coQDVnUg8mooh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HR0coQDVnUg8mooh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HR0coQDVnUg8mooh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HR0coQDVnUg8mooh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Pass
Fail
Code
Build
Run
Browser
Verify
Fix
Done

这意味着 Browser Automation 对 Coding Agent 来说,不再只是一个"浏览网页"的附加功能。

它正在成为:

让 Agent 从"会写代码"走向"能够真正验证和完成软件任务"的关键基础设施。

而从目前这些方案的架构演进来看,真正值得关注的方向并不是:

"谁的 Browser Tool 更多?"

而是:

"谁能够把 Browser、Tool、Skill、Verification 和 Coding Loop 真正连接起来?"

这才是 Browser-enabled Coding Agent 的核心竞争力。

相关推荐
Dawson Zhu3 小时前
为什么智能体 Agent 需要本体 Ontology
人工智能·语言模型·架构·制造·agi
重庆小透明3 小时前
深入探寻微服务【第四篇微服务监控实战】
微服务·云原生·架构
重庆小透明3 小时前
深入探寻微服务【第五篇微服务限流实战】
微服务·junit·架构
fthux3 小时前
装闭 RenoPit 源码解析(10):AI如何审查装修合同与报价单
人工智能·ai·开源·github·open source·renopit
慌途L4 小时前
Open Code Review 详解:阿里巴巴开源 AI 代码审查工具
ai·ocr·代码规范·code review·ai代码审查
JaydenAI4 小时前
[基于AgentEvals的自动化评估-04]全面优化面向LangGraph的轨迹评估[下篇]
ai·langchain·agent·evaluation·openevals
谢文峰4 小时前
Task Dispatch:基于 Codex 原生会话的任务分发 Skill
架构
hhb_6184 小时前
AI智能体调度微服务:高效任务分配方案
人工智能·微服务·架构
灵析表格4 小时前
灵析表格财务函数深度实用性分析与实操教程
开发语言·ai·json·excel·wps