agent-browser:一条命令一步操作,Vercel 的浏览器 CLI 拿下 4.8 万星

agent-browser:一条命令一步操作,Vercel 的浏览器 CLI 拿下 4.8 万星

我让本地的 agent 打开 example.com,它收到的全部页面信息是一行文本:- link "Learn more" [ref=e1]。

没有截图,没有 XPath,没有一坨 HTML。想点这个链接,下一句命令是 agent-browser click @e1。

vercel-labs/agent-browser 2026-01-11 创建,到今天 2026-11-10 攒了 48,953 star、3,395 fork,548 个未关闭 issue(GitHub API 的 open_issues_count 含 PR),主语言 Rust,Apache-2.0,npm 上 138 个版本,当天刚发布 0.42.0。它的自我描述只有六个词:Browser automation CLI for AI agents。

这篇按四个问题走:它到底是什么、怎么跑起来、哪些机制值得做 Agent 工具的人抄、以及和 Playwright MCP、browser-use 这些同类怎么选。先给一个反直觉的结论:它最大的创新不在"能开浏览器",而在它决定不给你一个 MCP 工具集。

本文提纲

  1. 是什么:给 Agent 的浏览器遥控器,不是爬虫框架
  2. 怎么用:装、开、看快照、点引用,以及四个容易踩的坑
  3. 值得学什么:五个机制层面的设计
  4. 同类比较:Playwright MCP、browser-use、Stagehand 怎么选

是什么:给 Agent 的浏览器遥控器,不是爬虫框架

一句话定位:agent-browser 是一个原生 Rust 编写的命令行工具,把浏览器拆成"一条命令做一个动作"的粒度,Agent 每步读一小段无障碍树(accessibility tree),拿到元素的引用 @e1,再对引用执行动作。

先划掉三个常见误解。

它不是 MCP server。 虽然它确实带 agent-browser mcp 子命令,可以起一个 stdio MCP server,但官方主推的接入方式是 CLI 加一份版本匹配的说明文档。MCP 在这里是"给已经只有 MCP 通道的宿主用的兼容出口",不是主路径。

它不是一个自己会规划的 Agent。 它不做"给一句自然语言,自己点完整个流程"这种事,planner 在 browser-use 那一侧。agent-browser 只负责执行和反馈,决策权留给外面的 Claude Code、Codex 或你自己的脚本。这个分工是它整个设计的地基。

它不是爬虫框架。 没有并发抓取调度、没有分布式队列、不绕过反爬。它就是一个有状态的浏览器遥控器,做的是"登录、点按钮、填表单、验证结果"这类需要真实交互的活。

那它解决谁的痛?三种旧路径的成本:

  • 截图喂视觉模型:一张 1280×720 的 PNG,token 开销不谈,你还得有个视觉模型,而且模型要自己从像素里找坐标。改一次布局,坐标全变。
  • MCP 工具集:每个工具都带 JSON Schema,tools/list 还可能分页。工具越多,光"有什么工具"就吃掉 context 一大块,而且这些 schema 每轮对话都在。
  • 每步起一个新的浏览器进程:状态丢失、cookies 丢失、冷启动几十上百毫秒,复杂流程跑一半断了要重来。

agent-browser 的答案是把这三样全砍掉:页面表示换成文本、工具描述按需加载、浏览器由一个常驻进程持有。

MERMAID_BLOCK_0

第一句命令会拉起一个后台 daemon,daemon 通过 Chrome DevTools Protocol 控制浏览器。之后每条命令只是往 socket 里发一行请求,浏览器一直开着。默认是 headless 的 Chrome for Testing,空闲一小时没有命令才会自己退出。

怎么用:装、开、看快照、点引用

安装两步:

npm install -g agent-browser
agent-browser install           # 首次下载 Chrome for Testing

Homebrew 也可以(brew install agent-browser,再跑一次 install)。Linux 上 agent-browser install --with-deps 会顺带装系统库。不想装就直接 npx agent-browser open example.com。

最小闭环五条命令:

agent-browser open example.com
agent-browser snapshot -i       # 只看可交互元素,每个带 ref
agent-browser click @e1         # 用上一条快照里的 ref
agent-browser get url           # 验证结果
agent-browser close

官方 README 里 example.com 的快照是一行 - link "Learn more" [ref=e1]。我自己在本机跑了一遍(本地装的是 0.24.1,比最新 0.42.0 旧不少,输出格式可能有细微差别),拿到的是:

✓ Example Domain
  https://example.com/

snapshot 返回的是多语言版页面的六段 StaticText,最后一行才是 - link "Learn more" [ref=e1]。也就是说,无障碍树给的是页面结构,不是像素:段落、链接、输入框、按钮,各自带角色名和引用。想省 token 就加 -i 只留可交互元素,加 -c 去掉空的容器节点,-d 3 限深度,-s "#main" 限定子树范围。

引用之外,普通选择器也能用。官方支持 CSS、文本、XPath 和语义定位:

agent-browser click "#submit"
agent-browser fill "#email" "test@example.com"
agent-browser find role button click --name "Submit"

find 这组命令(role、text、label、placeholder、alt、testid、first、last、nth)是给 Agent 用的降级路径:当页面结构变化导致 ref 失效、又不想重新读整棵树时,按语义找更稳。

等待有五种条件,别一股脑用 networkidle:

agent-browser wait @e1
agent-browser wait --text "Welcome"
agent-browser wait --url "**/dashboard"
agent-browser wait --fn "window.appReady === true"
agent-browser wait --load domcontentloaded

文档明确提醒:SSE、WebSocket、轮询和长轮询会让 networkidle 永远等不到。这是浏览器自动化最经典的坑之一,它把话说在前面了。

命令可以用 && 串成一次 shell 调用,因为浏览器状态在 daemon 里,链式调用是安全的:

agent-browser open example.com && agent-browser wait --load load && agent-browser screenshot page.png

需要解析中间结果时再拆开跑,比如先 snapshot 拿到 ref、再决定点哪个。脚本里要结构化结果就加 --json;调试时加 --headed 打开有头窗口。

四种接入形态,按你的宿主选

  • CLI + 技能文档(主推):agent-browser skills get core 输出一份和当前二进制版本匹配的操作说明。适合 Claude Code、Codex 这类本身有 shell 的 agent。
  • MCP(兼容):agent-browser mcp 起 stdio server,给只有 MCP 通道的客户端用。代价是工具 schema 会占 context,这也是它默认不主推 MCP 的原因。
  • 接管已登录的 Chrome:--cdp 或 --auto-connect 连上你正在用的浏览器,省掉扫码登录和二次验证。做内部系统自动化时这条最实用。
  • 换引擎或换远端:--engine lightpanda 或 obscura 换轻量引擎;--provider browserbase 之类把浏览器放到云上;还能驱动 iOS 模拟器里的 Mobile Safari。

四个容易踩的坑

第一,ref 有时效。 @e1 描述的是快照那一刻的页面。导航或 DOM 变化之后,旧 ref 不能再用,必须重新 snapshot。它不会帮你猜"应该还是那个按钮"。

第二,点击失败是显式失败。 目标被遮挡(比如 cookie 同意横幅)、隐藏、禁用或在视口外时,click 直接报错,而不是返回一个"成功"。官方建议是关掉遮挡元素、重新快照、重试。这个语义比"假装点到了"有价值得多,后面还会展开说。

第三,daemon 会自己下班。 默认空闲一小时关掉 headless 浏览器并退出。没配 session persistence 的话,重新拉起就是新会话、新状态。长流程的任务要显式配持久化。

第四,安全默认是放开的。 文档写得很直白:默认对导航、动作、输出都不做限制。要收紧得自己开 --allowed-domains、--action-policy、--confirm-actions,credential 有单独的 auth vault。给 Agent 开浏览器这件事,默认配置和你要的隔离级别基本不是一回事。

值得学什么:五个机制层面的设计

一、把"工具清单"从 context 里挪走

MCP 的隐性成本很多人没算过:工具越多,schema 越长,而 schema 是每一轮都在 context 里的固定开销。agent-browser 的选择是反过来:CLI 只暴露一个入口,具体能力靠文本说明书按需加载。

skills get core 给核心循环,skills get core --ref commands 只给命令表,--full 才带上全部参考和模板。仓库里 evals/context-footprint.ts 就是专门量这件事的:它分别测薄 stub、skills get core --full、MCP 的 initialize、默认工具集和 --tools all 的字节数与近似 token(ceil(len/4))。把"上下文预算"当成可以跑脚本测的指标,而不是拍脑袋讲体感,这个做法本身就值得抄。

顺带一提,evals/ 里还有 reference-routing 这一类用例,专门测 Agent 会不会"只加载需要的那一份 ref",而不是偷懒 --full 全量拉。这已经是在给 Agent 的使用习惯做回归测试了。

二、ref 生命周期 + 显式失败,把验证责任推回 Agent

Playwright 那套 auto-wait 和 actionability 检查很强,但它的反馈是给写测试的人看的。agent-browser 把同样的检查翻译成 Agent 能读的信号:元素不可见、被禁用、在视口外、被别的元素盖住,就失败,并让你重新快照。

这带来一个很干净的循环:snapshot → act → 再 snapshot 验证。为了让第三步便宜,它给了 diff snapshot:

agent-browser diff snapshot                    # 和本会话上一次快照比
agent-browser diff snapshot --baseline before.txt
agent-browser diff screenshot --baseline before-deploy.png

输出是行级 diff,+ 新增、- 删除。官方示例里填完表单后拿到的是"3 additions, 2 removals, 3 unchanged",还顺带看到 Submit 按钮多了 [disabled]、多了个 Sending... 状态。对 Agent 来说,这比再读一遍整棵树省太多,也比让模型自己比对两次快照靠谱。

三、文档作为二进制资产:skills get 解决版本漂移

Agent 工具最常见的翻车方式不是功能不行,是文档和版本对不上:模型记住的是老命令,装的是新 CLI。

agent-browser 的做法是把技能文档打进二进制(Cargo 依赖里有 rust-embed,仓库里有 skill-data/core/SKILL.md),从 skills.sh 装进 Agent 的那个 SKILL.md 只是极薄的一层 stub,只负责让 Agent 知道"遇到浏览器任务先跑 agent-browser skills get core"。真正的命令、工作流、注意事项全部由 CLI 在运行时吐出来,所以永远匹配已安装的版本。

这个结构的代价是每次用都要多一次命令调用;收益是模型不用靠训练记忆猜 API。对迭代了 138 个版本的 0.x 项目,这个收益是决定性的。

四、会话、设置与安全状态的持久化模型

--session 每个会话一套独立的 daemon、浏览器、cookies、历史、登录态。命令可以带回设置,daemon 拿它和当前会话对比后只应用差异:

  • 一样的值什么都不做,所以每轮都带 --profile ./work 不会导致反复重启浏览器;
  • 超时、action policy、确认动作这类运行时设置原地生效;
  • --profile、--args、--headed、--proxy、--state、--allowed-domains 属于启动设置,改了才需要重启浏览器,但 daemon 本身不重启。

更细的一层:三个安全设置(--allowed-domains、--action-policy、--confirm-actions)会写进 socket 旁边一个仅属主可读的 <session>.settings 文件,在生效前落盘。这样空闲退出、崩溃、被杀、升级都不会把沙箱限制悄悄丢掉;--allowed-domains 甚至在启动失败后仍然保留,确保限制只会收紧不会意外放宽。这种"安全配置不能因为进程重启而失效"的考虑,是做 Agent 沙箱的人必须过的关。

五、从 Node/Playwright 全量换成 Rust,以及知道什么优化不了

0.23.0(2026-03-27)是分水岭:删掉整个 Node.js/Playwright daemon,改成 100% 原生 Rust,不再需要 Node 运行时和 Playwright 依赖。动机写在 benchmarks 的 README 里:daemon 冷启动、常驻内存(RSS)、分发体积。

有意思的是它对自己 benchmark 的解读很克制:命令延迟主要被 CDP 往返支配,换语言对单条命令的延迟改善通常很小,要看标准差才能分清真实差异和噪声;真正能看出差别的是冷启动、daemon RSS 和分发体积,因为两种实现驱动的是同一个 Chrome。

benchmarks/ 的做法也值得看:在 Vercel Sandbox 微虚拟机里跑两个阶段——npm 最新版和从源码 cargo build --release 的版本,同一套场景(navigate、snapshot、screenshot、eval、click、fill、agent-loop、full-workflow),带 warmup、多次迭代和标准差。仓库里没有公开的结果文件,所以我只能说有这套测试装置,不报任何延迟数字。这点很重要:48k star 的仓库也很少有人真的去看它有没有公开对比数据。

同类比较:四种工具的位置

先声明口径:下面 star 数全部是 2026-11-10 同一时刻从 GitHub REST API 取的,只能说明热度,不能说明能力。这几款工具也没有公开的同一套 benchmark,所以本文不比较延迟和准确率。

工具 形态 谁做决策 context 成本 适合谁
agent-browser(48,953 star,Rust,Apache-2.0) CLI + 后台 daemon 外层 Agent(Claude Code / Codex / 脚本) 一份按需加载的文本说明 终端里的编码 Agent,要多步交互、要复用登录态
Playwright MCP(39,412 star,TS,Apache-2.0) MCP server MCP 客户端里的模型 工具 schema 常驻 已经只有 MCP 通道的宿主,想要强约束的工具调用
Chrome DevTools MCP(55,061 star,TS,Apache-2.0) MCP server MCP 客户端里的模型 工具 schema 常驻 重点是性能、网络、控制台诊断
browser-use(120,540 star,Python,MIT) Python 库 自带 planner,模型自己跑完 prompt + 历史,按步累积 想交付"一句话跑完整个任务"的 Python 项目
Stagehand(25,992 star,TS,MIT) TS SDK(基于 Playwright) 你的代码 + act/extract/observe 原语 每次调用的局部上下文 自己写 Agent 循环、要细粒度控制的 TS 工程

几个判断:

如果你用的是 Claude Code、Codex 这类有 shell 的编码 Agent,选 agent-browser。 它的整个形态就是为这个场景设计的:一步一条命令、输出能塞进 stdout、文档随版本走、浏览器常驻。反过来,如果你的宿主只有 MCP 通道,硬塞 CLI 反而多绕一层。

如果你已经在 MCP 生态里,Playwright MCP 更"正统"。 它同样有基于无障碍树的 snapshot 和元素引用,工具 schema 的强约束在结构化调用上有优势。代价是工具清单的 context 开销,agent-browser 就是在跟这笔账较劲。

如果你要的是"自动完成",browser-use 那一侧。 它自带规划和执行循环,你给任务它自己走;代价是你把决策权交出去了,出错时也更难定位是哪一步的判断错了。agent-browser 把决策权留给外层 Agent,可观测性和可控性更好,但也意味着外层模型得更靠谱。

如果目标是确定性的 E2E 回归测试,这些都不是答案。 直接写 Playwright 用例:断言明确、可并行、进 CI。agent-browser 的 diff snapshot 适合"Agent 改完东西自己验一眼",不适合替代测试框架。

如果痛点是页面为什么慢、哪个请求挂了,去看 Chrome DevTools MCP。 它的重心在 trace、性能面板、网络诊断,不在通用交互。

它的失效边界也说清楚:每步一次 shell 往返,虽然能 && 串联,但比一次 MCP 调用多一层进程通信;snapshot 给的是结构不是视觉,纯 canvas、纯图片、高度依赖视觉判断的页面会失灵,这时候只能退回 screenshot;0.x 阶段 10 个月发了 138 个版本,548 个未关闭 issue,命令面铺得很宽(README 里列了 12 组命令),意味着 API 还在动,别把它当成稳定基础设施来设计长期流程。

agent-browser 的取舍很清楚:页面结构交给文本,动作边界交给 Agent,文档交给版本,会话交给 daemon。四个决定相互咬合,少一个这套循环就散架。48,953 个 star 里有多少是冲着 Vercel 的名头来的不好说,但 cli/src/commands.rs 和 skills.rs 这两个文件本身值得读一遍。

参考资料

你给 Agent 开浏览器时,是自己写每一步,还是让它自己跑?遇到过最坑的页面是哪种?评论区聊聊。觉得有用点个赞,让更多做 Agent 的同学看到。


作者: itech001
来源: 公众号:AI人工智能时代(the-ai-era)
网站: https://www.theaiera.top/
关注每日最新AI新闻和技术博客,主页有更多的文章的AI 技术参考:https://www.theaiera.top

本文首发于 AI人工智能时代,转载请注明出处。

posted @ 2026-11-10 22:33  iTech  阅读(0)  评论(0)    收藏  举报