Playwright、Claude Code、Cursor、VS Code、OpenCode、OpenClaw,到底是如何让 AI 控制浏览器的?
表面上,它们都在做 Browser Automation。
但深入研究之后会发现,真正决定一个 Browser Agent 能力边界的,并不是它有多少个
click、type、screenshot工具,而是一个更加底层的问题:这个浏览器,到底是谁的?
对于 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
openclawprofile
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 等。官方文档也明确区分了 openclaw、user 和 chrome 三种典型模式。
可以把它理解成:
#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 的核心竞争力。