在不少管理后台里,Agent 最危险的失败不是找不到按钮,而是点进了正确记录,最后却把别的对象改掉。这类事故常见于“列表 + 详情抽屉 + 行内快捷操作”的组合:列表刚刷新,抽屉还没稳定,动作却已沿着旧观察继续提交。⚠️
表面看像定位器不稳,实质却是对象身份没有被显式认领。很多流程只验证“抽屉打开了”,却不验证“打开的是谁”。一旦虚拟列表复用 DOM、筛选重排,或详情异步回填,Agent 就会把前一步选中的对象和当前抽屉对象混成同一个。🧭
更稳的办法,是把“打开详情再修改”拆成 3 层:先做Object Claim,冻结目标对象主键、展示名称和列表上下文;再做Drawer Snapshot,确认抽屉头部、关键字段和值都和 claim 对齐;最后才允许写入或点击保存。✅ 多数错改发生在抽屉打开到表单可写之间。🔒
问题为什么总出在详情抽屉
抽屉视图最大的坑,是它看起来像新页面,实际上却还是旧页面的一部分。列表继续刷新、筛选继续生效、后台请求继续回流,抽屉中的对象身份可能在肉眼不易察觉时被替换。👀
如果系统只依赖“第 3 行的编辑按钮”或“当前看到的标题文本”,自动化很容易被两类现象带偏:列表重排后第 3 行已不是原对象,抽屉骨架屏先出现、延迟填入数据,模型会在半稳定态里抢先行动。⏱️
一套能落地的 Object Claim
Object Claim的目标,是让任务在进入抽屉前就拿到唯一对象证明。至少应冻结 4 个字段:object_id、主标题文本、动作所在行的辅助标签,以及当前筛选条件摘要。🧩 任一字段变化,都必须放弃旧上下文并重新取证。
claim={"object_id":row.dataset["id"],"title":row.query_selector("[data-col=title]").inner_text().strip(),"badge":row.query_selector("[data-col=status]").inner_text().strip(),"filter_fingerprint":current_filter_hash(),}claim 的价值,是把“我准备改谁”变成结构化约束。只要 claim 对不上,就不能继续沿用旧动作链。🛡️
[外链图片转存中…(img-3FgE07i5-1779872987189)]
Drawer Snapshot 才是提交前的硬门槛
只有Object Claim还不够,因为对象对了,视图不一定稳定。Drawer Snapshot要求在抽屉可写前,再次校验头部标题、关键字段初值、最后更新时间或状态标签是否一致。📌 如果抽屉刚打开就出现 skeleton、loading spinner 或占位文案,系统应等待稳定快照,不要让模型去猜。
| 校验层 | 常见做法 | 更稳做法 |
|---|---|---|
| 对象识别 | 只看按钮所在行 | 先生成 Object Claim |
| 视图稳定 | 抽屉出现就继续 | 等待 Drawer Snapshot 完整 |
| 提交保护 | 直接点保存 | 提交前复核 claim 与 snapshot |
快照字段不用多,能覆盖“对象是谁、视图是否换人、数据是否回填完成”就够。字段太多会拖慢自动化,太少又挡不住错改。⚖️
[外链图片转存中…(img-rgKh4DyK-1779872987194)]
实战里怎么把误改率压下去
这套流程通常是:列表点击前记录 claim,抽屉打开后轮询 snapshot,表单写入后在保存按钮前再做一次对象回证。若回证失败,不重试保存,而是直接回滚并重新定位。🚦 这比“失败后再补确认弹窗”更省,因为错误发生后再补救,往往已经污染数据。
笔者更看重的不是 Agent 会不会点按钮,而是系统有没有给它“对象边界”。很多浏览器自动化失败,本质不是模型能力不够,而是前端没有把对象身份暴露成稳定信号。未来 3 到 6 个月,能把对象 claim、视图快照、提交回证做成统一协议的后台,事故率会更快降下来。📉
如果一套 Agent 流程总在详情抽屉里改错对象,先别急着调提示词。多数时候,缺的不是“更聪明的模型”,而是Object Claim + Drawer Snapshot这护栏。🧱