功能概览

为什么 Zapvol 需要一个 Chrome 扩展作为 BUA 的一等公民、它解锁了什么能力、和云端 headless 浏览器有什么区别

问题

Agent 能覆盖公开 Web 内容(搜索、抓取、结构化 API),但一碰到需要登录的站点就撞墙。Gmail、Notion、公司内部系统、银行后台、多租户 SaaS —— 这些都躲在 cookie、OAuth session 和 MFA 后面,agent 拿不到。

常见解法是云端 headless 浏览器(Browserbase、Steel、自建 Playwright 集群)。这些方案对公开 Web 自动化很好,但对 需要用户登录态的任务就无能为力 —— “读我的日程”“从这个门户导出我的发票” 这类任务,用户的 session 在用户自己的浏览器里,云端 worker 根本没有。

答案 —— Browser Use Agent (BUA)

Zapvol 搭配一个 Chrome MV3 扩展,让 agent 在用户已登录的浏览器里执行操作。扩展把 agent 发出的高层动作代理成对用户显式授权过的 tab 的 Chrome DevTools Protocol (CDP) 命令。这和 Anthropic 的 computer-use 工具是同一个能力模式,只是作用域限定在单个已登录的浏览器 tab 而不是整个远程桌面。

Browser Use Agent (BUA) Agent 动作 → 扩展 → 用户已登录的 tab Zapvol Agent 后端 (服务端 / 桌面端) —— 运行 agent loop,选择下一个动作 WebSocket —— 已配对的连接 Chrome Extension (MV3) 后台 Service Worker —— 每次动作前校验 allowlist + session TTL CDP Input.dispatchMouseEvent / dispatchKeyEvent → event.isTrusted = true 用户已登录的 Chrome tab 用户自己的 cookie / OAuth / MFA —— 完整可用 Chrome 始终显示 "Zapvol Browser Bridge is debugging this browser" 黄条 —— 不可屏蔽

为什么需要专门的扩展

替代方案为什么不适合这个场景
云端 headless Playwright (Browserbase 等)在干净 profile 中运行——拿不到用户的 cookie / MFA 状态
Native messaging host需要单独安装二进制 + plist 注册
Bookmarklet / 页面注入脚本伪造事件过不了 event.isTrusted 校验——见下文
应用内嵌 Electron webview不复用用户的默认 Chrome profile;要求用户在第二个浏览器重新登录

为什么必须用 CDP,而不是页面注入脚本

现代登录态站点(Gmail、Google Accounts、大多数企业 SaaS)把敏感输入处理函数用 event.isTrusted === true 兜底。任何由页面 JavaScript 合成的事件 —— element.click()、手动构造的 MouseEvent、bookmarklet —— 到达时 isTrusted = false,会被静默忽略。

只有两种事件源能产生受信任事件:用户真实硬件,以及 chrome.debuggerInput.dispatchMouseEvent / Input.dispatchKeyEvent CDP 命令。第二条路只有安装了的、带 debugger 权限的 Chrome 扩展能走。这一个约束就排除了上表所有其它方案,也是 BUA 必须以扩展形态交付(而不是 agent 调用的某个库)的根本原因。

内部工具,UX 优先

BUA 只面向员工,不对公众开放。设计上优先静默、零摩擦执行 —— 没有 per-domain 授权弹窗、没有 session 倒计时、 没有 Approve 按钮。若内部产品每次 action 都要员工点一下 trust,最终只会训练出盲目点击的肌肉记忆。取而代之的是三条不变量:

  1. 完整审计 (Full audit trail) —— 每次 session 的 start 和 end 都追加到 append-only 日志(sessionHistory, 1000 条上限,Options 页可见)。End 条目带 reason / durationMs / actionCount。并行地,session_started / session_ended / domain_blocked / tab_closed / global_stop 等 WS 生命周期事件流到后端做运营观测;每个 action 的出入由 agent 子系统以 task_milestone 事件单独记录。post-hoc accountability,不是 pre-consent。
  2. 用户主导急停 (User-initiated global kill) —— popup 唯一的红色 “Stop all” 按钮,点下立即 detach 所有 debugger、 结束所有 session,并发 global_stop WS 事件让后端短路所有在途请求。永远一键可达
  3. 干净生命周期 (Clean lifecycle) —— session 在以下情形自动结束:tab 关 / 系统 idle 30 min / 屏幕锁定 / Chrome 黄条 Cancel / SW 卸载 / blocklist 加入该 domain。没有 TTL 倒计时

只要扩展挂着调试器,Chrome 就会显示它原生的 “Zapvol Browser Bridge is debugging this browser” 黄色提示条。 扩展代码无法屏蔽 —— 把它当作特性:员工持续看得到 agent 在远程控制浏览器。员工 onboarding 讲一次即可 (“看到黄条 = BUA 活跃;点 Cancel 可停”)。

有意不做的事

  • 没有 per-domain allowlist UI —— 默认任何域可访问。Options 里有 blocklist(默认为空),用于显式拒绝 (银行、薪酬、合规敏感工具),每次 action 前都检查。
  • 没有 Approve / Trust 按钮 —— popup 是活动监视器,不是授权面板。
  • 没有 TTL 倒计时 —— session 随 tab 存活,idle / lock 仍会清理。
  • 没有 “Trust this site” floating-ball 提示 —— floating ball 只在 agent 在该 tab 活跃时渲染;闲置时完全不挂载。

若未来需要对外版本,需另行加回 consent UI 层 —— 属于独立产品,不是本包的重配置。Chrome Web Store 也不会接受当前这份 带 <all_urls> + 静默执行的内部版本。分发仅走内部:GitHub Release / IT 私有渠道。

工具表面 (Tool Surface)

主 agent 不直接看到 browser 工具。BUA 被封装成一个内建 subagent:主 agent 通过标准 task 工具带 subagent_type: "browser" 委派过去,浏览器子 agent 在独立上下文里跑多步循环(extract → 推理 → click → …),最后返回一份 summary。

browser 工具本身 —— 单工具 + 13 种 action 的判别联合(navigate、click、type、hover、evaluate、screenshot、extract 以及另外六个)—— 住在子 agent 的私有工具箱里。命名对齐 Browser Use,让 LLM 的既有熟悉度可以迁移过来。多步流程靠反复调用同一工具拼装,重试和取消语义保持简单。

为什么要这层封装:BUA 的最小有意义单元是”一个循环”,不是”一次调用”。典型的”抓 3 个候选人”任务会跑 17 次 browser action。如果主 agent 直接跑这个循环,每一步都要重送主对话上下文——成本随主对话长度线性放大。内建 subagent 给 BUA 独立的上下文,主线程保持干净:一次委派进去,一次 summary 出来。

完整的 action 列表、参数、返回、错误码见 Protocol;subagent 封装和上下文隔离细节见 Browser Subagent

用户看到什么

四个表面,都刻意做得显眼,但没有一个是 gatekeeper:

  • Chrome 原生黄色调试条 —— 系统级、不可屏蔽,只要扩展挂着就一直显示。
  • 扩展 popup —— 活动监视器:列出每个活跃 session(域名、tab、已执行动作数),一个红色 “Stop all” 全局急停按钮, 与 Zapvol 后端的连接状态,以及 BUA 窗口的 Show / Hide 切换。没有 Approve 按钮 —— popup 用于观察和停止, 不用于授权。
  • BUA 窗口 —— agent 自己开的 tab 都落在一个独立的最小化窗口里,用户主浏览器不被打扰,但一键就能调出来查看。
  • Floating ball —— 页面内的小指示器,仅在该 tab 有活跃 session 时渲染。点击可查看 agent 在此页的进度、 输入后续指令。闲置 tab 上完全隐藏。

用户和 agent 之间的契约一眼就能看清:在哪个站点、哪个 tab、做了几步、怎么关掉。多 session 语义和 BUA 窗口的不变量见 Session 模型

这页有帮助吗?