凌晨两点,你的 Agent 又卡在同一个按钮上。截图发回模型,坐标算出来偏了十几像素,点下去没反应,再截图,再算,再点。三轮下来 token 烧掉几千,按钮背后的弹窗还是纹丝不动。这不是模型笨,是交互协议本身就不适合机器:截图是给人看的,坐标是给鼠标用的。十一月八日,Vercel 实验室的 agent-browser 冲上 GitHub 趋势总榜第一,它给出的答案很干脆------别让 Agent 看图,把整页读成一份带编号的纯文本。这一次,我把它的文档从头到尾读了一遍,看看它到底做对了什么。
一个 Rust 二进制,把浏览器留在后台
先把事实摆齐。agent-browser 是 Vercel Labs 的开源项目,仓库建在 2026 年 1 月 11 日,到我写这篇时一共 46,578 个 star、3,192 个 fork,Apache-2.0 协议,累计发了 120 个 release。它不是 Python 库,也不是 Node 脚本,而是一个 Rust 写的原生命令行程序,npm 包只负责按平台挑对应的二进制,macOS 的 ARM64 和 x64、Linux 的 glibc 和 musl、Windows x64 全都覆盖。
它的工作方式和常见自动化框架有一个本质区别:浏览器在执行间隙不退出。第一条命令到达时,一个后台 daemon 被拉起来,通过 Chrome DevTools Protocol 控制浏览器;之后每条命令都是一次短促的 shell 调用,发完就结束,浏览器留在原地等下一条。这个设计直接决定了使用手感------Agent 的每一步都是独立命令,状态在 daemon 里,不在调用方的进程里。
会话隔离也按命令行习惯做。每个 --session 参数对应一套独立的 daemon 加浏览器,互不干扰。无头模式下,一小时没有新命令,daemon 会先保存状态再退出,前提是你配置了 session persistence;不配就直接关。批量任务可以开一堆互不串味的会话,跑完让它们自然死亡,不需要写回收逻辑。
默认浏览器是 Chrome for Testing,第一次用先跑 agent-browser install 下载。不想多装浏览器也行,--cdp 和 --auto-connect 可以直接接管本机已经在跑的 Chrome,复用里面的登录态。对需要真实会话的场景,比如要带着已有 cookie 进后台系统,接管比新起一个干净浏览器实用得多。对主浏览器里躺着几十个登录态的人,这条几乎是刚需:不用导出 cookie,不用重新扫码,Agent 直接继承手里的会话。当然这也意味着权限边界要自己划清,接管命令落在谁手里,谁就拥有了那台浏览器里的一切。
snapshot 给每个元素发一个编号
核心交互协议只有三步。agent-browser snapshot 把当前页面读成一棵紧凑的无障碍树,以文本形式返回,每个可交互元素后面跟一个 ref,比如 @e1。Agent 看着这份文本决定动作,然后 agent-browser click @e1 作用在那个编号上,完事再 snapshot 一次确认结果。加个 -i 参数,snapshot 只返回可交互元素,输出更短。
这套协议省 token 的逻辑很直接。截图方案里,每一轮交互都要把整张图塞进模型上下文;ref 方案里,上下文里只有一份结构文本加几个编号。README 给的示例页面,整个 snapshot 只有一行:一个 Learn more 链接和它的 ref。真实页面当然不会这么短,但页面越复杂,结构文本相对截图的压缩率越高,这一点对长流程任务几乎是决定性的。
协议里有两条规则必须记牢。第一条:ref 描述的是拍快照那一刻的页面,导航或者 DOM 变化之后,旧 ref 全部失效,必须重新 snapshot 再用。第二条:click 会诚实地失败------目标被隐藏、被禁用、在视口外、或者被别的元素盖住,比如 cookie 同意横幅,命令直接报错而不是假装成功。想继续,就先处理遮挡物,重新拍快照,再点。
诚实失败这一条的价值被低估了。截图加坐标的方案里,点没点中经常要靠下一轮截图才能发现,错误会一路累积到流程末尾才爆。这里失败是即时的、带原因的。对无人值守的 Agent 流程,失败信号的及时性远比单次成功率重要,因为恢复逻辑可以立刻介入。
daemon 挂在 CDP 上,会话一小时不用就自己关
架构拆开看是三件套:命令行进程、后台 daemon、被控浏览器。命令行只是个传话的,真正维持状态的是 daemon,它通过 CDP 长连接驱动浏览器。所以你可以从任何能执行 shell 的地方驱动浏览器------cron 脚本、CI 管道、某个 Agent 框架的工具函数,调用方都不需要自己常驻一个进程。
引擎不止 Chrome 一家。--engine 可以切到 Lightpanda 或者 Obscura,前者是为自动化场景重写的轻量浏览器,资源占用和启动速度都冲着批量任务去。要在 iOS Simulator 里驱动 Mobile Safari 也有专门支持。不想自己维护浏览器的话,云厂商接入口已经留好:Browserbase、Browserless、Browser Use、Kernel、AgentCore 五家都写在文档里。
可观测性这组命令值得单独说。console 和 errors 拿页面日志,trace 和 profiler 做性能采样,vitals 读 Web Vitals,react 专门探 React 组件树,a11y 查无障碍问题。capture 这组更偏取证:screenshot、pdf、record 录屏、download 抓下载、diff 对比两次快照。页面和网络状态那组,cookies、storage、network、clipboard、eval 都齐。
安全边界是写进文档的一等功能:auth vault 存凭据,domain allowlists 限制能访问的域名,action policies 约束允许的动作,content boundaries 划清内容边界。会话和鉴权这组命令里还带了 confirm 和 deny,明显是给需要人工确认的敏感动作留的口子。把治理做成命令面的一部分,而不是让用户自己去包一层,这个取舍很对企业场景的胃口。
这套架构还有一个隐性好处:排查问题时分层清晰。命令行报错归命令行,daemon 的行为看日志,浏览器侧的异常走 console 和 errors 命令捞。三层各自独立,不会像一体化框架那样,一个超时把整条链路的现场全毁掉。doctor 命令专门做环境自检,装完先跑一遍,缺什么依赖一眼就能看到。
skills、MCP 和五家云浏览器
给 Agent 用,接入方式有三种,层层递进。最薄的一层是在 AGENTS.md 里写一句话:浏览器自动化用 agent-browser,第一次用之前先跑 agent-browser skills get core 并照着做。CLI 自带的 skills 和 CLI 版本绑定,指令永远对得上你装的那个版本,不会出现文档落后于实现的问题。
中间一层是 skills.sh 的发现机制:npx skills add vercel-labs/agent-browser 会把一个 stub 技能装进 Agent 框架,stub 的内容就是告诉 Agent 去加载 skills get core。skills list 里还有更细的场景技能,electron、slack、dogfood 都在列。dogfood 这个方向很说明问题:他们自己在拿这套东西做真实产品的探索式测试,不是只供着演示。
最厚的一层是标准协议:agent-browser mcp 在 stdio 上起一个 MCP server,任何 MCP 客户端都能接。也就是说,它既可以当裸 CLI 用,也可以挂进现成的 Agent 宿主。三种接入共用同一个 daemon 和同一套命令语义,区别只在谁发起调用,迁移成本几乎为零。
命令面铺得很全,官方命令表分了十组。导航读取有 open、back、forward、reload、read、snapshot、get、is;交互从 click、dblclick、fill、type 一路数到 drag、upload、find,共十六个;等待就一个 wait,但语义齐全;再加上标签页、frame、对话框各一组,setup 侧有 install、upgrade、doctor、connect、close。日常浏览器操作的动作面基本被这张表覆盖完了。
命令表里还有两组容易被扫过去。agents 和集成这一组除了 skills 和 mcp,还躺着 webmcp、flow、chat、batch、plugin 五个入口,前两个分别指向 WebMCP 协议和工作流编排,batch 看名字就是批量执行,plugin 留的是扩展口,官方文档单独一页讲怎么写插件。observe 这组只有 stream 和 dashboard 两条命令,却是调试复杂流程时最值钱的:stream 把页面变化实时推出来,dashboard 起一个面板看全部会话。无人值守流程出了怪事,先开 dashboard 看一眼十个会话分别在干什么,比翻日志快得多。
和 Playwright MCP 摆在一起比
很多人第一反应是:这和 Playwright MCP 有什么区别?两者确实共享同一个思想------都把页面表示成无障碍树而不是截图,都把元素做成可寻址的 ref。真正的差异在调用面、进程模型和治理边界。
| 维度 | agent-browser | Playwright MCP |
|---|---|---|
| 调用方式 | shell 一次性命令 | MCP 工具调用 |
| 进程模型 | daemon 加浏览器,按 session 隔离 | MCP server 常驻 |
| 实现语言 | Rust 原生二进制 | Node |
| 失败语义 | 被遮挡即报错 | 依赖 actionability 等待 |
| 治理边界 | allowlist 与 action policy 写进文档 | 由宿主自行约束 |
表格之外还有一个生态位差异。agent-browser 的命令天然可以被 cron、make、CI 这些非 Agent 环境复用,写一次脚本,人和 Agent 都能跑;MCP 方案的优势是调用方不用管进程细节,宿主帮你维持长连接和工具发现。选哪个,取决于你的 Agent 住在哪:住在终端和脚本里,前者顺手;住在 MCP 宿主里,后者省事。
我自己在意的一个细节是等待语义。Playwright 系靠 actionability 检查决定元素能不能点,页面有持续动画时这个等待可能卡住不动;agent-browser 把判断简化成快照加显式 wait,行为更容易预判,代价是脚本里要多写几次 snapshot。这不是谁好谁坏,是两种容错哲学的分叉,按流程的无人值守程度选。
还要说清楚一件事:这不是二选一的买卖。agent-browser 自己就能起 MCP server,等于同时占住表格两列。真正的选择题在于你希望命令面是文本协议还是工具协议,在于出错时想读 stderr 还是读 MCP 的结构化错误返回。已经在 MCP 宿主里跑得很顺的团队,没必要为一个 CLI 拆现有链路;脚本和 cron 驱动为主的团队,CLI 形态几乎不用做任何接入改造,当天就能把浏览器能力接进现有管道。
装完跑通只要七条命令,坑主要在两个地方
安装一行,然后下载浏览器,之后就是完整的开拍点验循环:
r
npm install -g agent-browser
agent-browser install
agent-browser open example.com
agent-browser snapshot -i
agent-browser click @e1
agent-browser get url
agent-browser close
macOS 用户可以用 brew install agent-browser,Linux 上加 --with-deps 连系统依赖一起装。连装都不想装的话,npx agent-browser open example.com 直接跑。想从源码构建,需要 Node 24 以上、pnpm 11 以上加 Rust 工具链,仓库的 AGENTS.md 写明了每次改动要同步更新哪些文件,维护纪律看着是认真的。
第一个坑是 ref 失效。任何导航、任何会改 DOM 的交互之后,手里的 ref 就成了废纸。写流程时要养成肌肉记忆:动作之后必 snapshot,拿新 ref 再做下一个动作。忘了这条的典型症状是 click 报元素不存在,而页面上明明有那个按钮------你手里拿的是上一页的快照,编号体系整个换了。
第二个坑是遮挡。cookie 横幅、新手引导浮层、吸底的工具栏,都可能盖住目标元素。和截图方案不同,这里不需要肉眼排查,错误信息会直接告诉你点不下去;处理流程是固定的,先关掉遮挡物,重新 snapshot,再重试。这两条坑官方 quick start 都写了,属于读文档十分钟就能省下的那种时间,但现实中大量自动化流程还是栽在这两处。
跑通最小循环之后,建议按固定顺序加复杂度。先把 wait 的几种等待条件摸熟,再碰 cookies 和 storage 做登录态管理,然后才轮到 record 和 diff 这类取证命令。一上来就想写全自动登录加抓数加比对的大流程,大概率会在会话细节上反复摔跤。agent-browser 的命令虽然多,但每一组解决的问题域很清晰,按组啃比按字母表翻文档快得多。碰到环境异常先跑 doctor,这是官方给的自检入口,比对着报错信息猜原因省时间。
十一月第一周的四个信号指向同一件事
把视野拉开一周,agent-browser 登顶不是孤立事件。十一月三日,GitHub Copilot 通过 Agent Client Protocol 进入 JetBrains Air;十一月四日,Copilot 进了 Xcode 27.3 beta 自带的 coding assistant 公共预览;十一月六日同一天,Claude Code 2.1.319 把 MCP 任务挪到后台执行,Codex CLI 0.167.0 加上了 codex agents 命令中心。
四个新闻形状各异,指向却一致:Agent 和工具之间的插座正在标准化。编辑器侧是 ACP,有评论直接把它比作当年语言工具们的 LSP;终端侧是 MCP 加 CLI;浏览器侧,agent-browser 这类工具在回答同一个问题------Agent 操作世界的接口到底应该长什么样。
答案的轮廓已经很清楚:文本化的页面表示、可寻址的元素编号、诚实的失败语义、会话级的隔离和回收。截图加坐标是过渡形态,无障碍树加 ref 才是正经协议。十个月攒下 4.6 万个 star 说明,干活的人已经用脚投完票了。
把这周的另一条新闻放进来对照更有意思:GitHub 的 @GitHub 机器人十一月六日在 Slack 和 Teams 正式 GA,从一段对话里直接查 bug、建 issue、改代码、提 PR,还会在产出的 PR 上标注它来自哪次对话、由谁发起。Agent 正在从几个方向同时渗进日常工具:写代码的编辑器、跑命令的终端、开会的聊天工具,再加上操作网页的浏览器。浏览器反而是标准化最晚的一个方向,因为它面对的页面最不标准。agent-browser 这类工具把浏览器侧的答案收窄到文本协议上,等于把缺的那块拼图按进了位置。
对正在搭 Agent 工作流的人,我的建议很朴素:先把 snapshot-ref-act 这个循环跑熟,把它的失败模式摸透,再决定要不要上更重的框架。浏览器自动化这层地基一旦选对,上面盖什么楼都稳;选错了,每次页面改版都是一场灾难。