在这里插入图片描述
computer use 这类需求,以前的做法是截图加坐标:拍一张界面图,让模型找按钮,算出位置,把鼠标挪过去点。

坐标不是按钮的属性,是这张图的属性。窗口挪一格、缩放变一下、列表滚一行,坐标就全废了,而且它不知道自己错了,照样按下去。

agent-desktop 换了个入口:不读像素,读操作系统本来给无障碍工具用的界面树。10,668 星,Rust 写,Apache-2.0,macOS、Windows、Linux 三端。这篇只讲怎么用、怎么接、哪里会卡住。

一、它到底是什么

一句话:给 AI agent 用的桌面操作 CLI 和 C 库。它读界面结构,给每个可操作元素分配编号,agent 点编号,点完再读一次确认。

先分清它不是什么,能省掉不少试错:

  • 它不是 agent。里面没有模型、没有 GUI、没有交互提示。每条命令输出一个 JSON 信封就退出进程。观察、决策、复查的循环跑在调用方
  • 它不管网页。网页内容交给 agent-browser,桌面应用才归它
  • 它不做像素匹配。看不到界面就报错,不会退化成"猜个位置点一下"
项目值
仓库vercel-labs/agent-desktop
语言 / 许可Rust / Apache-2.0
星数10,668(24 小时 +2,243)
命令60 个命令名,56 个可运行
平台macOS、Windows、Linux(x64 与 ARM64)
无障碍后端macOS 辅助功能 / Windows UI Automation / Linux AT-SPI

核心概念只有三个。snapshot 是一次界面观测,返回带编号的树;ref 是元素编号,形如 @s8f3k2p9:e8,自带快照 ID;session 是可选的命名空间,把快照、trace 和会话状态放在一起。

ref 只在自己那次快照里有效。跨快照使用会拿到 INVALID_ARGS,这是故意的。

在这里插入图片描述

二、不写代码也能用

装:

npm install -g agent-desktop
agent-desktop version

macOS 第一次要授辅助功能权限,它有引导:

agent-desktop permissions --guide
agent-desktop status      # 看平台、权限、可用能力

标准循环是三步:

agent-desktop snapshot --app Finder -i      # 读界面,-i 只看可交互元素
agent-desktop click @s8f3k2p9:e8            # 对编号动手
agent-desktop snapshot --app Finder -i      # 再读一次,确认结果

在这里插入图片描述
查有哪些应用、哪些窗口:

agent-desktop list-apps
agent-desktop list-windows --app Safari

密集界面别一次读全树,先看骨架再钻进去:

agent-desktop snapshot --skeleton --app Slack -i --compact
agent-desktop snapshot --root @s8f3k2p9:e3 -i --compact

三、从源码构建

需要 Rust 1.89 或更新。macOS 还要 Xcode 命令行工具,版本 13 以上;Windows 要 MSVC 构建工具;Linux 要 C 链接器。

git clone <项目仓库地址> && cd agent-desktop
cargo build --release -p agent-desktop

三个平台的适配器各自只能在自己系统上构建,所以测试要限定包,别全量跑。macOS:

HOST_PKGS=(-p agent-desktop-core -p agent-desktop-macos -p agent-desktop -p agent-desktop-ffi)
cargo test "${HOST_PKGS[@]}"

Linux 额外要构建平台包,并把 agent-desktop-linux-clipboard-owner 放在 CLI 旁边:

cargo build --release -p agent-desktop-linux --bins

构建完先跑一次自检,确认权限和后端都对:

agent-desktop status

四、接进自己的程序

走 CLI:每条命令输出一个信封,带 ok,成功给 data,失败给 error。error 里有 code、disposition 和通常有的 suggestion。重试规则单独放在下一节,因为它决定了你的脚本会不会重复提交。

这个字段是这套工具里最值得接的地方。它区分了"这个动作肯定没送出去"和"可能已经送出去了"——后者重复执行会造成重复提交,不能盲目重试。

走 FFI:每个 release 都带 libagent_desktop_ffi,可以在进程内直接调,不用每条命令 fork 一次:

import ctypes
lib = ctypes.CDLL("./lib/libagent_desktop_ffi.dylib")
lib.ad_adapter_create.restype = ctypes.c_void_p
lib.ad_adapter_destroy.argtypes = [ctypes.c_void_p]
assert lib.ad_init(7) == 0   # ABI 主版本要和头文件对上
adapter = lib.ad_adapter_create()
lib.ad_adapter_destroy(adapter)

交给 agent:二进制自带和自己版本匹配的说明书:

agent-desktop skills get desktop     # 循环、ref、验证与重试规则
agent-desktop skills get platform    # 当前系统的能力差异

也可以装进 agent 框架:npx skills add <项目仓库地址> --skill agent-desktop。或者在 AGENTS.md 里写一段:

Use `agent-desktop` to see and operate desktop apps. Before the first use, run
`agent-desktop skills get desktop` and `agent-desktop skills get platform`.

五、怎么判断一次点击到底成没成

截图路线的重试是盲的。一次点击失败,你只知道它失败了,不知道输入有没有送进应用。重试一次可能重复下单、重复发信;不重试可能整条流程断在这里。

agent-desktop 把这件事做进了返回值。出错时信封里带着:

error.code         STALE_REF / AMBIGUOUS_TARGET / TIMEOUT ……
error.disposition  本次动作送到了没有、重试安不安全
error.suggestion   下一步该怎么做

disposition 里有两个关键位:delivery 说明输入有没有到达应用,retry 说明这次重试安不安全。

  • delivery 为 not_delivered:动作确定没送到应用,重试不会造成重复,放心重试
  • delivery 为 delivered_unverified:输入确定发出去了,但效果没读到,这时候只能重新读一次界面确认,不能再发一遍
  • 判定不出来的时候按危险处理,先重新快照再决定

规则只有一条:retry 是 safe 才重试,其余一律停下来重新观测。

这是自研脚本最容易踩的地方。大多数桌面自动化只告诉你"失败了",重试与否全靠猜;猜错的代价是重复提交,而重复提交在真实业务里通常比失败更难收场。

六、几个坑

ref 不是持久 ID。 界面一变它就失效,报 STALE_REF。正确姿势是重新快照、拿新编号,不要缓存编号跨步骤复用。

窗口多会撞。 同一个应用开多个窗口时命令返回 AMBIGUOUS_TARGET,snapshot 会把候选窗口 id 列在 error.details 里,用 --window-id 指定。

密码框内容读不到。 系统标记为安全的字段,值不会出现在任何输出里,只能写不能读。这是设计,不是缺陷。

它不会自己动手。 默认 headless:走无障碍接口,不移动指针、不抢焦点、不合成键盘。语义路径走不通时它失败退出,不会偷偷降级成物理输入。要物理点击得显式加 --headed。

四个命令暂时不能用。 key-down、key-up、mouse-down、mouse-up 会直接拒绝执行,得等一个能接管按住状态的守护进程。所以 60 个命令名里实际可用 56 个。

它看不见自绘界面。 只读无障碍树,不做像素识别。游戏、canvas 自绘的、自己画控件又不声明角色的应用,读不到东西。上手前先 snapshot 一下看有没有树。

快照带隐私。 窗口标题、剪贴板、通知、截图、命令输出都可能含私密内容,debug HTML 里还嵌着截图和无障碍数据。trace 即使结构化字段脱敏,证据文件仍在。别把这类产物传上去或者贴进公开 issue。

七、小结

只想用:npm install -g agent-desktop,开权限,跑上面那个三步循环。

想搭自己的自动化:重点看 error.disposition,它决定这一步能不能重试。

想接进 agent:先让 agent 读 skills get desktop,别自己写循环规则,它自带的规则比临时想的完整。

它把坐标这个最容易出事的环节从流程里拿掉了,换成可以核对的编号。剩下的编排、验证、重试策略,还是调用方的事。

Logo

更多推荐