文章 · Context engineering

Context engineering:浏览器 agent 每看一眼页面,到底花多少

关于 context engineering 的文章很多,大多在争论定义。很少有人算一笔账:一个浏览器 agent 每「看」一次页面要往上下文里塞多少东西,这些东西又会在后面的每一步里被反复付费。建联系统的脚本改了几版之后,这笔账我算得很清楚。

作者 Nick2026-10-168 分钟阅读

这篇回应的是 ego lite 官网的 《Context engineering for browser agents: what an observation costs》。观点是我自己的,例子来自我搭的 KOL 建联系统。

先说结论
  1. Context engineering 就是决定每一轮里哪些东西进模型的上下文窗口。目标不是塞得多,而是用最少的高信号 token 换到想要的结果。
  2. 浏览器 agent 的上下文开销来自三处:这一次的页面观察、每次都要付的工具 schema、以及一直背在身上的历史。前两项决定了每一步的底价,第三项让成本随步数线性增长。
  3. 三件事最管用:让观察变小(只拿需要的那部分页面)、让工具变少(一个入口接代码,而不是几十个工具)、让历史变短(把确定性的步骤合并成一次执行)。

先把定义说清楚

Context engineering 指的是一种实践:在模型的每一轮调用里,决定上下文窗口中放什么。Anthropic 的说法是「为目标结果挑选最小的一组高信号 token」。市面上的定义在这一点上是一致的,分歧在于谁包含谁:有人认为 harness 是 context engineering 的一部分,有人反过来。

我不太关心包含关系。对一个要天天跑的浏览器 agent 来说,context engineering 就是一个成本问题:每一步进上下文的东西,决定了这一步多贵,也决定了后面每一步多贵。

和 prompt engineering 的区别也在这里。prompt engineering 关心的是你怎么说那一句话;context engineering 关心的是那句话旁边还摆着什么,而旁边那些东西往往比那句话大几十倍。

一次页面观察到底是什么

浏览器 agent 想知道页面上有什么,只有几种办法:截图、DOM、可访问性快照。每一种都是一次「观察」,每一次观察都会变成 token 进入上下文。

截图看起来最直观,但模型读图的代价不低,而且读出来的信息不精确:它知道那里有个按钮,不一定知道按钮的名字和能不能点。完整 DOM 最精确,但一个普通的后台列表页序列化出来动辄几万字符,大部分是 class 名和包装层。可访问性快照是折中:只保留角色、名字和层级,通常比 DOM 小一个数量级,而且带着可以直接操作的引用。

建联系统的「建联追踪」页是一个几十行的表格。我对比过三种观察方式拿到的东西:

观察方式大致体量拿到了什么缺什么
整页截图一张图,按模型读图计费版式、颜色、大概位置元素的精确名字、是否可交互
完整 DOM 序列化数万字符一切,包括不需要的可读性;噪声淹没信号
可访问性快照数千字符角色、名字、层级、可操作引用纯视觉信息,比如颜色

体量差一个数量级,意味着价格差一个数量级,而且这还只是一次观察。

成本的三个来源

把一个浏览器 agent 跑完一个任务的 token 拆开,大致来自三处。

来源一:这一次的观察

上面说的那份快照或截图。它是最显眼的一项,也是大多数人唯一会去优化的一项。

来源二:工具的 schema,开跑之前就付了

如果 agent 通过工具协议(比如 MCP)操作浏览器,每一个可用工具的名称、描述、参数定义都会进入上下文,而且每一轮都在。二三十个浏览器工具的 schema 加起来可能比一次快照还大,这笔钱在你什么都没做之前就付了,之后每一步继续付。

来源三:你一直背着的历史

每一轮的观察和结果都留在对话里。第十步的时候,前九步的快照还在上下文里,哪怕早就没用了。这是成本随步数线性增长的根源,也是为什么一个二十步的任务远不止二十倍于一步的价格。

第二和第三项加起来,才是大多数浏览器 agent「越跑越贵」的真正原因。只优化截图的大小,解决不了这个问题。

对上下文能做的四件事

  • 写。 把中间结果写到上下文之外,比如文件或数据库,需要时再读回来。建联系统的每日任务把筛出的名单写进文件,模型只看一行汇总。
  • 选。 每一轮只放这一轮需要的东西。要点击一个按钮,就不需要整页的 DOM,一个带引用的局部快照就够了。
  • 压。 把观察压缩成更小的表示:可访问性快照代替 DOM,表格的前几行代替全部,页面的变化部分代替整页。
  • 隔。 把子任务放进独立的上下文里跑,结束后只把结论带回来,而不是把整个过程带回来。

这四件事的共同点是:决定什么不进上下文,比决定什么进更重要。

一个设计同时改掉两项

有一种设计可以同时压低第二项和第三项:不把浏览器能力拆成几十个工具,而是给 agent 一个入口,让它提交一段代码,代码在本地运行时里把多步操作一次做完。

工具 schema 从几十个变成一个,因为只剩「执行这段代码」。历史也变短了,因为原来要十轮对话的事现在是一轮:模型写一段脚本,运行时打开页面、筛选、点击、读结果,只把最后几行返回。中间那九次观察根本没有进入上下文。

这正是我在另一篇文章里讲的 heredoc 的做法。建联系统的「该催谁」任务,早期版本每次都要模型看三四次页面快照;改成一段脚本之后,模型只看脚本输出的一张小表:多少人该催,几封已发出。上下文从几万 token 降到几千,而且不随名单长度增长。

怎么自己量一遍

  1. 挑一个你的 agent 常跑的任务,记下它完整跑一遍的总输入 token。大多数 agent 工具会在日志里给这个数。
  2. 把单次观察单独量一下:同一个页面,截图、DOM、快照各拿一次,看各自多大。
  3. 数一下可用工具的 schema 总长度。把它乘以步数,就是你为「工具目录」付的总价。
  4. 看总量里有多大比例是重复的历史观察。如果超过一半,优先合并步骤,而不是优化单次观察。

量过一次之后,你会发现优化的顺序和直觉相反:先减少步数,再减少工具,最后才是把截图换成快照。

Context engineering 和 harness engineering

这两个词经常一起出现。我的理解是:harness 决定 agent 有哪些工具、怎么循环、在什么环境里行动;context engineering 决定每一轮里这些东西以什么形态进入模型。前者是结构,后者是预算。一个好的 harness 让 context engineering 变得容易,比如把观察默认做成小的快照、把多步合并成一次执行;一个差的 harness 会让你在提示词里拼命省字,却省不回工具 schema 和历史快照那几万 token。

常见问题

会漏掉纯视觉的信息,比如颜色、图片内容和精确位置。对表单、列表、按钮这类操作任务,它几乎总是够用;需要判断视觉状态时,再补一张局部截图。

窗口大不等于便宜,也不等于模型会更专注。上下文里噪声越多,模型越容易抓错东西,而且每一步都要为整个窗口付费。更大的窗口只是把问题推迟,没有解决它。

三个成本来源对所有带工具的 agent 都成立,只是浏览器把问题放大了:页面是最大的一种观察,浏览器工具也是最多的一类工具。

想看这些想法落地的样子?

KOL 建联系统就是用这套方法搭出来的。