Snapshot
Agent 读取网页的结构化快照机制,以及 @N 引用如何工作。
Snapshot 是 Agent 读取网页的方式。它把当前页面整理成精简的结构化文本,并为按钮、输入框、链接等可操作元素分配临时编号,例如 @1、@2。Agent 基于这份快照决定下一步操作,而不是去读整页 HTML 或猜屏幕坐标。
它解决什么问题
网页对人是视觉界面,对 Agent 是几万 token 的 HTML、脚本、样式加动态状态。直接塞给 LLM 有两个常见代价:
- Token 成本高。一个普通后台页面可能就是 30k token,每一步操作前都要重新读一遍。
- 抓不到重点。完整 DOM 里大部分内容(样式、脚本、隐藏节点)和决策无关,反而干扰判断。
Snapshot 基于浏览器的 accessibility tree(无障碍树,浏览器为屏幕阅读器维护的语义视图),把页面压缩成大约几百 token:
- 页面标题和当前 URL。
- 可见文本和主要结构。
- 可点击、可填写、可选择的交互元素,以及它们的角色与名称。
- 每个交互元素对应的临时编号
@N。
Agent 读完这份快照就能决定点哪个按钮、填哪个输入框,不必读完整 HTML,也不需要屏幕坐标。
@N 引用是什么
快照里每个可交互元素会被分配一个临时编号:
@1 [input] "搜索"
@2 [button] "提交"
@3 [link] "下一页"
Agent 用这些编号执行操作,例如 await click('@2')。
@N 只对当前这一次快照有效。页面变化后(跳转、刷新、弹窗、表单提交、切标签页、局部重新渲染),旧编号可能失效。可靠的做法是页面变化后重新拍一次快照,而不是长期保存 @N。
如果某个元素后续要稳定引用,使用 snapshot 输出里的 loc=... 作为稳定 selector,或直接写 CSS selector。详见 ego-browser。
你什么时候会感知到 Snapshot
绝大多数情况下你不需要手动操作快照,Agent 会自己读。你可能在两种场景里看到它:
- Agent 说「重新获取快照」或「页面快照」,表示它检测到页面变化、需要重读当前状态。
- 任务结果里附带快照片段作为复核证据。
给 Agent 的任务描述
Snapshot 让 Agent 看得清页面,但任务边界要由你来定。一个好的任务描述包含:
- 目标页面或网站。
- 需要读取、填写、点击或下载什么。
- 不允许做什么(删除、发布、付款、发送邮件等)。
- 遇到验证码、支付、授权时是否暂停。
- 期望的返回形式(表格、摘要、截图、本地文件路径)。
例子:
打开我的 GitHub Notifications,筛选出需要我 review 的 PR,列出仓库名、标题、链接。
不要归档,不要标记已读。
打开后台订单页,筛选昨天的订单,下载 CSV。
出现登录验证或导出确认时停下来让我处理,告诉我文件保存在哪里。
复核 Agent 的结果
任务完成后,可以从这些线索判断 Agent 是否做对:
- 是否说明了访问过的页面和关键动作。
- 返回结果是否包含可核对的信息(标题、编号、链接、金额、时间)。
- 下载任务是否给出本地文件路径。
- 修改或提交类任务是否在最终确认前暂停过。
- 页面是否还保留在 Space 中,可以切过去查看。
结果看起来不对时,让 Agent 重新拍一次当前页面的快照,而不是基于之前的回答继续推测。
常见情况
为什么 Agent 说引用失效?
页面在上一次快照之后变化了,让它重新拍一次快照即可。
Snapshot 能读取所有内容吗?
不一定。不可见内容、图片里的文字、复杂 canvas、受限制的跨域 iframe 可能无法完整出现在快照里。这些场景下 Agent 可能要结合截图、文本提取或人工确认。
Snapshot 会修改数据吗?
不会。Snapshot 只读取页面结构。真正改变页面状态的是后续的点击、填写、提交、上传、删除等操作。
我需要记住 @1、@2 吗?
不需要。把它理解成「当前页面里的临时元素编号」,Agent 负责使用,你负责把目标和边界讲清楚。