• 简体中文
  • Computer Use

    computer-use 是一个驱动真实桌面的 worker 进程,提供:

    • 鼠标和键盘
    • 截图
    • 剪贴板
    • 窗口列表
    • 无障碍树(accessibility tree)

    它独立于 aiod 运行,可以部署在任何带桌面的主机上,例如:

    • Ubuntu 桌面
    • 跑 Xvfb 或 Xvnc 的虚拟机
    • 带交互登录会话的 Windows 主机

    aiod 只代理它的 API,不直接接触桌面。这层进程边界让桌面能力成为可选项:没有桌面时 aiod 照常运行,有桌面时通过 computer-use 触达。

    桌面能力只在 v2 提供,路径在 /v2/computer/* 下。

    能力路由说明
    能力探测GET /v2/computer/infodisplay、分辨率、支持哪些操作
    截图GET /v2/computer/screenshot获取当前桌面截图(PNG)
    动作POST /v2/computer/actions鼠标、键盘、滚动、剪贴板、窗口、节点,单个动作;?include_screenshot=true 时响应中包含执行后的桌面截图
    批量动作POST /v2/computer/actions/batch按顺序执行一批动作
    指针、剪贴板、窗口GET /v2/computer/cursor、/clipboard、/windows读取当前状态
    无障碍树GET /v2/computer/accessibility、/accessibility/nodes按 role、name 定位元素
    录屏POST /v2/computer/recordstart、status、stop

    v1 为 1.x 客户端保留两个别名:

    • POST /v1/browser/actions
    • POST /v1/display/record

    路由对照见 从 1.x 迁移。

    本页前半部分介绍 agent 工具使用的动作,后半部分介绍用来观察或接管同一个桌面的查看器。

    基于 CDP 的页面自动化见 浏览器 API;完整的桌面任务演示见 Computer Use 示例。

    面向 agent 的工具

    连接 daemon 与 worker

    worker 监听 AIO_COMPUTER_USE_LISTEN(默认 0.0.0.0:18100);aiod 通过 AIO_COMPUTER_USE_URL(默认 http://127.0.0.1:18100)连接它,并代理桌面路由。

    worker 没在运行时,computer 路由返回 503:

    {
      "success": false,
      "message": "computer-use worker is not available",
      "data": null,
      "hint": "start computer-use or set AIO_COMPUTER_USE_URL"
    }

    前置条件

    Linux:需要一个可达的 X11 display。设置 DISPLAY;display 需要 cookie 鉴权时再设置 XAUTHORITY。GET /v2/computer/info 会返回探测到的 display 和 xauthority。

    Windows:需要一个交互登录会话。aiod 可以作为 Session 0 的 SCM 服务运行,computer-use 必须在交互登录会话里,才能看到桌面并注入输入。

    启动 worker

    computer-use 随 aiod 一起发布,见 Releases。Linux 用安装脚本一并装上:

    curl -fsSL https://aio-static.tos-cn-beijing.volces.com/install.sh | AIOD_WITH_COMPUTER_USE=1 sh

    Windows 下载 https://aio-static.tos-cn-beijing.volces.com/latest/windows-x86_64/computer-use.exe。

    它没有命令行参数,只读环境变量:DISPLAY、XAUTHORITY 指定 display,AIO_COMPUTER_USE_LISTEN 指定监听地址。

    Linux:

    DISPLAY=:99 XAUTHORITY=$HOME/.Xauthority computer-use
    curl -s http://127.0.0.1:8091/v2/computer/info

    supervisord(Computer 镜像的写法):

    [program:computer-use]
    command=/usr/local/bin/computer-use
    environment=DISPLAY=":99",XAUTHORITY="/home/sandbox/.Xauthority",HOME="/home/sandbox",USER="sandbox"
    user=sandbox
    autorestart=true
    stdout_logfile=/var/log/computer-use.log
    redirect_stderr=true

    Windows:computer-use.exe 不能作为服务运行,要注册成登录触发的计划任务,见 Windows。

    查看当前可用能力

    GET /v2/computer/info 返回 worker 探测到的 display,以及这个 display 支持的能力:

    curl "$BASE_URL/v2/computer/info"

    data 字段:

    • available —— worker 是否连上了 display
    • display —— worker 找到的 display
    • xauthority —— worker 找到的 XAUTHORITY
    • screen_resolution —— {width, height}
    • capabilities —— {screenshot, actions, clipboard, recording}
    • warnings —— 探测过程中发现的问题

    v1 没有桌面 info 路由。这个 plane 的状态由沙箱能力探测报告:

    curl "$BASE_URL/v1/capabilities"

    data.computer 字段:

    • status —— ready、degraded 或 absent
    • display、resolution —— worker 找到的显示环境
    • screenshot、actions、clipboard、recording、accessibility —— 每项操作一个标志位
    • accessibility_backend —— atspi、uia,没有编译进后端时是 null
    • provider、missing、warnings —— 能力来源,以及缺了什么

    worker 没在运行时,响应如下:

    {
      "status": "absent",
      "provider": null,
      "display": null,
      "screenshot": false,
      "actions": false,
      "clipboard": false,
      "recording": false,
      "accessibility": false,
      "accessibility_backend": null,
      "resolution": {
        "width": null,
        "height": null
      },
      "missing": [
        "computer-use"
      ],
      "warnings": [
        "computer-use worker probe failed: error sending request for url (http://127.0.0.1:18100/capabilities)"
      ]
    }

    需要worker 的可用性和它找到的 XAUTHORITY 时,切到 v2:

    截图

    响应体就是图片本身:

    curl "$BASE_URL/v2/computer/screenshot" -o desktop.png

    获取当前桌面截图(PNG),包含所有窗口、任务栏、对话框。响应头带上尺寸 —— x-image-width、x-image-height、x-screen-width、x-screen-height。

    v1 没有单独的桌面截图路由。用动作接口返回的截图;如果只想截图,可以发一个不改变桌面状态的 WAIT 动作:

    curl -X POST "$BASE_URL/v1/browser/actions?include_screenshot=true" \
      -H "Content-Type: application/json" \
      -d '{"action_type": "WAIT", "duration": 0.5}'

    响应里的 screenshot 是桌面截图,格式为 base64 PNG。

    Python SDK 不会为该路由附加查询参数,因此需要直接发 HTTP 请求。GET /v1/browser/screenshot 截取的是浏览器页面,不是整个桌面。

    需要不附带动作、直接取到 PNG 响应体时,切到 v2:

    执行动作

    每次请求执行一个动作,坐标是屏幕坐标。加 ?include_screenshot=true 可以把观察步并入动作步,响应里会多一张执行后的桌面截图:

    curl -X POST "$BASE_URL/v2/computer/actions" \
      -H "Content-Type: application/json" \
      -d '{"action_type": "CLICK", "x": 640, "y": 400}'
    
    curl -X POST "$BASE_URL/v2/computer/actions?include_screenshot=true" \
      -H "Content-Type: application/json" \
      -d '{"action_type": "SCROLL", "dx": 0, "dy": -3}'
    curl -X POST "$BASE_URL/v1/browser/actions" \
      -H "Content-Type: application/json" \
      -d '{"action_type": "CLICK", "x": 640, "y": 400}'
    
    curl -X POST "$BASE_URL/v1/browser/actions?include_screenshot=true" \
      -H "Content-Type: application/json" \
      -d '{"action_type": "SCROLL", "dx": 0, "dy": -3}'

    别名和 v2 路由是同一个 handler:请求体相同,响应相同。

    Python SDK 每次发一个带类型的动作:

    Python
    TypeScript
    from agent_sandbox import Sandbox
    from agent_sandbox.browser.types.action import Action_Click
    
    client = Sandbox(base_url="http://127.0.0.1:18091")
    client.browser.execute_action(request=Action_Click(x=640, y=400))

    它的动作联合类型覆盖鼠标、键盘和 WAIT。下面列出的剪贴板、窗口和节点动作要在同一个路由上走 HTTP,动作后截图也一样。

    v1 和 v2 的动作请求体相同,例如点击屏幕坐标 (640, 400):

    {
      "action_type": "CLICK",
      "x": 640,
      "y": 400
    }

    请求体直接描述动作,action_type 决定执行哪一种:

    action_type必需参数可选参数
    MOVE_TOx、y——
    MOVE_RELx_offset、y_offset——
    CLICK——x、y、button、num_clicks
    RIGHT_CLICK——x、y
    DOUBLE_CLICK——x、y
    MOUSE_DOWN——button
    MOUSE_UP——button
    DRAG_TOx、y——
    DRAG_RELx_offset、y_offset——
    SCROLL——dx、dy
    TYPINGtextuse_clipboard
    PRESSkey——
    KEY_DOWNkey——
    KEY_UPkey——
    HOTKEYkeys——
    WAITduration——
    SET_CLIPBOARDtext——
    WINDOW_ACTIVATEwindow_id——
    WINDOW_MINIMIZEwindow_id——
    NODE_FOCUSnode_id——
    NODE_INVOKEnode_idaction
    NODE_SET_VALUEnode_id、value——
    • duration 单位是秒;keys 是一个列表,复制是 ["ctrl", "c"]。
    • window_id 来自窗口列表,node_id 来自无障碍树,两者见下文。
    • 两条限制对每个动作都成立,单发和批量一样:单个 WAIT 最长 10 秒,单个 SCROLL 每个方向最多 100 格。
    • TYPING 对 ASCII 文本直接按键输入;含其他字符的文本走剪贴板(use_clipboard,默认 true),会覆盖剪贴板原有内容;use_clipboard: false 时这类文本返回 400,因为按键输入会丢字。剪贴板里的文本用 Shift+Insert 粘贴,终端和 GTK、Chromium 窗口都接受这个组合键。
    • PRESS、HOTKEY、TYPING 成功只表示输入已送到焦点窗口,不表示应用已经响应。用截图确认结果。
    • 每种类型的完整 schema 见 API 参考。

    响应包含 status 和 action_performed。请求动作后的截图时,响应里还会多一张 base64 PNG。

    如果截图失败,响应会在动作结果旁返回 screenshot_error,但不会让整个请求失败;动作本身已经执行。

    Windows 的安全桌面(UAC 弹窗、锁屏)会拒绝输入,见 Windows。

    批量动作

    一个请求按顺序执行一批动作。执行期间,其他调用不能操作桌面:

    curl -X POST "$BASE_URL/v2/computer/actions/batch" \
      -H "Content-Type: application/json" \
      -d '{"include_screenshot": true,
           "actions": [
             {"action_type": "HOTKEY", "keys": ["ctrl", "l"]},
             {"action_type": "TYPING", "text": "example.com"},
             {"action_type": "PRESS", "key": "enter"}
           ]}'

    这个路由里的 include_screenshot 是 body 字段,不是查询参数。

    每批最多 50 个动作,所有 WAIT 加起来最多 20 秒。

    data 字段:

    • performed —— 已执行的动作,按顺序
    • failed_index、error —— 哪个动作中断了这批,以及原因;它之前的都执行了
    • status、reason —— 主机拒绝输入时是 denied 和机器可读的原因
    • screenshot、screenshot_error —— 最后一个执行到的动作之后的那一帧

    需要一串动作中间不被其他调用插入时,切到 v2:

    执行自动化脚本

    桌面就是一个普通的 X display,每条命令都带着 DISPLAY,所以直接操作屏幕的脚本可以通过 POST /v2/commands(v1 为 /v1/bash/exec)跑在上面这些动作所用的同一个桌面上。Computer 镜像自带 xdotool;pyautogui 用 pip install pyautogui 装一次即可:

    sb = Aio(BASE_URL)  # 示例首页定义的 helper
    sb.post("/v2/commands", command="pip install --quiet pyautogui", timeout=280)
    sb.post("/v2/commands", command='''python3 - <<'EOF'
    import pyautogui
    pyautogui.moveTo(320, 240)
    pyautogui.click()
    pyautogui.write("hello")
    pyautogui.screenshot("/tmp/desk.png")
    EOF''')
    print(sb.get("/v2/computer/cursor"))   # {'x': 320, 'y': 240}

    读取指针、剪贴板、窗口列表

    端点返回说明
    GET /v2/computer/cursor当前指针位置屏幕坐标
    GET /v2/computer/clipboard剪贴板文本读取超时 5 秒,上限 1 MiB
    GET /v2/computer/windows顶层窗口列表xdotool 路径下最多 200 个

    窗口列表结构:

    {snapshot_id, windows: [{window_id, title, process_id, bounds, minimized}]}

    window_id 是原生窗口句柄,不是列表序号。窗口存在期间一直有效;对已关闭窗口的操作会失败,不会误操作后来复用同一位置的窗口。

    需要窗口列表、指针位置或剪贴板文本时,切到 v2:

    通过无障碍树操作

    两个路由:

    • GET /v2/computer/accessibility —— 返回整棵无障碍树。
    • GET /v2/computer/accessibility/nodes —— 在整棵树上做扁平搜索。

    两者都支持 ?role=button&name=Sign+in 这类查询参数,字段相同:

    字段取值含义
    scopeforeground(默认)、desktop只看活动窗口,还是遍历所有顶层窗口
    role、namestring只保留匹配的部分
    matchsubstring(默认)、exact、regexrole 和 name 的比较方式
    states逗号分隔节点必须同时具备的状态(enabled,showing)
    include_offscreenboolean,默认关包含后端标记为屏幕外的节点
    max_depth1–64,默认 32最大深度
    max_nodes1–20000,默认 5000最大节点数
    timeout_ms100–60000,默认 5000遍历超时
    limit1–1000,默认 50仅 nodes:最多返回多少节点

    超出范围的值会被限制在允许区间内,不会报错。role 和 name 在所有匹配模式下都不区分大小写。

    truncated 表示结果达到了上限,没找到某个节点不代表它不存在。只有 nodes 支持 ?node_id=;传入后解析单个句柄,忽略其他搜索参数。

    node_id 在元素存在期间有效,跨快照也有效。窗口关闭或应用重启后元素消失,再用这个 id 会返回 404。

    每个返回节点带 node_id、role、name,以及 bounds、states、value 和 actions(该元素声明支持的动作名):

    {
      "node_id": "a::1.30:/org/a11y/atspi/accessible/247",
      "role": "link",
      "name": "Open the report"
    }

    把 node_id 填进动作请求体,就按元素操作,不用像素坐标:

    {
      "action_type": "NODE_INVOKE",
      "node_id": "a::1.30:/org/a11y/atspi/accessible/247"
    }

    三种节点动作:

    • NODE_INVOKE 不带 action 时执行节点的第一个动作;带 action 时执行指定的那个。元素没有声明该动作会返回 409,并列出已声明的动作。
    • NODE_FOCUS 只把焦点移到元素上,之后可以用 TYPING 输入。
    • NODE_SET_VALUE 需要 value,写入元素的文本或数值;元素两者都没有时返回 409。

    需要按 role 和 name 定位元素、而不是用像素坐标操作时,切到 v2:

    后端按平台提供:Windows 用系统自带的 UI Automation(UIA),无需安装;Linux 用 AT-SPI2(文档)。

    Linux 上要让桌面能被读成一棵树,需要三件事:

    1. 安装 at-spi2-core,它提供 org.a11y.Bus 这个 D-Bus 服务和总线启动器。
    2. 有一条会话 D-Bus,worker 通过 DBUS_SESSION_BUS_ADDRESS 找到它。
    3. 应用自己暴露树。GTK 和 Qt 应用默认暴露;Chromium 和 Electron 要用 --force-renderer-accessibility 启动。

    Computer 镜像已装好 at-spi2-core、拉起会话 D-Bus,并用这个参数启动 Chromium。

    错误码:

    状态码说明
    501没有可用的后端:平台尚未实现,或者上面第 1、2 条没满足。重试不会改变结果
    503后端存在,但当前读不到,例如没有交互桌面,或者没有获得焦点的窗口

    录屏

    POST /v2/computer/record 基于 ffmpeg 录制,提供 start、status、stop 三个动作。

    POST /v1/display/record 提供同样的能力:action 取 start、status 或 stop。Python SDK 支持该路由的全部参数:

    Python
    TypeScript
    client.display.record(action="start", save_path="/workspace/recordings/session.mp4")
    client.display.record(action="stop")

    录制基于 ffmpeg,一次只能跑一个录制任务。start 接受这些采集参数:

    参数范围默认值
    fps1–6030
    crf0–51(越低画质越好)30
    max_duration最长 600 秒60
    width、height像素探测到的屏幕分辨率

    save_path 可以省略。省略时,文件写入临时目录,文件名为 recording_<timestamp>.mp4。

    父目录不存在时会自动创建;worker 无法写入目标目录时返回 400。

    data 字段:

    • status —— recording、stopped 或 idle
    • duration —— 已录制的秒数
    • save_path —— 文件写到了哪里
    • file_size_bytes —— 停止之后的文件大小

    把录像存到 文件 API 能取到的路径下。销毁宿主前先停止录制,这样文件才完整可播放。

    直接访问 worker API

    computer-use 也能不经 aiod 直接被访问:

    路由作用说明
    GET /healthz存活探测公开
    GET /capabilities桌面能力探测schema_version 1;设置了 API key 时需要携带
    GET /openapi.jsonworker 自己的接口契约公开
    GET /metricsPrometheus 文本设置了 API key 时需要携带

    单独部署或给 worker 做健康检查时有用。

    Human in the loop

    人可以进入 agent 正在驱动的终端、浏览器或桌面,查看运行过程,也可以接手登录或验证码,再把控制权交回去。

    daemon 不需要为此改变配置。预构建镜像通过网关提供这些查看器,每个查看器都连接到 agent 已经在使用的对象:

    查看器镜像上的路径显示什么
    noVNC/vnc/index.htmlworker 驱动的 X display;可观察,也可接管
    DevTools/browser-ui、/cdp/devtools/*Chromium 的标签页,走 agent 在用的同一个 CDP
    WebShell/terminal?session_id=…一个 PTY 会话;链接由 GET /v1/shell/terminal-url 生成
    code-server/code-server/同一个文件系统上的 IDE;默认关闭,DISABLE_CODE_SERVER=false 打开
    JupyterLab/jupyter同一个文件系统上的 notebook;默认关闭,DISABLE_JUPYTER=false 打开

    Xvnc 同时是 X server 和 VNC server。人的点击直接作用于 display,worker 会在下一次截图中看到结果。

    daemon 只提供 API;单独运行的 aiod 对这些查看器路径都返回 404。

    预构建镜像已经配置好这些组件。

    AIO 镜像在 DISPLAY=:99.0 上运行 Xvnc、openbox 和 Chromium,并提供 noVNC、DevTools 和 WebShell。

    Computer 镜像在此基础上设置 AIO_DESKTOP=xfce。

    XFCE 会话接管 display,computer-use worker 和 aiod 一起启动。会话 D-Bus 为 AT-SPI 提供支持,Chromium 使用 --force-renderer-accessibility,因此标签页内容会出现在无障碍树中。

    相关页面