让 agent 用 Playwright 驱动浏览器去操作你的 ERP,是一条又慢又脆又贵的死路。

🤔真正的路径不复杂,但需要先想通一件反直觉的事:

我们那套用了十年的页面,对 agent 来说是一份设计时就该读完的文档——把它当运行时接口去戳,正是死路的起点。


作者 | 听风

编辑/排版 | MM77

翠鸟AI技术漫研 — 拓新AI边界、探索技术增量


1. 让 agent 驱动浏览器点你的业务系统,错在它把几乎不变的业务语义,当成每次任务都要现场重读的运行时数据。

2. "系统有 API" ≠ "agent 会用 API"。差的那层东西——指标定义、勾稽关系、异常阈值——藏在页面里,API 文档装不下。

3. 解法:把页面当文档读一次,自底向上抽提出领域模型,固化成 agent 能学的 skill。终点是领域模型,不是指标字典。

4. 千人千面靠 OBO 身份透传解决:agent 不拥有权限,只借用当下用户的权限,边界由后端强制。

01. 结论放送:别让 agent 走人的那条路

现在让 agent 操作一个没有专门 agent 接口的业务系统,最主流的做法是:

浏览器自动化——Playwright、computer use,让模型像人一样去识别按钮、填表、点提交。

这条路能跑通 demo,但一旦上规模、上生产,它的代价是结构性的,换个更快的浏览器引擎也救不了。



  1. 慢,是因为每个微操作都要往返:
  2. 你的代码到 relay,relay 到浏览器协议,再到 Chromium,三段跳还会在几个运行时之间产生状态漂移。
  3. 贵,是因为视觉路线每点一次就是一次模型调用——一张截图烧掉的 token,是同一页结构化文本的十倍量级。
  4. 脆,是因为它看不到后端:
  5. agent 能填完表提交,却无法判断返回的那个报价对不对、那个金额和后端算的一不一致。它在猜一个为人眼设计的界面。

Playwright 路线的根本错误,是强迫 agent 假装成人,去戳一个本来就不是为它准备的 UI。

而你的系统后端早有数据通道,绕一大圈回到前端去点,是自找的。

把截图控制换成读取结构化的界面语义(accessibility tree),某个公开测试里 agent 的准确率从 40% 直接跳到 90%。

这个数字说明:agent 的瓶颈不在聪明不聪明,在信息形态喂错了。

给它结构,它就准;逼它看像素,它就瞎猜。



02. "有 API" 不等于 "会用 API"

到这里很多人会说:那简单,系统有 API,让 agent 调 API 不就行了。

这话对一半。

问题在于,"系统暴露了 API"和"agent 会用这个 API 干活"之间,隔着一整层业务语义,而这层语义,API 文档系统性地丢掉了。

看几个例子,你会立刻明白这层东西有多关键:


API 给你的页面额外告诉你的(API 文档里没有)
status: 3 这是"已驳回(可重新提交)"——枚举到含义、 以及"驳回后还能重提"这条业务规则
一列 20 个字段哪三个是真正被盯着的 KPI(页面用大字、染红、放顶部的那几个)
amount、tax、discount total = amount + tax − discount 这条勾稽 关系,常常只活在前端
两个独立端点这两份数据必须关联起来看("这个客户的逾期订单"是一个完整业务视图)
一个数字它什么时候算"异常"——逾期超 30 天标红、库存低于安全线预警


页面是这套系统业务语义的事实载体,API 只是数据的搬运工。

指标的定义、字段的含义、阈值、勾稽、什么算正常什么算异常——这些是无数前端代码和产品决策沉淀出来的,API spec 天然装不下。

所以"直接调 API"的隐藏代价是:

你绕过页面,就把这层语义一起绕掉了,等于让 agent 拿着一堆裸数据自己瞎猜业务含义。



但这推不出"那还是回去爬页面"。它推出的是另一件事——

页面里那层语义很宝贵,但"驱动浏览器去现场读取它"是最蠢的提取方式。

√正确动作:把它抽出来一次,固化进工具,而不是每次运行时让 agent 去现场猜。

关键在于分清两种东西。

  1. status=3 这种运行时数据每次都变,该走 API 实时取;
  2. 而"3 = 已驳回可重提""这三个是 KPI""逾期超 30 天预警"这种业务语义,一年都不带变的——

你却让 agent 每次任务都拉起整个浏览器去页面上重新辨认一遍。

Playwright 路线的浪费,本质就是把几乎不变的语义,当成每次要现场重读的运行时数据来对待。



03. 抽提的终点是领域模型,不是指标字典

于是路径清晰了:

以现有系统(尤其 UI)为蓝本,把业务语义抽出来,固化成 agent 能学习的 skill,让它先读懂"这个系统在解决什么问题",再去服务客户。

但这里有个 90% 的人会踩的坑:

如果 skill 只是"每个指标项配一个范例"的清单,agent 拿到的就只是一本能查词、却不懂这门语言的字典。

要让 agent 真正理解系统,它需要的是四层知识,而指标项只是最底层:


是什么从哪抽
① 指标语义 status=3 是"已驳回";total 是含 税应收 UI 标签、枚举、tooltip
② 关系勾稽total = amount+tax−discount;逾期订单关联客户风险UI 聚合显示、关联视图
③ 规则阈值 逾期>30天预警;驳回后可重提 UI 标红、图标、状态流 转
④ 领域目标这是个应收账款系统,核心目标是降坏账、快回款不在任何标签里——靠整体归纳


"指标项范例"扎实覆盖了 ①,部分碰到 ②③。

但 ④——系统到底在解决什么问题——抽不出来,因为它不在任何一个 UI 标签里,它在系统的整体结构里。

而 ④ 恰恰是"让 agent 理解系统、再为客户服务"这句话的核心。



把指标语义、领域模型、场景范例三样都给到,agent 才从"会查系统"变成"懂这个系统在解决什么、并据此为客户服务"。

顺带纠一个对"范例"的误解。

最有价值的范例不是"指标 A 长什么值",而是一段解决问题的剧本——"当客户问 X,通常要看 A+B,判断依据是 C,这样回答"

前者教 agent 认字,后者教 agent 看病。"为客户服务",需要的是后者。

04. 千人千面:agent 不拥有权限,只借用权限

真实业务系统还有一道坎:千人千面。

同一个意图,销售调和经理调,能看到的数据行、能做的操作、能碰的金额字段,全都不一样。

这件事容易把人吓住,但拆开看,它其实是三件被揉在一起的事,而且大部分能直接甩掉:


差异层例子怎么处理
数据权限(行/列级)销售只看自己客户;财务看金额、客服看不到后端按身份强制
功能权限A 能审批,B 只能提交后端按角色强制
UI 个性化自定义仪表盘、收藏的筛选器直接扔掉


第三层是为人眼优化的,agent 根本不需要——这反而是好消息,意图层天然甩掉了最碎最难的那部分。

于是问题收窄成一句:agent 怎么以"当下这个用户"的身份执行,既不越权、也不少看?



两种错误做法先排掉:

  1. 给 agent 一个万能服务账号,让它"自己记得"该过滤成谁能看的数据——这是灾难:

一旦判断出错或被 prompt 注入,它有全量权限能动任何人的数据,审计日志里还全是那个服务账号,出事查不到替谁做的。

  1. 让 agent 持有用户的长期密码/session——凭据泄露面爆炸。

正解是 OBO:

agent 不该"拥有"权限,它只是"借用"用户的权限,且借条上写明了范围和有效期。

  1. 机制上:用户授权 agent 代表自己,换取一个作用域受限、有时效的令牌;
  2. agent 拿它调意图层,意图层把身份透传到后端,
  3. 后端按这个用户的真实权限做行列过滤和操作鉴权

agent 全程不需要知道完整的权限边界——它越权了后端直接拒,而不是指望它自觉别越界。



这套和意图层严丝合缝,因为两件事正交:

业务语义对所有人一样,固化进 skill;数据和操作权限对每人不同,运行时由后端按 OBO 身份强制。

同一个工具 get_orders(),销售的 token 调返回 30 条、经理调返回 800 条,工具定义一字不改。

这恰恰是意图层相对爬页面优势最大的地方:

换人只换 token;而爬页面换人要重新登录、重开 session,页面还可能因角色不同布局全变,抽好的语义全得重抽。

千人千面把爬页面的脆弱性指数级放大,却几乎不增加意图层的复杂度。

一个绕不过的硬骨头:

很多老系统的 API 压根不支持用户级 OBO,设计时只有服务账号或 session cookie。

退路按优先级是:

① 后端能改 → 给 API 加上接受用户身份令牌的能力(治本);

② 改不动 → 在网关做 token 交换 + 身份透传,让后端至少能按它过滤;

③ 后端完全没有任何用户级隔离、数据隔离纯靠前端 → 这是真实的安全债,补上之前不该接 agent。

没有后端强制,任何 agent 侧的"自觉过滤"都不可信,千人千面会变成"千人一面地全看到"。



05. 路径图:五步把系统交给 agent


把前面的判断串成可执行的步骤。

注意 ①②③ 大部分能让一个 agent 读 UI/前端代码自动初抽、人来审校;

④ 必须人深度参与——"系统在解决什么问题"是业务判断,agent 容易归纳得似是而非,这一步偷懒,整个 skill 就退化回字典。

① 全量盘点指标 扫 UI / 前端,列出系统所有指标、字段、状态、操作

└ 谁来做:agent 自动抽 + 人审 │ 这是前提,求全

② 逐项抽语义 从标签 / 枚举 / tooltip / 标红规则,抽每项的含义、阈值、异常态

└ 把页面当现成的语义规格书读——比任何 API spec 都准


③ 抽关系与勾稽 计算关系、关联视图、状态流转

└ ②③ 合起来,就是 API 文档装不下的那层精华


④ 归纳领域模型 自底向上:这堆指标合起来,系统在解决什么、核心目标是什么

└ ⚠ 人必须深度参与,别外包给 agent。这步是 skill 的灵魂


⑤ 固化成 skill 领域知识(给 agent 读懂)+ 意图工具(给 agent 动手,配 OBO 身份)

└ 工具按业务意图设计,不按技术端点;编排和校验吃进工具内部

最后那条工具设计原则值得单独强调,因为它是真正干掉 Playwright 式低效的地方。



别把原始 API 一对一机械包成工具。

原始 REST 是为程序员设计的,一个业务动作往往要调五个端点、自己拼参数、自己排顺序——你直接丢给 agent,它就会参数幻觉、调错顺序、陷入重试循环。

正确做法是按意图设计:

暴露一个 place_order(customer, items),内部把那五步编排好、校验好,agent 只表达"我要下单"。

你把试错成本从运行时(每次都试)挪到了设计时(写一次工具)。

但完整 API 手册必须保留——意图层不取代它,是架在它上面。

意图层只为高频意图铺路,不可能穷举所有操作;它内部编排调用的那些原子操作,正是完整 API。

所以分工是:

完整 API 是能力全集与底座(所有原子操作、字段、边界都在这,确定性、可审计,给程序和需要精确控制的场景用),意图层是它上面给 agent 的高频入口。

agent 优先走意图层,遇到长尾操作再退回完整 API 自己组合——这恰恰要求那本手册全且准。

只有意图层没有完整 API,等于既把系统能力阉割成"只剩常见操作",又让意图层自己建在没有稳定契约的流沙上。



而这整套 skill,就是前面所有判断的载体:

一半是让 agent 读懂的领域知识(目标 / 指标词典 / 关系 / 场景剧本),一半是让 agent 动手的意图工具(配 OBO 身份)。

API、意图层、页面语义、认证,到这里全部收进同一个资产里。

关于实施,两句实话:

  1. 第一,这不是从零重写——
  2. 业界共识是 retrofit 而非 rebuild,原系统业务逻辑一行不改,只在旁边加一组新接口(已有 OpenAPI 的甚至能用网关半自动生成)。
  3. 第二,别指望"fire and forget":
  4. 不可逆操作(审批、删除、付款)即便 agent 有权限,也该在执行前给用户确认——权限上能做,不等于该自动做。

测试基准从 70% 爬到 99% 可能还要数年,最后那 20% 的边缘 case 指数级地难。



最后

把整条路径浓缩成一句能用三年的判断:

页面对 agent 的价值,是设计时读一次的文档,而不是运行时戳一万次的接口。

这是死路和活路的根本分野。

存量系统 agent 化,难点不在技术选型,在想通一件事:agent 不该用人的 UI。

好消息是,这条路是加出来的,不用拆老房子——给 agent 单开一条按业务意图铺的通道,领域模型从页面抽一次固化下来,权限靠 OBO 向当下用户借。

想通了页面的角色,剩下的五步只是工程