
最近 “cua” 这个词在科技圈突然多了起来不管是技术社区还是朋友圈都有人拿它开玩笑说“让 AI 自己 cua 一下桌面”。如果你第一反应是某个拼音梗其实也不奇怪但在我们这些做 AI 应用的人眼里它现在有一个更明确的含义Computer Use Agent也就是“能替人操作电脑的智能体”。直白点说以前想让程序自动干活要么写按键精灵脚本要么上 RPA 规则流程现在只要给大模型一句“帮我把这些文件按月份归档”“帮我在这个后台系统里把表格导出来”它就能看着屏幕、操作鼠标键盘一步步把任务完成。这个东西解决的是什么问题本质上是把“理解和执行”之间的鸿沟补上了——模型不仅会读会写还能“伸手”去操作系统里的各种应用。这篇文章想把 CUA 从原理到落地拆开聊透包括我踩过的坑和能直接抄作业的最小实现。适合正在研究 AI Agent、做办公自动化或者只是对“AI 操作电脑”这件事好奇的读者。1. 先把概念理清楚CUA 是“会动手”的 AI1.1 从聊天机器人到操作电脑的 Agent我们熟悉的大模型聊天机器人比如 ChatGPT给人的印象是“能说会道”。你问它“怎么把 PDF 转成 Word”它能给你写出一篇非常详细的教程但它不会真的帮你打开 WPS、点导出按钮。而 CUA 做的事情就是把最后这一步补上。它本质上是一个“感知-决策-执行”的闭环。感知靠的是截图和可访问性信息决策靠的是多模态大模型的推理能力执行靠的是底层的鼠标键盘控制指令。你可以把它想象成一个“长了手”的机器人只不过它的身体就是你的电脑桌面。模型看到屏幕上的图标、按钮、菜单栏然后根据用户给出的目标决定先点哪里、输入什么、什么时候停下。这种思路和人类使用电脑的方式几乎一致。我们人用电脑也是先看屏幕然后大脑判断下一步再操作鼠标键盘。CUA 把这三件事交给了 AI所以它天然能处理那些“没有 API 接口”“没有现成脚本”的三方软件。1.2 CUA 和 RPA、普通宏脚本有什么不同很多人会问这不就是 RPA 吗确实RPA机器人流程自动化已经存在很多年了银行、电商、财务系统里大量使用。但二者的核心区别在于“规则从哪来”。普通 RPA 需要人工把每一步操作录制成流程比如“打开 Excel - 读取 A 列 - 复制 - 粘贴到网页表单 - 点击提交”。只要界面布局变一下或者某个弹窗文案改了流程就可能断掉。而 CUA 不需要你写这些步骤你只需要告诉它目标比如“把这个 Excel 里的数据填到网页后台”它自己会去看屏幕临时决定操作路径。网页改版了它看到的新按钮还是能认出来。我给一个比较直观的对比表维度传统 RPACUA规则来源人工编写固定流程模型理解屏幕后动态决策界面变化适应性界面改版后脚本经常失效模型实时重读屏幕鲁棒性更好操作精度基于 DOM 节点或像素坐标精度高依赖视觉理解偶尔会有偏差落地成本商业产品 license 费用高大模型 API 按调用次数付费安全性行为完全确定可控性强行为有一定随机性需要护栏当然这并不意味着 CUA 能立刻取代 RPA。至少目前在需要稳定执行几千次、每次严格一致的任务上RPA 依然更可靠。CUA 更擅长的是“变化较多的长尾场景”。1.3 一个 CUA 系统的四个核心部件如果要在工程上拆解一个 CUA 系统一般会分成四块屏幕观察层负责截屏、获取窗口信息和可访问性树。最简单的就是纯截图进阶一点可以调用系统 API 拿到窗口控件结构让模型看到“语义化”的界面。指令决策层一个支持视觉输入的大模型它能基于截图和用户目标输出下一步动作。这个动作需要被定义成结构化格式比如 JSON。动作执行层把模型输出的指令翻译成真实的鼠标点击、键盘输入、滚动、快捷键等操作。任务编排层管理整个循环包括每一步的超时控制、最大执行步数、历史记录、失败重试和最终结果确认。我见过很多失败的 CUA 项目都是只做了前两块然后发现模型只是“嘴上说说”没有真正动起来。其实动作执行层的可靠程度直接决定了整个系统的稳定性。如果连“双击打开”和“单击选中”都分不清后续都白搭。2. 为什么 CUA 会成为热词需求与技术双双到位2.1 LLM 多模态能力是关键“眼睛”前几年也有人做“AI 操作电脑”的产品比如 Windows 上的一些语音助手但它们几乎都停留在“识别固定图标位置”的层次。背后的瓶颈是视觉理解能力不行模型分不清一个日历图标和邮箱图标的区别。最近这波 CUA 热最核心的驱动力是多模态大模型的成熟。以 GPT-4o、Claude、Qwen-VL 为代表的一批模型能直接“读图”还能定位图上物体的坐标。当模型看到一个红色按钮它能说“在 (412, 730) 处有一个‘确认支付’按钮”。这种能力过去只有人类具备。我自己的实测感受是两年前的模型会把“收件箱”和“发送”按钮混淆现在的模型已经很少犯这种低级错误了。模型对屏幕细节的感知能力已经到了可以信任的程度——这里的“可信任”是指你可以让它自动跑几步然后在关键节点人工确认。2.2 企业自动化场景的延伸CUA 火的另一个原因是企业在传统自动化的“最后一公里”上卡了很久。很多业务系统是外包做的老系统没有 API、没有数据库权限、甚至代码都找不到了但业务人员每天还得在里面录入数据、审核流程、导出报表。这些场景靠 RPA 能做但维护成本极高。CUA 提供了一个更便宜、更可维护的替代方案。它不需要系统方开放接口不需要开发人员写死流程只需要给模型一个屏幕和鼠标键盘控制权。于是在客服工单处理、财务报销审核、供应链信息录入等场景中CUA 都能切入。不过我要泼一盆冷水现在的 CUA 还没有到“开箱即用”的成熟度。它更像是“一个极其聪明的实习生”你给它清晰目标它能干得不错但偶尔也会自作主张点错按钮需要你盯一下。2.3 当前 CUA 能做什么、不能做什么我帮一个朋友做过一个内部工具用 CUA 自动登录一个老旧的 OA 系统然后批量下载附件。这个流程涉及输入账号密码、点击菜单、进入列表页、勾选多个复选框、点击下载。CUA 全程看着屏幕操作速度比人工快很多平均一分钟处理 20 条流程。但它也有明显边界。比如遇到需要滑动验证码、图片选择验证码的场景模型虽然能识别但有时会卡在“点击正确图片”这种交互上。另外如果系统响应很慢异步 loading 状态没有明显反馈模型可能会在页面还没加载完的时候就去点下一个按钮导致操作错乱。还有一个问题是误触。模型可能把“退出登录”认成“刷新”然后直接给你登出。所以做 CUA 时重要操作一定要加确认机制最好让模型在提交或删除前先“自言自语”说一句将要执行的动作由脚本判断是否需要人工放行。3. 手把手搭一个最小 CUA从截图到执行3.1 环境准备与工具选型先说结论我推荐用 Python 来做最小实现因为它生态最成熟。你需要安装这几个库pyautogui负责鼠标键盘控制Pillow负责截图处理openai或其他大模型 SDK 负责视觉对话。如果你只是想本地快速验证也可以直接用ollama跑一个支持视觉的模型比如qwen2.5-vl。安装命令就三行pip install pyautogui pillow openai如果你用的是本地模型可以换成pip install pyautogui pillow ollama这里有一点要特别注意pyautogui在 macOS 上需要给终端或 IDE 授权“屏幕录制”和“辅助功能”权限不然截图是黑的、点击也没反应。Windows 上相对宽松但也可能被安全软件拦截。我第一次跑的时候因为权限没开全折腾了半小时。3.2 第一步截屏并将图像传给模型CUA 的第一步永远是“看屏幕”。pyautogui.screenshot()会返回一张当前屏幕的图像你可以直接保存为本地文件也可以用内存字节流把它传给模型。我的习惯是先把截图缩放到一个合理的尺寸。因为大模型 API 对输入图像分辨率有上限太高的分辨率会浪费 token而且会导致响应变慢。我实测 1680x1050 的桌面截图直接传给 GPT-4o 能看清但上下文长得很快如果缩放到 1280 宽基本不影响关键按钮识别成本却能降不少。构造请求时把截图作为 image 消息把任务描述作为 text 消息。这里有个小技巧把“屏幕当前状态”和“任务目标”分开放在 prompt 里模型理解起来会更清晰。下面是一个简化示例import pyautogui import base64 from io import BytesIO from openai import OpenAI client OpenAI() def screenshot_to_base64(): img pyautogui.screenshot() img img.convert(RGB) # 控制最大宽度 max_width 1280 if img.width max_width: ratio max_width / img.width img img.resize((max_width, int(img.height * ratio))) buf BytesIO() img.save(buf, formatJPEG, quality85) return base64.b64encode(buf.getvalue()).decode(utf-8) def ask_model(task, b64_img, history): response client.chat.completions.create( modelgpt-4o, messages[ { role: user, content: [ {type: text, text: f任务{task}}, {type: text, text: f最近动作{history}}, { type: image_url, image_url: {url: fdata:image/jpeg;base64,{b64_img}} } ] } ] ) return response.choices[0].message.content3.3 第二步让模型输出可执行的操作指令模型返回的内容不能是自然语言一长段否则没法稳定解析。我一般会在 prompt 里强制模型输出 JSON字段定义成action、coordinate、value。例如{ action: click, coordinate: [820, 450], value: }常用的 action 我定义成五种click单击、double_click双击、type输入文本、scroll滚动、done表示任务完成。其中coordinate是屏幕坐标value是输入内容或滚动量。我把这段 prompt 模板固化下来你是计算机操作助手。我会给你一张屏幕截图你需要根据任务决定下一步动作。 请严格输出 JSON不要输出其他文字。格式如下 {action: click|double_click|type|scroll|done, coordinate: [x, y], value: ...} 要求 1. click 和 double_click 必须有 coordinate。 2. type 需要提供要输入的文本 contentcoordinate 可以置为 null。 3. 如果任务已完成输出 {action: done}。这里有个容易踩的坑很多模型会自作主张在 JSON 前后加解释性文字比如“好的我点击搜索按钮”。你需要在解析时做一次“清洗”把 json 代码块和前后缀都去掉。我后来干脆写了一个extract_json()函数专门处理模型输出。3.4 第三步把指令翻译成鼠标键盘动作拿到模型输出的 JSON 后执行层就是一个简单的 if-else 分支。只要action是click就调用pyautogui.click(x, y)如果是type就调用pyautogui.write(value)。写执行层的时候我建议给每个动作之间加 0.5 秒左右的停顿防止动作太快导致页面来不及响应。pyautogui.PAUSE可以全局设定停顿时间我实测设成 0.3 到 0.5 秒比较合适。另外一定不要关掉pyautogui.FAILSAFE它会在你鼠标移动到屏幕左上角时强制中断程序这是救命功能。import pyautogui import json import time pyautogui.FAILSAFE True pyautagui.PAUSE 0.5 def execute_action(action_json): try: action json.loads(action_json) except json.JSONDecodeError: return False, 模型输出不是合法JSON act action.get(action) coord action.get(coordinate) or (None, None) if act click: pyautogui.click(coord[0], coord[1]) elif act double_click: pyautogui.doubleClick(coord[0], coord[1]) elif act type: pyautogui.write(action.get(value, )) elif act scroll: pyautogui.scroll(action.get(value, 0)) elif act done: return True, 任务完成 else: return False, f未知动作: {act} return False, f已执行: {act}要注意pyautogui.write()只能输入 ASCII 字符如果你要输入中文得用pyperclip先把内容复制到剪贴板再pyautogui.hotkey(ctrl, v)粘贴。这个问题我第一次跑中文输入时才发现卡了很久。3.5 循环判断与退出条件最小 CUA 的主循环可以这样写先截图再问模型然后执行动作循环往复。为了避免模型卡在一个死循环里必须设置两个关键参数最大循环次数和“无进展”检测。我一般把最大循环步数设成 30 或 40。如果模型连续三次输出的动作相同或者连续五次都没有改变屏幕状态就判定为卡住自动停止。判断屏幕是否有变化最粗暴的方式是对比前后两张截图的像素差。用PIL.ImageChops.difference()就能拿到差异图算出变化区域面积。我不要求大面积变化只要有 0.1% 像素不同就认为页面有响应。这个方法简单但很有效from PIL import ImageChops import numpy as np def screen_changed(img1, img2, threshold0.001): diff ImageChops.difference(img1, img2) arr np.array(diff.convert(L)) changed_pixels (arr 10).sum() total_pixels arr.size return changed_pixels / total_pixels threshold完整的循环里我还会把每一步的动作和模型回复都存到历史列表里然后在下一步问模型时把最近几条动作传回去。这样模型能知道“我刚刚点了什么”避免重复操作。这一步非常重要如果模型没有记忆它很容易反复点击同一个地方。4. 实操中的坑与排查技巧4.1 截图模糊导致模型“看错”一开始我直接用 1080p 全屏截图结果发现模型经常把“最小化”按钮和“关闭”按钮看混。原因是窗口右上角的三个图标太小在 1280 宽的缩略图上几乎看不清。后来我把截图改成“目标窗口局部放大”先用 Windows API 或 macOS 的 CGWindowList 拿到当前活动窗口的位置和大小只裁剪出窗口区域再传给模型。识别准确率一下子提升了三成。如果你不想写系统 API也可以简单粗暴地把截图分辨率降得低一点后再针对屏幕的 1/4 区域截图。比如一个步骤里先“看到”整个桌面下一步再“放大”到某个具体区域。这种“先宏观后微观”的策略非常有效。4.2 坐标错位与多显示器问题坐标错位是 CUA 最常见的坑之一。多显示器环境下副显示器的坐标轴可能是负值也可能大于主屏分辨率。pyautogui对多显示器的支持还算可以但它依赖操作系统坐标系统如果你的模型输出的坐标是相对某张截图的局部坐标那必须做换算。我的做法是在生成截图时同时记录截图在虚拟桌面坐标系中的偏移量。比如截图范围是(1920, 0, 1920, 1080)那么模型输出的(x, y)必须加上偏移量(1920, 0)才是全局坐标。如果不加这个偏移模型会一直点在错误位置。另外Windows 缩放比例如果不是 100%也会造成坐标错位。比如显示设置是 125% 缩放pyautogui的坐标和真实像素之间存在缩放因子。我建议在项目配置里统一固定为 100% 缩放或者读取缩放比例后在代码里乘回去。4.3 模型“脑补”操作与幻觉指令大模型最大的问题之一是会“脑补”。比如屏幕上没有“确定”按钮模型却因为任务需要直接输出点击一个不存在的坐标。这种情况下程序会点到空白区域后续动作全部错乱。我的防线是在 prompt 里明确要求“如果界面上没有完成任务所需的元素请输出等待或返回上一个动作”并且限制它“不要点击屏幕底部或顶部可能触发系统弹窗的区域”。更重要的是在解析模型输出时加一个坐标合法性检查如果坐标落在屏幕范围外就丢弃这次动作并让模型重新生成。还遇到过一种特殊幻觉模型为了“结束任务”会提前输出done。我排查后发现它是因为看到页面没有明显变化误判任务完成。解决办法是要求模型在输出done时必须附带“任务完成的原因”由程序判断原因是否合理。4.4 卡死、超时与循环保护CUA 跑自动化时最怕遇到无限循环。假设系统弹了一个“确认登录”的窗口模型一直去点“跳过”按钮但按钮又不生效它就会重复这个动作几十次。如果没有人看着可能跑一晚上都是白费的。我建议在循环里加几个硬性保护最大步数限制比如 30 步。连续相同动作达到 3 次暂停并截取现场图。单次模型调用超过 30 秒直接重试。总运行时间超过某个阈值强制停止。这些保护逻辑看起来简单但实际项目里 90% 的稳定性都是靠它们撑起来的。模型判断能力再强也架不住外部页面卡死、断网、弹窗抢占焦点等环境问题。CUA 系统必须假设环境是充满噪音的。4.5 权限与安全底线最后聊一个很多教程不会细说的问题权限。pyautogui的鼠标键盘控制能力如果被滥用危害非常大。它本质上是一个键盘记录器加远程控制器。所以做 CUA 项目必须考虑安全边界。我自己的原则是只在隔离环境或测试环境中执行权限较高的操作。不把 CUA 用在登录态、支付、删除等高风险场景除非加了人工二次确认。记录所有动作日志方便审计。不要让模型输出任意的 shell 命令除非你明确知道后果。CUA 是工具工具本身没有对错但它能做什么、被允许做什么取决于使用者。如果你要把它接入生产环境最好做一个“操作白名单”机制凡是模型要执行的操作都要在规则的范围内才能通过。5. 从 Demo 到产品可以落地的方向5.1 客服与业务系统的自动化我目前看到的最靠谱的落地场景是企业内部老系统的自动化。很多公司都有一个或多个“很老但很重要”的业务系统新人都要花两周时间学操作录入订单、查流转状态、导出报表。CUA 可以做成一个“虚拟员工”通过屏幕操作这些系统把重复劳动接管掉。这类场景的特点是系统封闭、没有 API、界面稳定但操作繁琐。CUA 不需要系统方配合只需要一台电脑和一个授权账号就能顶上一个全职操作员。我帮朋友做的 OA 附件下载工具本质上就是这个方向。5.2 个人知识库整理与批量办公对于个人用户CUA 也能解决很多“文件搬家”类的问题。比如一键把散落在桌面的 PDF 按内容关键词归档、把上百个截图重命名、把钉钉里的聊天记录定期备份整理。这些操作如果用脚本写每个需求都要单独处理用 CUA 只需要一句自然语言描述它自己会去操作文件管理器。不过个人使用需要注意隐私问题尤其不要让模型把整个屏幕的内容传到外部 API。如果你在意数据安全建议用本地部署的视觉模型或者至少把敏感窗口遮挡后再截图。5.3 软件测试的自动化回归测试领域我一直觉得是被低估的方向。传统的 UI 自动化测试框架如 Selenium、Appium需要编写大量元素选择器维护成本高。CUA 可以直接模拟真实用户从“用户视角”操作界面判断页面是否正常响应。它的优势在于“跨技术栈”不管前端是 Vue、React 还是老的 jQuery 项目CUA 都一视同仁地看屏幕不需要知道内部实现细节。当然它的断言能力比较弱需要配合截图对比、日志检查等手段才能形成闭环。5.4 与流程引擎、定时任务的结合CUA 不应该是一个孤立的“跑马灯”它可以被嵌入到更大的系统里。比如用一个定时任务调度器每天凌晨触发 CUA让它登录后台系统把前一天的数据导出并发送邮件。或者把它接入企业微信机器人业务人员在聊天里提一句“帮我跑一下月度报表”后台启动 CUA完成后推送结果。这种组合玩法把 CUA 从一个“脚本替代品”提升为“组织里的数字员工”。但要注意它的执行结果需要做校验不能只靠模型说“完成”就当作成功。我会在流程结束后额外截图并让另一个非视觉模型判断结果是否合理用双保险降低误报。5.5 后续扩展思路如果你想让 CUA 更强可以考虑接入系统辅助功能接口。Windows 上的 UI Automation、macOS 的 Accessibility API可以拿到比截图更精确的控件信息比如按钮名、输入框状态、列表项结构。这样模型不仅能“看”还能“读”到界面的语义层。混合模式是现在比较流行的做法默认用截图做视觉理解当模型无法识别某个控件时再去查辅助功能树。我在一个表格录入场景里试过混合模式的准确率比纯截图高出近 20 个百分点而且因为不用频繁调系统 API性能损耗也在可接受范围内。最后再分享一个小技巧在让 CUA 跑任务之前先把屏幕分辨率固定下来关掉无关的通知然后把窗口布局收拾干净。我实测过干净的屏幕比什么参数调优都管用。另一个心得是别指望一个循环就能跑通给模型一个可以犯错、可以重试的环境CUA 的稳定性就会立刻上一个台阶。CUA 这个领域还很新持开放心态多试错收获往往比想象中多。