实测AI代理用MCP打开页面时,Playwright快照是thinbrowser的2.6倍~11倍大,影响token成本和响应速度。
Playwright 是一个出色的工具,但它生来要干的活跟 Agent 实际要干的活几乎完全相反。你为某个页面写测试,那个页面是你自己建的,你知道按钮的 selector 是什么,你知道你的 App 什么叫"加载完成",你也知道 cookie 横幅在那儿——因为是你放上去的。页面会乖乖待着等你去做断言。
Agent 则不一样,它操作的页面是从未见过的。它不知道 selector,无法区分是渲染慢还是元素缺失,每次遇到 cookie 栏都是新的意外。这种摩擦在性质上就不同——而它最最初级的形式出现在 Agent 做任何事情之前:拿到手的页面描述太大了,大到根本读不完。
当一个基于 MCP 的 Agent 打开页面时,通常会得到一份无障碍快照——即屏幕阅读器能读取到的页面上所有内容的文本渲染。这是一个合理的设计默认值,但它非常庞大。我在 2026 年 9 月 29 日,对五个普通的公开页面,用 Playwright 自己的 MCP server 生成的字符串(即其内部的 _snapshotForAI)做了测量:
字符数。按每 token 约 4 个字符的常用经验值来算,同样的五个页面,无障碍快照约 128,000 token,紧凑快照约 2,900 token。Token 数字是估算值,我承认这是个粗略的估计;但字符数是精确的。在仓库里跑 npm run bench 你会得到自己的数据——线上页面会漂移,所以重点是比值,不是具体数字。
一篇 Wikipedia 文章的快照是 25 万字符。Agent 来是为了读某个定义或点击目录里的一个链接,结果被塞进了所有导航项、侧边栏所有语言选项、所有编辑入口、整个页脚,以及每个元素的 ARIA 角色。几乎没有任何一部分是它真正需要的东西。它读完了——也为此付了钱——整页内容,只为了用到角落里的一小块。
成本是显而易见的部分。判断力是安静的部分
Token 账单是容易看到的部分,在多步骤任务中它还会叠加:每次点击都会返回一份新的快照,所以一个十步流程可能会把"家具"读上十遍。但更昂贵的代价是,所有那些脚手架信息会如何影响模型的决策。唯一重要的那个控制项埋藏在成千上万无关的 token 里,模型每一轮都必须在那堆东西里把它找出来,同时还要在脑子里记住任务。一个更小、更真实的描述不只是更便宜;正确判断它也更容易。
把页面精简到 Agent 可以操作的程度,它就很小了:给页面提供结构的标题、分组的形式和对话框、每个可交互元素作为一行——[e12] button "Next" (disabled)——导航和页脚压缩成几条链接加一个计数,然后是页面实际正文的几百个字符。那是几千个字符。页面的其余部分并没有消失;如果 Agent 需要,它一次调用就能拿到。只是它不该出现在每一轮对话里。
大小是第一个摩擦点,但不是唯一一个。每一个摩擦都曾让我们花费了大量时间才写出对应的工具,而且即便你从不安装任何东西,了解它们也是有价值的:
元素引用会过期。 你做了快照,拿到了按钮的句柄,页面重新渲染,句柄现在指向空——或者更糟,指向了别的东西。一个存在于元素本身、能够跨重新渲染而保留的引用,是"点击我刚看到的东西"和"点击现在位于那个索引位置的东西"之间的区别。
Cookie 栏会吃掉点击。 Agent 瞄对了按钮,但有一个它看不到的遮罩层盖在上面;点击落在了遮罩上。一个先检查目标实际上被什么覆盖着、并且报告结果的点击,会大声地失败,而不是悄悄地做错事。
"未找到"和"还没加载完"看起来一样。 浏览器自动化里最危险的歧义:一个元素真的不存在,和一个元素只是还没到来,会产生相同的空结果,Agent 会自信地得出错误的结论。诚实的答案会区分"仍在加载中"和"页面已经空闲但元素不存在"。
两个东西同名,工具静悄悄地选了其中一个。 有两个"Submit"按钮;点击取了第一个,什么都不说。那份沉默可能导致本来想提交向导表单的点击反而重新打开了侧边栏。一个工具如果对第一个动手但告诉你它有过选择,会把一个谜变成一行就能修复的问题。
这些摩擦就是我们做 thinbrowser 的原因——一个基于 Playwright 的 MCP 浏览器层——Playwright 仍然做驱动 Chromium 的硬活儿。其中每个工具的存在都是因为上面某个问题曾让我们花掉一个下午。快照返回紧凑的轮廓,而不是无障碍转储——即上表中 44 倍那个数字。引用存在于元素本身,所以一个按钮只要还存在就会在多次快照之间保留其句柄。click 会滚动到目标、移动或关闭盖在上面的遮罩层,并报告它做了什么。wait 回答三种状态之一,而不是一个裸露的 true/false。当页面是登录墙或机器人检查时,快照会在顶部说明这一点,而不是返回一个看起来莫名其妙为空的内容。
一个对自动化如此有用的工具,很容易被指向错误的方向,所以把边界说清楚是值得的。thinbrowser 会命名 Cloudflare interstitial 或登录页面;但不会尝试突破它。它的 solve 步骤会在一个可见窗口中重新打开挑战,留给坐在那里的人类去清除。至于密钥,通过一个 fill_secret 工具把凭证文件里的值直接填入字段——值从不经过模型的转录,后续快照里那个字段显示为 (secret)。做最少的事、存储最少的东西、说出它不能做什么,这就是全部的姿态。
它是免费的,采用 MIT 协议,不绑定任何一个模型或编辑器,安装只需一行:
claude mcp add thinbrowser -- npx -y thinbrowser
或者将任何 MCP client 指向 npx -y thinbrowser 作为 stdio server。基准测试在仓库里;最快打消 44 倍这个数字的方法是自己跑一遍。
我们构建工具,将 Agent 的上下文——以及你的数据——视为稀缺之物,值得谨慎消耗。这就是我们在 Rebel Studios 所做的事。