浏览器智能体的惨痛教训
随着模型能力提升,浏览器框架必须做出改变。而且是大改。
当我们于2024年11月推出 Browser Use 时,GPT-4o 并非为计算机操作而训练。它基于下一词元预测构建,无法可靠地理解自己在页面上能做什么。我们必须把一切都明确写出来。
随着模型在编码方面变得更强,我们从预定义的状态和动作转向代码:起初模型编写它的动作,然后是它的观察。现在它通过原始 CDP 在现有的智能体框架内完成这两件事。
定义状态与动作空间
我们定义了状态:页面上有什么,什么可以点击。然后是动作空间:点击、输入、滚动。每一次交互都必须符合这些规则。
模型选择一个动作,我们执行它并返回下一个状态。但浏览器自动化是一场边缘情况的游戏。每一个异常都需要另一次修复。
用代码取代固定动作
模型的编码能力变得强得多。我们在2025年9月试验了 JavaScript 执行,在10月试验了 持久化笔记本。模型可以编写程序,而不是选择动作。
绘制签名或循环遍历评论不再需要新的动作。变量得以持久化,因此模型可以检查结果并继续进行。
Hermes agent 用
browser_exec取代了12个浏览器工具,由我们的 Browser Use CLI 驱动。Opus 4.8 的平均词元使用量下降了60%,Kimi K3 下降了66%。两个版本在每个模型上都完成了18/18次运行(六个任务,三次运行)。
预定义状态的局限
我们开放了动作,但仍然决定了模型能看到什么。这成了下一个问题。
一个 Cookie 按钮可能就在屏幕上,却在我们发送的状态中缺失。也许无障碍树没有暴露它,或者我们的处理将其丢弃。无论哪种情况,模型都看不到这个按钮。
一个电子健康记录(EHR)下拉菜单可能看起来像这样(简化的 DevTools 树):
<ehr-app>
#shadow-root (open)
<iframe src="https://ui.example">
#document <!-- other origin -->
<dropdown-menu>
#shadow-root (closed)
<button>Choose...</button>我们的状态启发式方法无法预见每一个网站。我们给了模型行动的自由,但它仍在透过我们的假设进行观察。
移除预定义状态
如果我们让它也编写观察结果呢?
我们让大语言模型直接访问 CDP,即 Chrome 开发者工具协议。没有强制性的可点击元素列表。它可以编写代码来检查 DOM、截图或查看某个框架内部。
浏览器仍然有状态。消失的是我们要求一切都符合一种预定义表示的规定。一张截图可能回答一个问题。一次 DOM 查询可能回答下一个问题。模型决定它需要看到什么。
为什么选择 CDP 而不是 Playwright?
CDP 是 Chrome 的原生控制协议。模型可以直接使用它。
Playwright 增加了一些假设,例如 无法看到已关闭 shadow root 的定位器。CDP 可以 直接检查这些 root。Playwright 也暴露了 CDP;我们将直接访问设为默认。
一个简单的浏览器框架
Pi、Codex 和 OpenCode 已经处理了智能体循环。编码智能体拥有数百万用户,尝试各种各样的工作。这种测试是复用它们框架的一个理由。
进行到第五个小时质量保证的智能体,不应该因为循环中的一个 bug 而失败。我们曾遇到过压缩产生如此多的上下文,以至于立即再次触发压缩的情况。我们的客户不应该不得不去发现这些 bug。
我们添加了一个简单的浏览器工具:持久化的代码,文本、截图和错误会返回给模型。
从我们 2026 年 1 月的 Agent SDK 到 4 月的 Browser Harness,这成为了方向。Browser Harness、BrowserCode 和 Browser Use Pi 采取了不同的方法。它们都让模型选择要看什么、做什么。
这里的苦涩教训究竟是什么?
Sutton 的苦涩教训青睐那些随计算量增加而改进的通用方法。对我们而言:
- 复用经过验证的智能体框架。
- 暴露模型能够良好使用的最简单的底层接口。
- 让模型选择它的观察和行动。
浏览器、计算机、文本、音乐:同样的原则适用。随着模型的变化,重新思考框架。