本文是「Agent 工程实战」系列的第 08 篇,属于界面线。
系列索引(21 篇阅读路线):Agent 放权前,先补权限、出站、发现这三道口子
摘要:OpenAI 说 agent 能操作界面了,我没光看热闹,在隔离沙箱里搭了个假后台,让 agent 自己去批量调价。结果它跑得飞快,对账时发现零星几个商品库存被清零——它把"编辑"点成了"删除",还把确认弹窗当成了流程下一步。本文复盘完整事故链路,拆三个根因(视觉噪声、上下文缺失、默认猜测),给出三层护栏方案和适用边界。
文章目录
- 一个认真的沙箱实验
- 现象:跑得飞快,日志一片绿
- 排查:回放每一步点击
- 根因:界面是给人眼设计的,agent 在猜
- 三层护栏:我后来怎么修的
- 什么时候可以放手
- 总结
一个认真的沙箱实验
上一篇文章刚聊完 OpenAI 说 agent 能操作界面 这回事。光看发布页不过瘾,我决定自己上手验证一下——在隔离沙箱里搭了个假后台,让 agent 自己进去干活。
这里先交代清楚:是沙箱,不是生产。所有数据都是假的,任务也是我自己布置的,就是为了看 agent 操作界面到底靠不靠谱。事实证明,这个决定非常正确。
现象:跑得飞快,日志一片绿
假后台是个典型的商品管理页:表格、每行有编辑和删除按钮、顶部有批量操作入口。任务很简单:把列表里一小批商品的价格整体上调一成。
agent 干得确实快,几分钟就把活"干完"了。页面日志一片绿,没有一条报错。我当时心里还嘀咕:computer use 这波可能真成熟了。
真正让我冷汗下来的是对账环节。我按沙箱的备份一对比,发现零星几个商品的库存变成了 0——不是我让它改的价格,是库存,被清零了。
排查:回放每一步点击
沙箱的好处是可以完整回放。我把 agent 的操作记录翻出来,一行一行看,最后定位到这样一条链路:
列表页(每行两个按钮:编辑 / 删除) ↓ agent 的点击坐标错位 点到相邻行的"删除"按钮 ↓ 系统弹出确认框:"确定删除该商品?" agent 把弹窗里的"确认"当成流程的下一步 ↓ 直接点了 该行被删除,库存显示归零问题出在两个环节的叠加:点错了行,以及把确认弹窗当成了必经流程。
第一个错,回放里看得很清楚——agent 的点击坐标落到了相邻行的"删除"按钮上。我猜是截图里表格行距不够,按钮靠得近,模型按坐标定位时偏了一格;第二个错更隐蔽——在 agent 眼里,弹窗里的"确认"就是"继续",它不知道这一步不可逆。
根因:界面是给人眼设计的,agent 在猜
复盘完这条链路,我最大的感触一句话:界面是给人眼设计的,agent 在猜。
拆开说,有三个机制放大了这次事故:
视觉噪声。截图里全是角标、状态色、装饰性元素,模型分不清哪些是数据、哪些是摆设。两个按钮之间靠间距和 hover 状态区分,这些对 agent 来说都是弱信号。
上下文缺失。我看到"删除"两个字,脑子里会自动补全"删了不可恢复,这是生产数据,不能乱点"。agent 没有这个上下文,它看到的只是两个名字相似的按钮。
默认猜测。当界面不提供机器可读信号时,模型只能按普遍网站的常见布局去猜。单按钮弹窗在绝大多数网站里是"下一步"的意思,于是它就点了。
说白了:人眼会再三确认的高危按钮,agent 按概率就点了。
这个差异,拿人和 agent 摆在一起看更清楚:
| 维度 | 人 | agent |
|---|---|---|
| 视觉理解 | 靠颜色、间距、经验判断按钮层级 | 靠截图 + 可访问性树"猜" |
| 歧义处理 | 不确定时会犹豫、会再看一眼 | 按普遍网站的习惯默认猜测 |
| 按钮意图 | 结合业务上下文理解"删除"的后果 | 只读到两个名字相似的按钮 |
| 确认行为 | 高危操作会反复确认 | 单按钮弹窗 = “下一步”,直接点 |
三层护栏:我后来怎么修的
翻车之后,我在沙箱里给界面加了三层护栏,然后让 agent 重新跑同一个任务,同一套护栏下连着重跑了好几轮,没再出现同类误点。
第一层:写操作走结构化通道。批量调价这种事,直接给 agent 一个 API,让它提交"商品 ID + 新价格"的 JSON,别让它逆着 UI 去点。这样 agent 根本碰不到那些高危按钮。
// 给 agent 的结构化通道:批量调价POST/api/products/batch-price{"items":[{"productId":"P1001","pricePercent":10},{"productId":"P1002","pricePercent":10}]}运行结果:
HTTP 200 { "updated": 2, "failed": 0 }agent 不再需要"看"界面,也就不存在点错行的问题——这是最彻底的一层护栏。
边界说清楚:这个方案的前提是系统有可用的结构化接口。很多老后台没有,只能从第二层做起。
第二层:高危控件加机器可读信号。给删除按钮补语义,让 agent 在可访问性树里能读到"这是删除、不可逆"。这一步主要依赖 WAI-ARIA 1.2 规范里的 aria-label、role 这类属性:
<buttonclass="row-action"aria-label="删除商品(不可逆,需二次确认)"data-action="delete"data-irreversible="true">删除</button>运行结果(可访问性树视角):
button name="删除商品(不可逆,需二次确认)" >什么时候可以放手三层做完,我要划一条边界,免得矫枉过正:
只读操作可以放手。查询、搜索、分析数据这类不改状态的活,让 agent 自己跑,出错了重来就行。
写操作必须人盯。改数据、删数据、发消息、转账,任何不可逆动作,至少留一层人工确认。等 agent 的可靠性和你的监控能力证明它值得信任了,再逐步放权。
沙箱永远是验证场。想让 agent 操作界面,先在隔离环境跑几轮,看它在哪里犯错。我这次要是直接在真系统上试,清零的就不止是沙箱里的假库存了。
总结
这次沙箱演练把"为 AI 设计界面"从概念变成了刚需。
上一篇我说语义层是"让 AI 看得懂",当时还是推论;这次翻车是实证——界面在可访问性树里长什么样,直接决定 agent 会不会点错。以后谁跟我说"agent 操作界面已经很成熟了",我就把这次的回放日志给他看。
「Agent 工程实战」系列
- 路线:界面线(computer use / Agent UI)
- 上一篇:07 AI 都要自己点界面了
- 下一篇:09 给 AI 看的界面三层适配
- 系列索引(21 篇阅读路线):Agent 放权前,先补权限、出站、发现这三道口子
- 专栏:Agent 工程实战
- 如果这篇对你有用,欢迎收藏;想追更可以关注「Agent 工程实战」专栏。