最近看到一段很像“AI 在桌面软件里摸黑探路”的命令:
osascript \
-e 'tell application "System Events" to tell process "vibeos-desktop"' \
-e 'set g to UI element 5 of UI element 1 of scroll area 1 of group 1 of group 1 of window 1' \
-e 'set out to ""' \
-e 'repeat with i from 1 to count of UI elements of g' \
-e 'set e to UI element i of g' \
-e 'set out to out & i & " | " & role of e & " | " & description of e & " | " & position of e & " | " & size of e & linefeed' \
-e 'end repeat' \
-e 'return out' \
-e 'end tell'
它到底在干什么?
先给一句话答案:这不是在点击按钮,而是在借助 macOS 的可访问性接口,沿着目标应用的 UI 层级找到一个容器,再枚举其子元素的角色、说明、位置和大小。 它更像一次界面侦察:先找出“这里有哪些可操作对象”,再决定下一步点哪里。
为什么一个看起来很聪明的大模型,要用如此笨拙的层级路径查看桌面?因为“理解用户要什么”和“可靠地操作一个具体软件”是两类问题。模型可以理解“把这段文字发送出去”,但操作系统仍需要一个精确答案:哪个进程、哪个窗口、哪个控件、什么动作、结果怎样才算成功。
这篇文章想建立一个比“AI 看截图、点鼠标”更有用的心智模型:
桌面 Agent 的核心不是模仿手,而是为一个概率决策器设计可观察、可执行、可验证的 Agent–Computer Interface。Accessibility、视觉、DOM 和 API 只是不同接口,各自在语义、覆盖、稳定性、成本与权限之间做取舍。
一、把这条命令翻译成人话
先看最外层。osascript 是 macOS 用来执行 AppleScript 或 JavaScript for Automation 的命令行工具;每个 -e 传入一段脚本源码,多段会组合成一次执行。终端日志里用于折行显示的 │ 不是 AppleScript 语法。
整理后,脚本做了五件事。
1. 找到目标应用进程
tell application "System Events" to tell process "vibeos-desktop"
System Events 是 macOS 自动化里负责系统事件和 UI scripting 的入口之一,process "vibeos-desktop" 选中这个正在运行的应用进程。这里不是让目标应用执行它自己公开的业务命令,而是从操作系统提供的可访问性视角观察它。
Apple 的 Mac Automation Scripting Guide 对这个用途说得很直接:不是所有 Mac 应用都支持脚本,即使支持,也未必覆盖所有任务;这时可以用 UI script 模拟点击、按键、菜单选择和文本输入。UI scripting 依赖系统的 Accessibility framework,而且需要用户给执行脚本的应用授予辅助功能权限。
2. 沿 UI 树找到一个深层容器
set g to UI element 5 of UI element 1 of scroll area 1 of group 1 of group 1 of window 1
把它从右向左读:
第 1 个窗口
└── 第 1 个 group
└── 第 1 个 group
└── 第 1 个 scroll area
└── 第 1 个 UI element
└── 第 5 个 UI element ← 记为 g
这里的 group、scroll area、UI element 不是屏幕像素,而是应用通过可访问性接口暴露出来的对象。它们形成一棵近似树状的层级。脚本先把其中一个深层对象保存为变量 g。
注意这个路径没有说“找到名为消息列表的区域”,而是说“第一个窗口里的第一个 group 里的第一个 group……”。这是一种位置索引。它能工作,却非常依赖当前界面结构。
3. 枚举它的直接子元素
repeat with i from 1 to count of UI elements of g
set e to UI element i of g
...
end repeat
脚本数出 g 有多少个直接子元素,然后逐个访问。它没有递归扫描整个应用,只查看一个已经缩小范围的容器,这能减少输出和后续模型需要阅读的 token。
4. 把语义和几何信息打印出来
set out to out & i & " | " & role of e & " | " & description of e & " | " & position of e & " | " & size of e & linefeed
每一行包含:
| 字段 | 回答的问题 | 后续用途 |
|---|---|---|
i | 它是第几个子元素? | 再次通过层级路径引用 |
role | 它像按钮、文本、列表还是容器? | 判断能不能点、读或输入 |
description | 系统给它的可访问性说明是什么? | 把用户语言映射到控件 |
position | 它在屏幕哪里? | 计算点击或截图裁剪位置 |
size | 它占多大区域? | 计算中心点并避免点到边缘 |
5. 返回探测结果
return out
因此,这条命令只完成了桌面控制闭环里的“观察”和部分“定位”。它没有 click,也没有 keystroke,不能从这条日志推断 Agent 已经操作成功。更可能的下一步是:模型阅读这些候选元素,选出目标,然后生成另一条点击、赋值或键盘命令。
二、先建立心智模型:桌面控制是闭环,不是一次点击
无论底层使用 AppleScript、Windows UI Automation、截图还是浏览器 DOM,一个桌面 Agent 都绕不开四个环节:
flowchart LR
U[用户任务] --> O[观察<br/>读取 UI 与环境状态]
O --> G[定位<br/>语义目标映射到控件或坐标]
G --> A[行动<br/>点击、输入、快捷键或工具调用]
A --> W[软件与系统状态改变]
W --> V[验证<br/>重新读取目标状态]
V -->|未完成或出现异常| O
V -->|外部证据通过| D[任务完成]
X[权限、预算与安全策略] -.约束.-> O
X -.约束.-> A
可以把四个环节想成四个连续问题:
- 观察:当前窗口里有什么?真正的文件、消息或设置处于什么状态?
- 定位:用户说的“发送按钮”对应哪个节点或哪块像素?
- 行动:应该调用语义动作、点击坐标、按快捷键,还是直接调用业务 API?
- 验证:动作以后世界真的变成目标状态了吗?
大模型主要负责在不确定信息下做语义判断和下一步决策;操作系统、应用与外部服务才是真实世界。一个命令返回退出码 0,最多证明命令没有以错误退出,不证明邮件已发出、文件已保存或订单已付款。
这也是为什么桌面 Agent 不能只有“会点”:它还要看得见、找得准、知道什么时候不该点,并能从动作后的世界取得完成证据。
三、为什么可访问性树会成为桌面 Agent 的常用入口
可访问性 API 原本不是为大模型发明的。它的主要用户是屏幕阅读器、语音控制、替代输入设备和自动化测试。为了让这些工具理解界面,应用要把一个按钮暴露成“按钮”,给出名称、值、选中状态、父子关系和可执行动作,而不能只把它画成一组像素。
不同桌面系统有相似的抽象:
- macOS 有 Accessibility /
NSAccessibility,AppleScript UI scripting 可通过System Events查询和控制元素。 - Windows 的 UI Automation 把桌面作为根,应用窗口和控件作为下级
AutomationElement,并通过 control pattern 暴露选择、展开、调用等能力。 - Linux 桌面常见 AT-SPI,可访问对象同样提供名称、说明、父节点、子节点数量、角色与动作接口。
- 浏览器则有 DOM、ARIA 与 Accessibility Tree;Chrome DevTools Protocol 的 Accessibility domain 可以取得节点的 role、name、description、value、父子 ID 和关联 DOM 节点。
对 Agent 而言,它比整张截图多了三种关键价值。
1. 像素变成了语义对象
视觉上,一个按钮只是一块带颜色、文字和边框的区域;在可访问性树里,它可能是:
role: button
name: Send
enabled: true
position: (1132, 781)
size: (72, 32)
模型不必先识别形状、OCR 文字、猜测边界,再把坐标还原到桌面。结构接口已经替它完成了一部分 grounding——把语言里的对象落到可操作实体。
2. 文本观察通常更紧凑,也更容易筛选
一张高分辨率、多窗口截图包含大量与任务无关的像素。可访问性树也可能很长,但程序可以先按窗口、角色、名称和层级筛选,再只把候选节点交给模型。开篇脚本先找到 g 再列直接子元素,就是在缩小观察范围。
3. 语义动作可能比坐标点击更稳定
如果节点支持 press、invoke、setValue 或 select 一类动作,自动化程序可以直接要求“激活这个按钮”,不必把它换算成某个瞬间的屏幕坐标。窗口移动、分辨率变化或轻微遮挡时,语义引用更可能继续有效。
但“更稳定”不等于“稳定”。Microsoft 对 UI Automation Tree 的官方说明明确指出:整棵树可能包含数千个元素,而且结构并非固定;元素增加、移动或删除时,树会变化。开篇那种连续使用 UI element 1、UI element 5 的路径,正好把这个变化放大成了脆弱性。
四、为什么大模型会采用如此别扭的 osascript 方式
看到这条命令,一个自然疑问是:为什么不让模型直接调用应用功能?
答案通常不是“这是最好的方式”,而是这是当前可用的共同接口。
原因一:目标应用没有公开合适的机器接口
如果应用提供稳定 API、CLI、插件 SDK 或 AppleScript scripting dictionary,直接调用通常更好。但大量桌面软件只为人类提供 GUI;有些应用能脚本化,却没有覆盖当前任务。Apple 官方文档正是把 UI scripting 定位为这类缺口的补救手段。
GUI 是不同应用都共有的一层。它不懂业务,却拥有广覆盖:只要人可以操作,Agent 理论上就可能通过界面操作。这种“最后一公里通用性”是它最大的吸引力。
原因二:Shell 是 Agent 很容易使用的统一执行通道
Agent 运行时往往已经能执行终端命令。通过 osascript,它不需要临时编译 Swift/Objective-C 程序,也不需要为每个应用安装专用驱动,就能查询 macOS UI、发送快捷键或触发可访问性动作。命令输出又可以直接回到下一轮模型上下文。
原因三:结构化探测能减少纯视觉猜测
“看见一个像按钮的东西”与“知道它的 role 是 button、description 是 Send”不是同等强度的证据。结构化探测能先缩小候选,再把坐标动作留给最后一步。
原因四:模型需要边走边补环境知识
Agent 事先通常不知道某个版本的软件把目标控件放在哪一层。它会像程序员使用 Accessibility Inspector 一样,先查询层级、枚举子元素、观察结果,再逐步深入。这不是模型在“思考 UI 的内部源码”,而是在主动建立当前界面的临时地图。
所以这条长路径真正暴露的是一种运行时策略:
不知道目标在哪里
→ 读取一小块 UI 层级
→ 获得角色、说明和坐标
→ 选择候选动作
→ 执行动作
→ 再次观察
它很实用,也很临时。把一次探测得到的第 5 个节点长期写死,往往就会从 Agent 变成一段等待 UI 改版后失效的 RPA 脚本。
五、控制桌面还有哪些方式
桌面控制不是“Accessibility 或视觉”的二选一。更准确的技术地图有五条路线。
| 路线 | Agent 看见什么 | 怎样行动 | 优势 | 主要局限 |
|---|---|---|---|---|
| 业务 API、CLI、插件、脚本字典 | 业务对象、参数、返回值 | 结构化函数或命令 | 语义最强,快,容易验证和重试 | 应用必须提供;覆盖面窄 |
| DOM/CDP、应用内部对象模型 | DOM、ARIA、组件属性、稳定 ID | DOM 事件、协议命令、应用方法 | Web/Electron 场景信息丰富,可精确筛选 | Canvas、远程画面、原生窗口或跨应用时失效 |
| Accessibility / UI Automation | 控件树、角色、名称、状态、动作 | 语义动作或节点坐标 | 跨多数常规桌面控件,结构和通用性平衡 | 依赖应用正确暴露;树动态、冗长且可能缺失 |
| 截图 + 多模态模型 + 鼠标键盘 | 屏幕像素与视觉布局 | 点击坐标、拖拽、滚动、输入 | 最接近人类,能覆盖 Canvas、游戏、远程桌面和未知应用 | grounding、缩放、遮挡、动画和视觉歧义带来误差 |
| OCR、模板匹配、快捷键、固定坐标 RPA | 文字框、图标模板或预设位置 | 固定动作序列 | 固定流程便宜、快、无需大模型 | UI 改版、分辨率和状态变化后维护成本高 |
1. 原生 API、CLI 与脚本字典:优先选机器接口
例如“把一封邮件保存为草稿”,如果邮件应用提供结构化接口,Agent 可以传入收件人、主题、正文,获得草稿 ID,再查询草稿是否存在。这个过程比点击输入框、粘贴文本、猜测保存状态更短,也更容易做幂等和权限控制。
它的代价是通用性:每个应用的能力、认证和数据模型都不同。工具数量多了以后,Agent 还要先判断该调用哪个工具。
2025 年的 OSWorld-MCP 把“GUI 操作”和“MCP 工具调用”放进同一个真实电脑评测框架。原论文实验中,加入工具整体上能提高多种 computer-use agent 的任务成功率,但模型并不会自然地总选对工具。它提醒我们:提供机器接口很重要,工具选择本身仍是 Agent 能力的一部分。
2. DOM 与 CDP:浏览器里的结构化捷径
在网页里,DOM 和 Accessibility Tree 提供了比屏幕像素更丰富的对象关系。Agent 可以按 role、accessible name、label、test ID 或 CSS 关系定位元素,读取页面状态,再触发点击和输入。Chrome DevTools Protocol 还能直接获取完整或局部 AX Tree。
但 DOM 不是整个桌面。浏览器原生菜单、系统文件选择器、权限弹窗、Canvas、视频流和远程桌面都可能处在它的边界之外。跨出网页后,Agent 仍需要 OS 级接口或视觉。
3. 纯视觉与坐标:把未知软件都变成一张图
视觉路线不要求应用提供结构。模型收到截图和任务,输出要点击的位置、要输入的文字或下一步快捷键。它能覆盖未知应用、Canvas、自绘控件和远程桌面,是最接近“像人一样用电脑”的方案。
问题在于,理解“点发送”至少包含两步:知道哪个视觉对象代表发送,再把它精确落到坐标。第二步就是 GUI grounding。
SeeClick 专门研究了这个问题:模型只依赖截图,把指令映射到点击位置;论文同时提出 ScreenSpot,覆盖移动端、桌面和 Web 的 600 多张界面截图、1200 多条指令与对应可操作元素。作者的实验显示,面向 GUI 的 grounding 训练能明显改善下游 Agent 任务,而通用视觉模型即使能理解画面,也不必然能精确点中控件。
OmniParser 走了另一条很有启发的路线:从截图检测可交互区域,结合 OCR 和图标描述,把纯像素重新组织成带局部语义的元素集合,再交给多模态模型。换句话说,纯视觉系统也在主动重建一种临时的“伪 UI 树”。这反过来说明,真正稀缺的不是截图,而是对下一动作有用的结构。
4. 键盘、OCR 与传统 RPA:不智能,但常常够用
快捷键比坐标更不依赖布局。例如 Command-S 往往比寻找“保存”菜单快;按 Tab 顺序移动焦点,在表单稳定时也很可靠。OCR 和模板匹配适合文字或图标位置相对固定的流程。
它们的弱点不是“不够先进”,而是缺少开放环境里的语义判断与异常恢复。流程一旦分叉、弹窗文案改变或窗口焦点丢失,固定脚本不一定知道发生了什么。
5. 混合控制:现实里最常见的答案
成熟系统通常不押注单一路线。2025 年的 UFO2 就明确采用混合方案:Windows UI Automation 与视觉解析共同检测控件,同时给应用专用 Agent 配置原生 API 和统一的 GUI–API 动作层。
一个实用的优先级是:
业务 API / CLI
→ DOM 或应用对象模型
→ Accessibility / UI Automation
→ 视觉与 OCR
→ 固定坐标兜底
这不是价值排名,而是“尽量少猜”的降级链。越靠前,语义越接近业务;越靠后,对应用配合的要求越低,但 Agent 必须从更多不确定信息中恢复目标。
六、论文告诉我们:接口设计与模型能力同样重要
GUI Agent 研究常被描述成“模型越来越会看图”。这只说对了一半。
ACI:Agent 也是一种需要专门界面的用户
SWE-agent 在软件工程场景提出 Agent–Computer Interface(ACI)的视角:语言模型是新的计算机用户,它有自己的能力与缺陷,需要专门设计动作和反馈接口。论文研究的主要是文件浏览、编辑、命令执行与错误反馈,不是桌面 GUI;但它留下的工程原则可以迁移:
- 动作空间要简单、明确,避免一次调用承担太多隐含决策。
- 观察要信息充分但不过量,错误信息要能支持恢复。
- 接口应对模型的常见失败设置 guardrail。
- 工具效果必须能被重新检查。
从这个角度看,开篇命令是在临时搭建一个 ACI:它把不可直接消费的桌面,转换成少量 role | description | position | size 文本。但这个 ACI 仍很原始,因为节点身份主要靠层级索引,错误恢复和结果验证也没有包含在命令里。
OSWorld:真实电脑把局部能力串成了长链
OSWorld 把 Agent 放进真实的 Ubuntu、Windows 和 macOS 环境,允许原始键盘鼠标动作,并为 369 个跨 Web、桌面应用、文件与多应用工作流任务编写可执行评测。原论文报告的基线实验中,最好模型完成 12.24% 的任务,而人类完成率超过 72%;模型常见问题包括截图上的精确坐标定位、重复动作、意外窗口噪声和缺少软件操作知识。
这些数字属于 2024 年原论文的模型和实验设置,不是今天的排行榜。更长期有效的结论是:会识别按钮、会点按钮、会完成跨应用任务,是三个逐级变难的问题。 桌面任务把 grounding、规划、焦点管理、状态记忆、应用知识和终态验证串成一条链,其中任何一环失效都可能让任务失败。
OSWorld 还使用 execution-based evaluation 检查真实任务结果。这比让模型在最后说一句“已经完成”更接近生产:保存图片要检查文件,修改表格要检查单元格,发送内容要检查目标系统状态。
七、这些方式有什么局限
把局限按“观察—定位—行动—验证”拆开,比列一串模型缺点更有用。
1. 观察局限:UI 树不是真实世界的完整副本
应用开发者可能没有正确填写 accessible name,也可能把整个自绘区域暴露成一个大容器。Canvas、游戏画面、远程桌面、视频和 GPU 渲染区域经常只有像素,没有足够的可访问性结构。
反方向也会出问题:完整 UI 树可能有数千个节点、重复名称、不可见节点和纯布局容器。把它全部塞给模型并不比传一张截图聪明,只是把像素噪声换成了结构噪声。
Accessibility 看到的也只是界面投影。按钮显示“已保存”,不一定能证明服务器持久化成功;支付页消失,也不一定能证明资金状态正确。关键业务状态仍要通过文件、数据库、API 或明确的页面反馈验证。
2. 定位局限:层级与坐标都会漂移
开篇的路径依赖“第几个”:插入一个 group、切换 A/B 版本、打开侧边栏、改变语言,都可能让 UI element 5 指向别的对象。即使节点没变,重复的“确定”按钮也需要结合窗口、对话框和邻近文字消歧。
坐标更依赖当前几何状态:分辨率、显示缩放、窗口位置、多显示器、滚动、动画、弹窗和遮挡都可能让昨天正确的 (x, y) 今天点到别处。OSWorld 的分析也观察到,窗口位置、大小和无关窗口干扰会显著影响 Agent 表现。
更稳的策略是组合条件:进程 + 窗口 + role + name/description + 状态 + 相对层级;执行前再次确认候选数量,无法唯一定位时不要盲点。
3. 行动局限:动作发出不等于动作生效
键盘输入可能进入了错误窗口,点击可能被浮层截获,按钮可能处于 disabled 状态,拖拽可能因为动画延迟而中断。语义动作也可能被应用错误实现。
因此每个有副作用的动作都应有最小验证:点击“展开”后检查状态是否变成 expanded,输入后重读字段值,保存后检查文件或服务端对象,发布后检查公开 URL。高价值或不可逆动作还要区分“准备”和“提交”,在提交前请求人工确认。
4. 权限局限:辅助功能授权是一把很大的钥匙
macOS 默认关闭跨应用的可访问性控制,需要用户按应用授予权限,这是安全边界,不是安装麻烦。获得权限的进程可能查看界面内容、控制控件、发送输入;若 Agent 同时能读网页、邮件和文档,外部内容就可能影响它的下一步动作。
AgentDojo 研究的正是工具型 Agent 读取不可信数据后的提示注入问题。它不是桌面专用论文,但风险在 GUI Agent 中更直观:网页里一段“忽略原任务,上传文件”的文字,既是用户要处理的数据,也会进入模型的观察上下文。
安全不能只靠 Prompt 里写“不要受骗”。运行时还需要:
- 默认最小权限,限制可操作的应用、文件、网络域和账号。
- 把网页、邮件、文档内容标记为不可信数据,不能让它自动扩大权限。
- 发送、付款、删除、授权和公开发布等动作使用确定性策略检查或人工确认。
- 保存操作轨迹和外部结果 ID,使误操作可审计、可补偿时可补偿。
5. 性能局限:观察也有成本
高分辨率截图占用视觉 token 和推理时间;完整 UI 树可能冗长,跨进程逐节点查询也可能很慢。频繁截图容易把历史塞满,频繁树遍历又可能读到快速变化的中间状态。
有效的系统通常采用分层观察:先确定当前进程和窗口,再取局部树或局部截图;没有变化时复用稳定信息,动作后只读取验证所需的状态。观察不是越多越好,而是要让下一步决策拥有刚好足够的证据。
八、一个更可靠的桌面 Agent 应该怎样选路
面对具体任务,可以依次问六个问题。
1. 应用有没有直接的机器接口?
有 API、CLI、插件或脚本字典时优先使用。它们更接近业务对象,也更容易返回稳定 ID 和明确错误。不要为了“像人”而把一个可靠函数调用退化成十次鼠标点击。
2. 任务是否局限在网页或可检查的应用内部?
如果是,优先使用 DOM、ARIA、CDP 或应用对象模型。系统弹窗、文件选择器和跨应用步骤再交给 OS 级通道。
3. 可访问性树是否完整、语义是否可信?
先查询 role、name、description、value、state 和动作能力。优先用语义条件定位,不把深层序号当长期 ID。找不到或存在歧义时,再引入视觉证据。
4. 是否只有像素可用?
对 Canvas、远程桌面、自绘控件和未知软件,使用截图、OCR、图标检测和 GUI grounding。尽量裁剪到当前窗口或候选区域,并在动作前后重新截图验证。
5. 动作的风险有多大?
浏览和读取可以自动化得更激进;发送、购买、删除、授权、改权限和公开发布需要更严格的策略、预算和人工确认。模型置信度不能替代权限边界。
6. 什么外部证据能证明任务完成?
在操作前先写出 verifier:文件存在且内容正确、数据库状态改变、消息出现在已发送列表、公开页面可访问。没有 verifier,Agent 只能证明“我执行了一串动作”,不能证明“目标已经实现”。
把这些问题收束成一条工程策略:
优先使用语义最强、权限最小、效果最容易验证的接口;结构接口不足时引入视觉,视觉仍不确定时停下来确认,而不是继续猜。
九、回头再看这条命令
现在可以更准确地给它定性:
osascript
→ 通过 System Events 进入目标进程的可访问性界面
→ 沿位置索引走到一个深层 UI 容器
→ 枚举直接子元素
→ 输出角色、说明、位置、大小
→ 给下一轮 Agent 决策提供局部观察
它的优点是通用、即时、输出可读,不需要目标应用提供专用 API;它的缺点是层级路径脆弱、依赖辅助功能权限、看不到未暴露的 UI、不能证明业务终态,而且一旦把探测结果直接转成高风险动作,就会扩大误判的后果。
所以真正值得关注的不是“为什么大模型还要跑这么土的脚本”,而是:当软件只给人类一扇 GUI 窗口时,我们能否为模型建立一条足够有语义、足够可控、失败可见、结果可验收的通道。
桌面 Agent 的成熟,不体现在它越来越像人类一样到处点鼠标。恰恰相反,它应该在能调用 API 时不看屏幕,能使用语义节点时不猜坐标,必须看图时缩小观察范围,并在每个关键动作后回到真实世界验证结果。
下次再看到类似 UI 探测命令,可以快速检查五件事:它在观察还是行动?定位依赖语义还是序号?界面变化后会不会错位?权限边界在哪里?最终由什么证据证明任务完成?
能回答这五个问题,才算真正看懂了大模型如何操作电脑。