返回博客2026年8月10日1 分钟阅读

Vercel 的 Agent Browser,让 Agent 操作网页不再靠猜

摘要

Vercel Labs 的 Agent Browser 在 skills.sh Hot 出现安装量上涨。它让 Agent 根据当前页面的无障碍树选择元素,再用会话、安全策略与流式预览处理真实网页里的变化和风险。

网页自动化最容易演示,也最容易出事故。打开页面、找到按钮、填完表单,这几步在视频里看起来像是 Agent 已经获得了一双手;真正放进工作流后,遮罩层、页面更新、登录状态、慢网络和误操作确认,才是决定它能否继续跑下去的部分。

本次检查中,skills.sh Hot 显示 Vercel Labs 的 agent-browser 有 139 次安装,较对应的前一窗口增加 53。这是 skills.sh 的安装信号,不是 GitHub stars。GitHub API 显示仓库累计 40,276 stars,近期仍有代码推送。Vercel 是 Next.js 的创建者;最新 v0.33.2 release 发布于 8 月 2 日。

这些数字不足以说明一切,却说明 agent-browser 正在被更多 Agent 工作流接入。我会借它梳理一个更具体的问题:浏览器对于 Agent,为什么不该只是一组 click 命令,而应当是有状态、有边界、能观察失败的运行时。期望对大家有所帮助。

不是“找到选择器”,而是保留一次观察结果

agent-browser 是一个以 Rust 编写的浏览器自动化 CLI。它能用 CSS 选择器,也能用角色、标签等语义定位器;但 README 给 Agent 的默认路径是先拿到无障碍树,再使用树里的引用。

agent-browser open https://example.com
agent-browser snapshot -i
agent-browser click @e2
agent-browser fill @e3 "hello"

snapshot -i 会输出当前页面的交互元素,并给出类似 @e2 的引用。模型不是猜一个可能已经失效的 button:nth-child(3),而是先根据角色、可访问名称和当前页面状态选择一个已观察到的元素。页面改变后重新 snapshot,旧引用也不该继续沿用。

这听起来只是接口设计,其实是在给 Agent 加一条很朴素的纪律:先看,再操作,再确认当前页面是否已经变了。项目还会在点击点被遮罩层覆盖时提前失败,并把覆盖元素报出来。README 的建议同样是先处理遮罩层,再重新获取 snapshot。

flowchart LR
  A[打开或恢复会话] --> B[读取无障碍树]
  B --> C[选择引用 @eN]
  C --> D[点击或填写]
  D --> E{页面是否变化}
  E -->|是| B
  E -->|否| F[读取结果或结束]

这比“让模型自己看着页面点”少了一些魔法感,却多了一种可以复盘的状态转换。对测试登录流程、后台配置、表单录入这类任务,后者更重要。

一个会活下来的浏览器进程

很多浏览器工具把每个命令当作一次短暂调用。agent-browser 的结构不同:CLI 和 Rust daemon 分开,第一次命令启动 daemon,后续命令复用同一个浏览器和会话。它直接走 Chrome DevTools Protocol,不需要 Node.js 常驻。架构说明 写得很明确。

这让“打开 - 登录 - 跳转 - 截图”不必在每一步重新创建浏览器,但也把资源回收变成一个运行时问题。项目默认在一小时没有命令或 dashboard 输入后,保存配置的恢复状态、关闭浏览器并退出;下次命令再启动。8 月 2 日的发布还处理了另一类真实故障:慢客户端看直播画面时,点击和键盘事件不能排在旧帧后面等着发送。

运行时问题agent-browser 的处理
页面已经变化重新获取 snapshot,再选择当前引用
Agent 非正常退出空闲超时后关闭 daemon 与浏览器
人需要看过程WebSocket 流式预览与本地 dashboard
慢网络积累旧画面可用 ack 节流,只保留最新帧
Chrome 丢弃后台标签页切换时尝试恢复,并在结果里标出 revived

这里最有意思的是流式预览的处理。v0.33.2 增加了每个客户端的帧率与质量控制,也支持 ack 节流:客户端没有确认前,一次只接收一帧,新帧会替换未发送的旧帧,而不是把过期画面排成队。release note 记录了其测试结果:在 400 KB/s 链路、客户端停滞 8 秒的情形下,默认推送会留下 436 帧旧画面,而 ack 模式只留下 1 帧。

这不是一个为了“看起来实时”的细节。只要人和 Agent 同时盯着浏览器,过期画面会直接改变人的判断,也可能让点击落在一个已经变化的页面上。

浏览器内容不是可信上下文

让 Agent 打开网页,还有一个常被轻描淡写的风险:网页文字本身是外部输入。一个页面可以诱导模型忽略原任务、索取凭据,或把操作转向不该去的域名。agent-browser 没有声称靠模型识别这些内容,而是提供几层可组合的限制:给页面输出加内容边界标记、限制最大输出长度、限制可访问域名,以及为敏感类别设置静态策略或人工确认。安全文档 与 README 的 Security 部分 都列出了这些选项。

尤其值得注意的是 --allowed-domains。它不只阻止顶层跳转,还会拦截不在白名单内的脚本、图片、fetch、WebSocket、EventSource 与 sendBeacon 请求,并在可控的 Chromium 会话中关闭 WebRTC 的绕行路径。代价也写得很清楚:接入已有 Chrome、复用个人 profile、恢复 state 文件等模式,无法在页面脚本执行前施加同样的约束,因此该参数会拒绝这些不安全组合。

安全功能没有替代部署决策。状态文件可能包含会话 token;README 明确要求不要提交它们,并提供 AES-256-GCM 的静态加密。自动操作付款、删除、发布、改权限等页面前,仍然应该把确认留在人手里。

值不值得接进自己的 Agent

如果你的 Agent 只需要抓一篇公开文章,HTTP 抓取通常更简单。agent-browser 的价值出现在需要真实浏览器状态的地方:登录后的页面、前端渲染后的内容、需要上传文件的表单、需要把测试过程交给人查看的 QA,或者希望通过 MCP server 把一组浏览器能力交给 AI 编程工具。

第一次接入可以从一个没有破坏性的任务开始,例如在测试站点走一遍注册流程、核验后台页面的无障碍问题,或把一条手工回归测试录成可重复的命令序列。随后再逐步加上:

  • --allowed-domains,并把页面依赖的 CDN 一并列入
  • --content-boundaries 与 --max-output,避免网页内容直接淹没模型上下文
  • --confirm-actions 或 action policy,先覆盖下载、执行脚本和会产生外部影响的操作
  • 独立 session 与加密的状态存储,不复用日常个人浏览器 profile

它把浏览器 Agent 从“模型会不会点按钮”的问题,拉回到了更可靠的工程问题:状态从哪里来,页面变化后怎样重新观察,外部内容在哪里停止,敏感动作由谁确认。把这些边界先放进去,浏览器才更适合成为 Agent 的执行环境。


相关文章

最近一封 · Sample

OpenRig 冲上 Trending:把 Claude Code 和 Codex 编成一支队伍

“OpenRig 在 GitHub Trending Today 获得 622 个 stars 的窗口信号。它用可恢复的队列、席位与权限记录,把 Claude Code 和 Codex 放进同一套多 Agent 工程流程。”

—— william

Letters

来信

里面装的是

  • 新文章 — 写完一篇就寄一封,不攒货
  • 这周读到的、看到的、好用的工具
  • 正在折腾的实验,附带翻车记录

约莫 1–2 周一封 · 随时退订

合作伙伴

CompeteMap — 英国及爱尔兰学生竞赛一站式搜索

数学、编程、科学、写作等各类竞赛信息汇总,支持按年龄和科目筛选,再也不错过报名截止日。

准备开始了吗?

先简单说明目标,我会给出最合适的沟通方式。