Skip to content

Computer Use Agent ​

CUA(Computer Use Agent)让 Agent 直接"看屏幕、操作鼠标键盘"完成 GUI 任务,而不再依赖被操作方提供 API。Anthropic 在 Claude 3.5 Sonnet 中首次开放 Computer Use 能力,OpenAI 紧接推出 CUA 模型驱动的 Operator 产品线,Browser Use、OpenHands 等开源项目也相继发力。CUA 的能力边界完全由"屏幕能看见什么、键鼠能做什么"决定——任何没有开放 API 的遗留 ERP、桌面软件、内网系统、行政系统都能被 Agent 接管,这是工具调用 Agent 永远无法触达的最后一公里。

CUA 与工具调用 Agent 的区别 ​

工具调用 Agent 操作的是结构化的 JSON 接口,CUA 操作的是屏幕上的像素和操作系统的输入设备。这个本质区别决定了 CUA 在架构上必须额外引入"显示子系统"和"输入注入子系统",Agent 才能感知和控制目标环境。

维度工具调用 AgentCUA
输入自然语言 / 结构化查询截图(多模态视觉)
输出结构化数据鼠标移动、点击、键盘输入、滚动
依赖被调用方提供 API / MCP Server操作系统 + 桌面环境 + 输入设备
错误检测函数返回码屏幕视觉差分 + 元素存在性判断
任务空间受限于工具覆盖范围几乎所有可见的 GUI 操作

CUA 的核心循环与传统 Agent 高度相似——观察 → 推理 → 行动——但观察环节从"读消息"变成"截屏分析",行动环节从"调函数"变成"模拟键鼠"。这意味着每次推理都要把整张屏幕的图片送进多模态模型,token 消耗和延迟都远高于普通 Agent。优化方向主要有两类:缩小截图(只截关键区域、降低分辨率)、用结构化中间表示替代原始像素(DOM 快照、UI 树、可访问性树)。

为什么必须运行在容器里 ​

CUA 本身是一个不可信代理——它会点击任何按钮、输入任何字符、在任意网页上自由操作。如果直接在用户的桌面环境运行,一个 prompt 注入就能让 Agent 删除文件、转账付款、下载恶意程序。把 CUA 装进容器是工业界的基本共识,本质上是给 Agent 一个"沙箱"。

容器提供的隔离能力是 CUA 安全运行的根基。文件系统层,Agent 看到的只是一个独立的 rootfs,写入操作只影响容器层;网络层,可以切断外网或仅放行必要域名,防止 Agent 被反向利用为跳板;进程层,目标软件运行在容器 PID 命名空间,与宿主机进程隔离;权限层,禁用特权模式,去掉 CAP_SYS_ADMIN 等危险能力,让 Agent 无法逃逸。

更重要的工程价值在于可复现性。每台 CUA 容器都从同一个镜像启动,浏览器版本、Cookie、扩展、字体、代理设置完全一致,调试一个任务时跑通的容器可以打包发版给其他节点使用。这种"环境即工件"的能力是 CUA 走向生产部署的前提条件——没有容器化的 CUA 永远停留在 demo 阶段。

容器内 CUA 的核心组件 ​

一个能跑 CUA 的 Linux 容器与传统 Linux 容器最大的区别,是它必须包含完整的图形栈——没有图形栈,CUA 就看不见屏幕、操作不了任何东西。

组件自底向上分四层。最底层是显示协议层,决定屏幕内容如何被绘制:X11 是三十年的老协议,几乎所有 Linux GUI 程序都支持;Wayland 是新一代协议,更现代但部分老旧软件兼容差。中间层是合成器(Compositor),负责把多个窗口合成为一张最终图像:X11 下合成器可以由 X server 兼任,Wayland 下必须由独立的合成器实现(labwc、sway、Weston 都是常见选择)。第三层是远程访问协议层,负责把合成器输出的图像编码后传输出去:VNC 是最广泛兼容的方案,noVNC 让浏览器无需客户端即可连接,RDP 在 Windows 环境更流行。第四层是 Agent 控制器,运行在容器内某个进程中,负责截图、调用多模态模型、解析行动指令、再用输入工具执行——这是 CUA 的"大脑",其余三层都是它的"眼睛"和"手"。

容器内还需要安装输入注入工具,让 Agent 能真正控制鼠标键盘。X11 下用 xdotool 移动鼠标、点击、键入字符,截图用 scrot 或 import;Wayland 下鼠标键盘工具是 wtype(文本输入)和 dotool/ydotool(鼠标移动和点击),截图用 grim。这些工具是 Agent 与桌面交互的桥梁,比 PyAutoGUI 这种跨平台库更贴近协议层——PyAutoGUI 内部最终还是调用 xdotool,但在容器里直接用 xdotool 脚本更容易调试和审计。

两种主流的显示栈 ​

业界最常见的两套方案都把 VNC 作为远程访问层,因为 VNC 协议足够简单、客户端兼容性好、H.264 编码成熟。区别在于显示协议层的选型。

X11 + Xtigervnc 路线 ​

早期方案是分两步走:先用 Xvfb 启动一个无头 X server 提供显示能力,再启动 x11vnc 把 X server 的画面编码成 VNC 流。这种方案有两个明显缺陷——Xvfb 没有合成器,所有窗口绘制都是软件光栅,CPU 占用高;x11vnc 性能瓶颈大,延迟通常在 100ms 以上。

Xtigervnc(TigerVNC 项目的子模块)把 X server 和 VNC server 合二为一,启动一个进程就同时提供 X11 显示和 VNC 访问,绕过了 Xvfb + x11vnc 的双进程开销。dtinth/xtigervnc-docker 是这个路线的代表性镜像,十几行 Dockerfile 就能起一个完整桌面,国内不少 CUA 项目的镜像也是 fork 自此。

X11 路线最大的优势是兼容性——几乎所有 Linux GUI 程序都默认支持 X11,不需要额外适配。DISPLAY=:1 xdotool ... 这种命令在任何 Linux 容器里都能直接运行,对调试和原型验证非常友好。劣势在于 X11 本身的安全模型已经过时,键盘记录、截屏攻击、网络嗅探都是协议层面就能做到的事;以及 X11 的窗口坐标体系对现代多 DPI 屏幕支持混乱,在 4K 屏幕上 Agent 看到的截图分辨率可能与实际操作坐标不一致。

Wayland + labwc 路线 ​

Wayland 是新一代显示协议,架构上比 X11 干净得多:合成器独占屏幕,每个应用通过协议直接提交窗口内容,截图、输入注入都是合成器提供的官方能力。labwc 是一个轻量级 Wayland 合成器,定位是"Openbox 的 Wayland 替代品",配置文件兼容 Openbox 的格式,启动只需几兆内存,适合塞进容器。

XT-Martinez/labwc-headless-docker 是这个路线的典型实现:labwc 作为合成器,wayvnc 把 labwc 的画面编码成 VNC 流,二者通过 Wayland 协议内部的截图和输入注入 API 协作。整套方案没有 X11 的任何代码,协议层面就杜绝了 X11 的诸多安全问题。

Wayland 路线的优势是延迟低、协议安全、内存占用小,特别适合多 CUA 实例并发的场景——单个宿主上可以同时跑十几个 labwc 容器,每个内存开销仅几十兆。劣势在于兼容性:部分老旧 GUI 程序还没有原生 Wayland 支持,需要跑在 XWayland 兼容层;部分截图/输入工具还在用 X11 的 API,需要换成 grim、wtype、ydotool 这套工具链;以及 Wayland 生态文档相比 X11 还是稀薄一些,踩坑时社区答案少。

选型对比 ​

新项目无特殊依赖优先选 Wayland + labwc,延迟低、安全模型好、并发友好;遇到老旧 GUI 软件或调试复杂问题时回退 X11 + Xtigervnc,最大兼容性是它的护城河。两种方案都可以叠加 noVNC,让 Agent 通过浏览器访问容器,省去 VNC 客户端。

参考项目:dtinth/xtigervnc-docker(X11 路线)、XT-Martinez/labwc-headless-docker(Wayland 路线)、livinhigh/claude-computer-use-agent(多 VNC 显示隔离 + Anthropic Computer Use API 的 FastAPI 集成)、NAISYS/xfce-computer-use-guide(XFCE 桌面 + TigerVNC 的生产级实践指南)。这些项目的 Dockerfile 和脚本都是工业界验证过的模板,可以直接 fork 改造。

Agent 接入显示栈的工作流 ​

Agent 在容器内的工作流是一个紧凑的循环。截图工具抓取当前合成器的输出,编码成 PNG/JPG 送进多模态模型;模型结合用户目标和历史轨迹,输出下一步动作——点击坐标 (x, y)、键入文本 hello、滚动 delta_y=300、等待 wait 2s;Agent 控制器解析动作指令,调用对应的输入工具执行;执行后再次截图,进入下一轮循环。

动作语义的规范化是工程关键。直接让模型输出 (x, y) 坐标是脆弱的,屏幕分辨率变化、网页响应式布局、缩放级别都会让坐标失效。更鲁棒的做法是让模型输出"语义动作"——click_button("提交")、type_into_field("邮箱", "user@example.com")、scroll_to("页面底部")——由 Agent 控制器翻译成具体的 xdotool/wtype 调用,翻译过程可以加入"先定位元素再点击"的中间步骤,提升成功率。

多模态模型的输入优化是性能瓶颈。每张截图 100KB 起,5MB 大图很常见。1280×720 的截图压缩后大约 500-800 token,2560×1440 直接超过 2000 token——一个 30 步的 CUA 任务,光截图就要消耗 6 万 token。优化手段包括:截图前裁剪到感兴趣区域(去掉空白和无关元素)、降低分辨率到 1024×768、统一缩放到模型训练的分辨率、用结构化表示(DOM 树、可访问性树)替代原始像素。

工程经验与陷阱 ​

CUA 在生产环境跑起来后,真正的难点不是模型能力,而是"模型和现实之间"的无数边界条件。焦点丢失是最经典的坑——xdotool 点击 (x, y) 之前没有先 xdotool windowactivate,可能点到的是另一个窗口或者任务栏;多显示器环境同样要小心,DISPLAY=:1 选错了显示器,所有坐标全错位。

DPI 缩放是另一个深坑。宿主机 4K 屏配 200% 缩放,VNC 推流给 Agent 的画面按什么 DPI 计算?合成器内坐标和物理像素的对应关系在 X11 和 Wayland 下完全不同,跨平台迁移 Agent 脚本时务必把缩放参数当作一等公民处理。Cookie 弹窗、模态对话框、登录验证码这些"打断流程的元素"也要在 prompt 里提前警告,让模型遇到它们时主动等待或者截图给运维介入,而不是傻乎乎地点确认按钮。

反检测是商业 CUA 部署的高级话题。Cloudflare、Akamai 等服务的反机器人系统会通过 WebGL 指纹、Canvas 噪声、鼠标轨迹熵检测 CUA 流量。要让 CUA 看起来像真人,需要在 Agent 控制器里加入随机延迟、贝塞尔曲线鼠标轨迹、随机滚动、偶尔的"误触"回退,这些策略比模型能力更影响实际成功率。