当前位置: 首页 > news >正文

[use agent-browser not playwright directly]

agent-browser 架构设计

🏗️  agent-browser 的架构┌─────────────────────────────────────────────────┐│            agent-browser MCP                    │├─────────────────────────────────────────────────┤│                                                 ││  ┌──────────────────┐      ┌────────────────┐ ││  │  @ref 缓存系统    │ ───▶ │  Token 优化    │ ││  └──────────────────┘      └────────────────┘ ││           ▲                                 ││           │                                 ││  ┌────────┴────────────────────────────────┐ ││  │           BrowserManager                │ ││  │  - launch()                            │ ││  │  - getPage()                           │ ││  │  - getSnapshot()                       │ ││  │  - getLocatorFromRef(ref)              │ ││  └────────────────────────────────────────┘ ││           ▲                                 ││           │                                 │├───────────┴─────────────────────────────────┤│            playwright-core                   ││  (浏览器自动化引擎)                          │└─────────────────────────────────────────────┘

📦 缓存机制详解

1️⃣ Snapshot(一次性抓取,建立缓存)

// 第一次调用 snapshot
browser_snapshot({ interactive: true })// 内部执行:
async getSnapshot() {const page = this.getPage();// 1. 用 Playwright 抓取页面const snapshot = await getEnhancedSnapshot(page, {interactive: true  // 只抓可交互元素});// 2. 缓存 ref 映射this.refMap = snapshot.refs;// refMap = {//   "e1": { selector: "button", role: "button", name: "登录" },//   "e2": { selector: "input[type='email']", role: "textbox", name: "邮箱" },//   ...// }// 3. 返回简洁的树结构return snapshot;
}

返回格式:

@e1 [button] "登录"
@e2 [textbox] "邮箱"
@e3 [textbox] "密码"
@e4 [checkbox] "记住我"
@e5 [link] "忘记密码"

2️⃣ 后续交互(使用缓存,省 Token)

// 用户说:点击登录按钮
browser_click({ element: "@e1" })// 内部执行:
async click(element) {// 1. 从缓存中查找const refData = this.refMap["e1"];// refData = { selector: "button", role: "button", name: "登录" }// 2. 用 Playwright 定位并点击const locator = this.getLocatorFromRef("e1");await locator.click();
}

💡 关键设计点

1. 一次性抓取 vs 多次查询

方式 Playwright MCP agent-browser MCP
获取元素 每次都用 selector 查询 DOM Snapshot 一次,缓存所有元素
Token 成本 每次查询都消耗 一次成本,多次复用

2. Ref 的生命周期

// 1. 导航到新页面
await browser_navigate({ url: "https://example.com" })// 2. Snapshot(建立缓存)
await browser_snapshot({ interactive: true })
// 返回:@e1, @e2, @e3 ...// 3. 使用 ref(从缓存读取)
await browser_click({ element: "@e1" })  // 从缓存获取
await browser_fill({ element: "@e2", text: "test" })  // 从缓存获取// 4. 页面导航后,缓存失效
await browser_click({ element: "@e5" })  // 假设这是链接,会导航// 5. 必须重新 snapshot
await browser_snapshot({ interactive: true })
// 返回新的 refs:@e1, @e2 ...(与之前不同)

3. 智能缓存失效

// src/browser/manager.ts 中的 ref 管理
export class BrowserManager {private refMap: RefMap = {};  // 缓存private lastSnapshot: string = '';async getSnapshot() {const snapshot = await getEnhancedSnapshot(page, options);// 每次 snapshot 都会更新缓存this.refMap = snapshot.refs;  // 覆盖旧缓存this.lastSnapshot = snapshot.tree;return snapshot;}getLocatorFromRef(refArg: string): Locator | null {const ref = parseRef(refArg);  // "e1" 或 "@e1"const refData = this.refMap[ref];  // 从缓存读取if (!refData) return null;  // ref 不存在或已失效// 用缓存的 selector 创建 locatorreturn page.locator(refData.selector);}
}

🎯 Playwright 作为底层引擎

agent-browser 完全依赖 Playwright 做底层操作:

操作 Playwright 原生调用 agent-browser 封装
启动浏览器 await chromium.launch() browserManager.launch()
获取页面 page.locator() browserManager.getLocatorFromRef("@e1")
点击 await locator.click() 同左
填写 await locator.fill() 同左
截图 await page.screenshot() 同左

agent-browser 没有重写自动化逻辑,只是加了缓存层。

📊 Token 节省的来源

传统方式(Playwright MCP):

每次交互 = 完整 CSS selector
click("#auth-container > div.login-wrapper > form > div:nth-child(5) > button")↑ 每个 token 都要传

agent-browser 方式:

第一次: snapshot(一次性成本,几百 token)
后续:   click("@e1")  ← 只传 2-3 个 token

✅ 总结

  1. 底层依赖:agent-browser 100% 基于 Playwright 实现浏览器自动化,未重写核心逻辑。
  2. 核心优化:通过 snapshot 一次性抓取页面元素并建立 ref-selector 缓存映射,替代每次交互都查询 DOM 的方式。
  3. Token 节省:首次 snapshot 付出一次性 Token 成本,后续交互仅需传递简短的 ref ID(如 @e1),大幅降低 Token 消耗,且页面导航后缓存会失效,需重新 snapshot。
http://www.jsqmd.com/news/403268/

相关文章:

  • AI-RAN Sionna开发者套件全解析:从入门到集群,开启无线通信与AI融合开发新纪元
  • AI原生应用领域自主代理的故障诊断与修复
  • Vue实现智能客服对话框与推荐问题展示:从架构设计到AI集成实战
  • 如何在WSL中设置AMD AI MAX 395的Rocm微调环境
  • Flink实时计算心智模型——流、窗口、水位线、状态与Checkpoint的协作
  • 百度AI智能客服Prompt设置实战:从零搭建高效对话系统的避坑指南
  • 2024提示工程安全趋势:加密传输机制的3个创新方向
  • 【GitHub项目推荐--Heretic:全自动语言模型去审查工具】⭐⭐⭐
  • 【GitHub项目推荐--Flet:Python全栈开发者的跨平台应用框架】⭐
  • 智能客服转人工:从架构设计到实战避坑指南
  • Node.js运维部署实战:从0到1开始搭建Node.js运行环境
  • 修复网页失效的css
  • 倒立摆系统MPC控制MATLAB代码功能说明
  • 近况报告(II)
  • 北京大兴区附近回收黄金店实测,在跑了三家之后,我更看重这三点
  • 基于MCP的智能客服系统搭建:从架构设计到性能优化实战
  • 客服在线会话智能体流程图:从零构建高可用对话系统的实践指南
  • 网络抓包(hooker 无处不在的眼睛)
  • 基于西门子PLC s7-1200的往返小车的控制设计
  • 椭圆周长问题
  • 基于扣子实现智能客服系统的架构设计与性能优化实战
  • 智能客服系统技术路线解析:从架构设计到生产环境实践
  • 基于AI的物业管理智能客服系统开发实战:从架构设计到性能优化
  • 写代码自动分析简历关键词,匹配招聘要求,颠覆海投没回音。
  • [AI提效-14]-豆包“帮我写作”进阶功能详解:全文修剪与重构三大核心能力
  • 企业邮箱怎么申请注册?自己办还是找服务商,一篇说清楚
  • 公司级智能客服系统入门指南:从零搭建到核心功能实现
  • 开源客服智能体系统入门指南:从零搭建到生产环境部署
  • 智能客服实体填槽技术实战:从原理到避坑指南
  • RStudio是一个功能强大的R语言开发环境,其简洁直观的界面使得数据科学家能够更加高效地进行数据分析和可视化