上周帮一个朋友调他的 AI Agent。需求很简单:自动登录一个政府网站,填三张表,提交。
他选了 VNC 路线——Agent 通过远程桌面连上一台真实 Mac,操作真实的 Chrome 浏览器。逻辑很对:真实浏览器没有 navigator.webdriver 标记,没有 CDP 连接痕迹,TLS 指纹是真的,Canvas 指纹是真的。从浏览器的视角看,就是一个正常用户坐在键盘前。
他很有信心。然后 Agent 在第二步就被拦住了。
不是被防火墙拦的,不是被反爬拦的。是 Cloudflare Turnstile 弹了一个无感验证,Agent 的鼠标 瞬移 到了按钮上, 零毫秒 完成点击。没有移动轨迹,没有加速度变化,没有人类手指的微颤。
一个人类不可能这样操作。而 Cloudflare 知道。
一个常见误解
很多人对 Computer Use Agent 的理解停在一句话:「操作真实浏览器,所以不会被检测。」
这句话对了一半。在 Agent 操作浏览器的九条路线 里,我把浏览器自动化分成了九个梯队。VNC 和 Computer Use 属于最「重」的那一档——成本最高,速度最慢,但反检测能力最强。
但「反检测能力最强」不等于「不会被检测」。
因为检测不是一道题,是四层考试。你过了前三层,第四层照样能让你挂。
四层检测模型
我把浏览器反自动化检测分成四层。每一层的检测对象不同,对抗手段也不同:
L1 环境检测 你是不是自动化框架?
L2 指纹检测 你的浏览器是不是真的?
L3 行为检测 你的操作像不像人?
L4 信誉检测 你这个身份有没有历史?
# generated by hugo AI
L1 环境检测:检查 navigator.webdriver、CDP 连接、$cdc_ 变量、headless 标记。Playwright 和 Puppeteer 在这一层就会暴露。VNC 操作真实桌面,天然通过。
L2 指纹检测:Canvas 渲染、WebGL 参数、TLS/JA3 指纹、HTTP/2 帧顺序、字体列表、插件列表。Headless Chrome 的指纹跟真实 Chrome 有几十处差异,stealth 插件能补一部分,但补不全。VNC 用的是真实浏览器,指纹天然正确。
L3 行为检测:鼠标轨迹、点击偏移、打字节奏、滚动模式、页面停留时间。这一层不看你的浏览器是什么,只看你 怎么操作。VNC 和 Computer Use 在这一层 没有任何天然优势——甚至因为坐标点击是瞬移,比 Playwright 的 mouse.move() 还更容易暴露。
L4 信誉检测:IP 历史、Cookie 积累、账号年龄、Google 账号行为画像。新环境 + 异常行为 = 低信任分。这一层跟技术路线无关,只跟「养号」有关。
用一张表总结各路线在四层上的表现:
| 路线 | L1 环境 | L2 指纹 | L3 行为 | L4 信誉 |
|---|---|---|---|---|
| VNC + 真实浏览器 | ✅ 无痕迹 | ✅ 真实 | ⚠️ 需要模拟 | ⚠️ 需要养号 |
| Anthropic Computer Use | ✅ 无痕迹 | ✅ 真实 | ⚠️ 需要模拟 | ⚠️ 需要养号 |
| OpenAI Operator | ❌ 云端 Chromium | ⚠️ 需伪装 | ⚠️ 需要模拟 | ❌ 新环境 |
| Playwright + stealth | ⚠️ 可被检测 | ⚠️ 部分伪装 | ❌ 无鼠标事件 | ❌ 新环境 |
| 直接 API 调用 | N/A | N/A | N/A | N/A |
关键洞察: VNC 和 Computer Use 在 L1-L2 上是等价的——都是操作真实桌面,天然干净。但 L3 才是真正的战场。而大多数团队把 90% 的精力花在了 L1-L2 上。
三条 Computer Use 路线
目前 Computer Use Agent 有三条主要技术路线。它们的感知层、决策层、执行层设计完全不同。
Anthropic Computer Use:纯视觉,坐标驱动
Claude 的 Computer Use 是最「暴力」的方案:
循环:
1. screenshot() → 1280×800 PNG
2. 图片发给 Claude(base64 塞进 tool_result)
3. Claude 返回 tool_use: computer(action="click", coordinate=[640, 320])
4. xdotool / cliclick 在坐标上执行操作
5. 等 0.5-2 秒 → 回到 1
# generated by hugo AI
没有 DOM,没有 Accessibility Tree,没有 CDP。Claude 看到的就是像素。它说「点击坐标 (643, 312)」,执行层就真的在那个像素位置点一下。
这意味着它不依赖任何浏览器内部接口——反检测上最干净。但也意味着 所有定位都靠视觉猜测。
Anthropic 的参考实现用了一个改进:Set-of-Mark(SoM)。在截图上给每个可交互元素叠加数字标注,Claude 说「点击 7」而不是「点击 (643, 312)」。准确率提升明显,但本质上还是视觉定位。
macOS 上的执行层核心就三行:
import subprocess, base64
def click(x: int, y: int) -> None:
subprocess.run(["cliclick", f"c:{x},{y}"])
def type_text(text: str) -> None:
subprocess.run(["cliclick", f"t:{text}"])
def screenshot() -> str:
subprocess.run(["screencapture", "-x", "/tmp/screen.png"])
with open("/tmp/screen.png", "rb") as f:
return base64.b64encode(f.read()).decode()
# generated by hugo AI
cliclick 底层走 macOS 的 CGEvent API,需要 Accessibility 权限。事件在 WindowServer 层面注入,对应用完全透明——浏览器不知道点击来自物理鼠标还是 cliclick。
OpenAI Operator:专用模型 + 沙箱浏览器
Operator 的架构跟 Anthropic 有本质区别。
第一, CUA 是微调模型。OpenAI 在 o3 基础上针对 GUI 操作做了 RL 训练。在 OSWorld benchmark 上,CUA 的坐标预测准确率比通用模型高 20-30%(基于公开 benchmark 数据估算)。这不是 prompt 工程能弥补的差距——是训练数据的差距。
第二, 沙箱浏览器是云端托管的。用户不需要暴露自己的桌面。Agent 操作的是 OpenAI 基础设施里的一个独立 Chromium 实例。好处是隐私隔离——Agent 看不到你的其他窗口。坏处是 无法操作本地应用,而且云端 Chromium 的指纹管理是 OpenAI 的责任,不是你的。
第三, Human-in-the-loop 设计。遇到登录、支付、CAPTCHA 时,Operator 把控制权交回用户浏览器,用户完成后 Agent 继续。这比 Anthropic 的「全自主」更务实——承认了 Agent 在 L4 信誉检测面前没有好办法。
开源方案:控件树 + 视觉混合
微软的 UFO(UI-Focused Agent)走了一条完全不同的路:不截图,直接读 Windows UI Automation Tree。
每个按钮、文本框、菜单都有结构化的 name、class、bounding box。Agent 不需要猜坐标,直接说「点击 Button[name=「Submit」]」。
优势很明显:不需要视觉模型,成本低 10 倍,定位精确。劣势也很明显:只支持 Windows,自定义渲染的 UI(Electron 应用、Canvas、游戏)控件树是空的。浏览器里的网页内容在控件树里是一个巨大的 Document 节点,没有子元素——等于白给。
三条路线的核心差异:
| 维度 | Anthropic CU | OpenAI Operator | 开源(UFO 等) |
|---|---|---|---|
| 感知 | 纯截图 | 截图 + 可能的 DOM 辅助 | 控件树 + 截图 |
| 决策 | 通用 Claude | 微调 CUA 模型 | 通用 LLM + ReAct |
| 执行 | xdotool / cliclick | 沙箱 Playwright | UI Automation API |
| 坐标准确率 | ~80% | ~90%+ | 精确(控件级) |
| 应用范围 | 整个桌面 | 仅沙箱浏览器 | 仅 Windows 原生控件 |
| 反检测 | 真实桌面,天然干净 | 云端 Chromium,需管理 | N/A(本地操作) |
| 用户数据隔离 | ❌ 看到整个桌面 | ✅ 沙箱隔离 | ❌ 本地操作 |
macOS 的坑:权限不是问题,坐标系才是
很多人担心 macOS 的 TCC 权限模型(Screen Recording、Accessibility、Input Monitoring)会挡住 Computer Use。
实际上,权限是 一次性成本。VNC Server 或 cliclick 首次运行时弹窗授权,重启后保持。被操控的应用完全不知道输入来自 VNC 还是物理键盘——事件在 WindowServer 层面注入,对应用透明。
真正的坑在别处。
Retina 坐标系混乱。 macOS 的逻辑分辨率是 1440×900,物理分辨率是 2880×1800。screencapture 输出物理分辨率的图片,但 cliclick 和 CGEvent 用逻辑分辨率。视觉模型在 2880×1800 的图上预测出坐标 (1200, 800),你得除以 2 再传给 cliclick。Anthropic 的参考实现里就有这个 bug——在 Retina Mac 上点击位置偏移一半。
输入法拦截。 macOS 中文输入法(搜狗、微信输入法)会拦截键盘事件。Agent 的 type_text 可能被输入法吃掉,变成拼音。解决方案:操作前用 AppleScript 切换到 ABC 键盘布局。我在 用 Vision + macOS 自动化消灭 Browser MCP 的最后一个手动断点 里也踩过类似的坑——macOS 的 GUI 自动化,坑不在技术上,在平台细节上。
Mission Control 和多桌面。 screencapture 只捕获当前 Space。如果目标窗口在另一个桌面,Agent 看到的是空的。需要先切换桌面,但切换桌面的操作本身又需要 Agent 能识别当前状态。
这些都不是「权限」问题,是 平台工程 问题。每一个都能让一个 Demo 级别的 Computer Use 在生产环境里翻车。
真正的战场:行为模拟
回到开头那个朋友的故事。他的 Agent 被 Cloudflare 拦住,不是因为浏览器环境有问题,而是因为 操作行为不像人。
Cloudflare Turnstile、DataDome、Akamai Bot Manager 在页面里注入 JS,收集的不是你的浏览器指纹,而是你的 操作生物特征:
- 鼠标轨迹:人类移动有微修正、加速度变化、贝塞尔曲线特征。Agent 瞬移或直线移动,立刻暴露
- 点击偏移:人类不会每次正中元素中心,有 2-5px 的高斯偏移
- 打字节奏:人类 keydown/keyup 间隔 80-200ms,有快有慢,偶尔打错再退格。Agent 如果均匀间隔或瞬间填入
- 滚动行为:人类有惯性滚动、回滚。Agent 精确滚动到目标位置
- 时间分布:人类在页面间有犹豫、阅读、走神。Agent 每步间隔恒定
DataDome 从 2024 年开始用 ML 模型分类鼠标轨迹。简单的噪声注入已经不够了——你需要 统计分布上 像人,不只是单点像人。
为什么不能靠「加随机数」解决?因为 ML 分类器看的不是单个数据点,而是 分布特征。真实人类的鼠标速度曲线是右偏的(大部分时间慢,偶尔快),加速度有 1/f 噪声特征,微修正频率跟目标距离相关。你加均匀随机噪声,分布形状就不对——分类器一眼就能分出来。
所以行为模拟的核心不是「加噪声」,而是 生成统计特征正确的轨迹。一个最低限度的实现:
import random
import math
import time
def human_mouse_move(start: tuple[int, int], end: tuple[int, int]) -> list[tuple[int, int]]:
"""生成贝塞尔曲线鼠标路径,模拟人类移动。"""
cx = (start[0] + end[0]) / 2 + random.gauss(0, 50)
cy = (start[1] + end[1]) / 2 + random.gauss(0, 30)
points = []
steps = random.randint(20, 40)
for i in range(steps + 1):
t = i / steps
# 二次贝塞尔曲线
x = (1-t)**2 * start[0] + 2*(1-t)*t * cx + t**2 * end[0]
y = (1-t)**2 * start[1] + 2*(1-t)*t * cy + t**2 * end[1]
points.append((int(x), int(y)))
return points
def human_click(x: int, y: int) -> tuple[int, int]:
"""在目标位置加高斯偏移,模拟人类点击不精确性。"""
return (x + int(random.gauss(0, 3)), y + int(random.gauss(0, 3)))
def human_type_delay() -> float:
"""模拟人类打字间隔:80-200ms,偶尔更长。"""
if random.random() < 0.05:
return random.uniform(0.3, 0.8) # 偶尔犹豫
return random.uniform(0.08, 0.2)
# generated by hugo AI
但这只是入门。真正的对抗是:你的贝塞尔曲线控制点分布、速度曲线、微修正频率,都会被 ML 模型拿来跟真实人类数据做分类。这是一场 军备竞赛,不是一个工程问题。你加噪声,对方加特征维度。你模拟犹豫,对方分析犹豫的分布是否自然。
成本:被忽略的结构性瓶颈
技术讨论容易忽略最朴素的问题:多少钱?
以「登录网站 → 填三张表 → 提交」这个任务为例:
| 路线 | 步骤数 | 时间 | 成本 | 成功率 |
|---|---|---|---|---|
| VNC + Claude | ~25 步 | 3-5 min | $0.50-1.00 | ~70% |
| Anthropic CU | ~20 步 | 2-4 min | $0.30-0.60 | ~75% |
| OpenAI Operator | ~15 步 | 1-3 min | $0.20-0.50 | ~85% |
| Playwright 脚本 | 1 次 | 5 sec | $0.001 | ~95% |
| API 调用 | 1 次 | 0.5 sec | $0.0001 | ~99% |
(成功率含义不同:Playwright 的 95% 是「脚本写对了的情况下」,写脚本本身可能需要 2 小时。Computer Use 的 70-85% 是零脚本、纯自然语言指令的成功率。成本基于公开 API 定价估算。)
VNC 路线的成本是 Playwright 的 100-500 倍,是 API 的 1000-5000 倍。
这不是模型降价能解决的。成本来自 结构性循环:每一步都要截图 → 发给视觉模型 → 等推理 → 执行 → 再截图。20 步任务就是 20 次视觉推理。即使模型推理免费,截图传输和等待时间也是硬约束。
再加上错误恢复的成本:误点、页面加载异常、CAPTCHA 弹出,每次重试都是额外的 3-8 秒和一次视觉推理。一个 70% 成功率的任务,平均需要 1.4 次尝试。
分层架构:不要一上来就用最重的方案
在 Agent 时代的权限:从 RBAC 到五层信任架构 里,我写过 Agent 进入企业需要五层信任。Computer Use 的技术选型也是同样的逻辑——不是选最强的,是选 最够用的。
Layer 0: API 优先
↓ 没有 API
Layer 1: 确定性脚本(Playwright / AppleScript)
↓ 页面结构不固定,需要判断
Layer 2: Computer Use Agent(视觉 + 坐标)
↓ 需要真实浏览器环境 + 反检测
Layer 3: VNC + 真实浏览器 + 行为模拟
# generated by hugo AI
大多数场景 Layer 1 就够了。Computer Use 的价值在于处理 非结构化、不可预见的 GUI 交互——弹窗、动态表单、验证码后的恢复流程、没有 API 的政府网站。
VNC 是 Layer 3,是 兜底方案,不是主力。它的适用场景很窄:高价值、低频、无 API、需要真实浏览器环境。比如政府表单提交、银行操作、特定预约系统。
如果你的 Agent 每天要跑 1000 次,用 VNC 路线意味着每天 $500-1000 的成本和 50-80 小时的执行时间。同样的任务,Playwright 脚本 $1、8 分钟跑完。
如果真要做 Computer Use
五条工程建议,都是踩坑之后的:
一、用 Accessibility Tree 辅助截图。 不是替代截图,是把控件信息作为文本 context 一起发给模型。纯视觉定位的准确率天花板在 80-90%,加上控件树能到 95%。
二、每步操作后做截图 diff。 不要盲操作。点完按钮后截图,跟上一帧对比,确认操作生效。页面没变化 → 可能点偏了,重试。
三、维护操作历史 scratchpad。 长任务中模型会迷失。把「已完成步骤 + 当前状态 + 下一步计划」作为文本 context 每步传入,防止模型在 20 步之后忘记自己在干什么。
四、行为模拟不是可选的。 鼠标移动用贝塞尔曲线,点击加高斯偏移,打字加随机延迟,步骤间加 1-8 秒随机等待。这不是锦上添花,是 L3 检测的及格线。
五、中文环境锁定 ABC 键盘布局。 macOS 上不做这一步,你的 Agent 输入中文时会变成拼音。一行 AppleScript 的事,但不做就是 100% 故障率。
最后
回到那个朋友的故事。他最终没有继续死磕 VNC 路线。
我帮他重新评估了需求:那个政府网站其实有一个半公开的 API(藏在 JS 里,但能用)。Layer 0 直接搞定,成本从每次 $0.80 降到 $0.001,时间从 4 分钟降到 2 秒。
他之前花了两周研究 VNC 反检测、行为模拟、macOS 权限,最后发现 问题本身就不该用 Computer Use 来解。
这是我觉得最值得说的一句话:Computer Use 是一个令人兴奋的技术方向,它让 Agent 第一次有了「手」,能操作任何 GUI。但兴奋感容易让人跳过第一步判断——这件事真的需要一双手吗?
大多数时候,一个 API 调用就够了。而判断「够不够」这件事本身,才是 Agent 工程师最值钱的能力——不是会写行为模拟,是知道什么时候 不需要 行为模拟。
你在实际落地 Agent 时,遇到过「杀鸡用牛刀」的技术选型吗?欢迎留言讨论。