Claude Computer Use 在同一按钮上反复点击死循环 —— 排查与修复

Claude Computer Use 不停地点击同一个按钮或输入框迟迟无法推进,几乎都是截图时机、坐标缩放或隐藏状态的问题。本文先给最快的修复,再给完整诊断。

你让 Claude Computer Use 填一份表单、点提交、读确认信息。Claude 点了提交按钮,页面看起来没变化。它又截图一次,发现表单还在,于是再点一次,然后再一次。二十轮过去,整个聊天记录就是一面”我将点击提交按钮”的墙。模型并没有坏 —— 它只是在根据看到的画面做反应,而它看到的 UI 状态前后压根没变。

最快的修复(对大多数死循环有效): 在 prompt 里加一条明确的”等待 - 截图 - 验证”规则,让 Claude 不再盲目重试。Anthropic 官方推荐的措辞见 第 1 步。如果你能控制 API 循环,再用一个 max_iterations 预算给迭代次数封顶(第 5 步),这样卡死的运行就不会一口气跑掉几百轮。这两个改动能解决绝大多数 action loop。

死循环几乎都能追溯到这六种情况之一:点击落在了覆盖元素上、按钮被异步校验拦着、截图在 DOM 稳定之前就抓了、resize 或 Retina 屏幕导致坐标漂移、确认信息渲染到了画面外,或者操作其实成功了但成功提示太短 Claude 没捕捉到。

你用的是哪个工具版本?

修复细节取决于你的工具版本,而这套阵容在 2025 年底变过。截至 2026 年 6 月:

工具版本 typeanthropic-beta支持模型新增能力
computer_20251124computer-use-2025-11-24Claude Opus 4.7、Opus 4.6、Sonnet 4.6、Opus 4.5zoom 动作(enable_zoom: true)
computer_20250124computer-use-2025-01-24Claude Sonnet 4.5、Haiku 4.5,以及更老的(Opus 4.1、Sonnet 4 已废弃)scrollwaittriple_clickhold_key

如果你在 computer_20251124 上,你就有 zoom 动作,它能直接缓解下面两类死循环成因(成功提示太细、标签太小)。Computer Use 在 Claude API 上仍是 beta 功能,必须带 beta 头 —— 漏了它返回的是工具定义错误,不是死循环。

有一个缩放变化对死循环很关键:截至 2026 年 6 月,Anthropic 文档指出 Claude Opus 4.7 支持长边最高 2576px 的截图,且坐标与图像像素是 1:1(无需缩放换算)。下面那套 1568px 上限和手动坐标缩放的算法,只对更早的模型(Sonnet 4.6、Opus 4.6、Opus 4.5)仍然适用。换句话说,“每一击都偏”这类死循环最大的源头 —— 静默降采样 —— 只要你用 Opus 4.7 且截图不超过 2576px,基本就消失了。

常见原因

按典型 Computer Use 死循环出现的概率排序。

1. 点击落在了覆盖元素上(modal 遮罩、tooltip、overlay)

Computer Use 是按像素坐标点击的。如果点击瞬间,目标按钮上方刚好盖着一个 tooltip、modal 背景或者 pointer-events: auto 的 overlay,那这一击就打在了覆盖层上,按钮根本没触发。下一张截图看起来一模一样,Claude 又点一次。

如何识别: 手动打开页面,在按钮位置悬停,用 DevTools 的 “Inspect” 拾取器看那个坐标的最顶层元素。如果不是按钮本身,就是这种情况。

2. 按钮”看着可点”,其实在等异步校验

很多表单的提交按钮在视觉上是 enabled 的,但点击处理函数被一个 debounce 的校验逻辑拦住,要等校验跑完才生效。Claude 点得太早,点击被静默吞掉,页面纹丝不动。

如何识别: 你自己在输入完后立刻手动点按钮 —— 如果要等 500-1500ms 才有反应然后才生效,就是这个原因。

3. 截图在 DOM 稳定之前就抓了

截图本身只是又一次工具调用,所以时机完全取决于你的 agent 循环。如果页面在做整页客户端路由切换、中间有个 2 秒的 spinner,而你的循环立刻就截图,Claude 抓到的就是 spinner 那一帧,然后判断”还在加载,再点一次” —— 可此时加载途中再点已经是误操作了。

如何识别: 看截图里有 spinner / skeleton 占在内容本该出现的位置,而 Claude 还在反复点那个其实已经失效的 CTA。

4. resize 后坐标漂移,或 Retina 屏幕缩放错误

有两种不同的味道:

  • resize 漂移: 如果浏览器缩放级别、窗口大小或布局在两轮之间变了(自动 resize、侧边栏收起、移动端模拟弹出虚拟键盘),Claude 之前算好的坐标就不再指向同一个 DOM 元素了。
  • Retina / DPI 缩放: 在 macOS Retina 屏幕上,截图是按 device pixel ratio 为 2 抓取的,所以图像分辨率是逻辑坐标空间的两倍。按 Anthropic 文档,你必须要么在发送前把截图降采样 2 倍,要么把 Claude 返回的坐标除以 2 再点击。不做这一步,每一击都会落在大约两倍偏移的位置 —— 这是教科书级的”画面永远不变”死循环。同理,只要你发出的截图超过 API 图像上限(多数模型长边 1568px)被静默降采样,也是一样的问题。

如何识别: 对比两张连续截图 —— 如果按钮挪了位置但 Claude 还在点老坐标,就是 resize 漂移。如果点击是 一致地朝某个方向偏(比如总是偏右下),那是缩放不匹配,不是漂移。

5. 确认弹窗渲染在画面外,或在 Claude 看不到的 portal 里

有些 UI 把 modal portal 到 document.body 的某个位置,而那位置在 Claude 当前视野之外(比如挂在文档顶部,但当前滚动在页面中间)。Claude 看到的还是没变化的表单,而 modal 正在画面外等着。

如何识别: 手动把页面滚到最顶部。如果那里真有一个 modal 挡着,那 Claude 需要先被告知滚动到顶部。

6. 操作其实成功了,但成功提示太微弱

一个 200ms 淡入、停 1.5 秒再淡出的 toast。一个持续 800ms 的绿色边框。或是降采样后 Claude 根本看不清的细小状态文字。等下一张截图触发时,成功信号已经没了,所以 Claude 判定操作失败。

如何识别: 手动操作一遍,看成功提示能停留多久。如果不到 2 秒,或文字比正文还小,Claude 大概率会错过。

排查前的准备

  • 把死循环里整个截图序列保存下来。每轮的截图是判断 Claude 看到了什么的唯一证据。
  • 记录触发这次运行的确切 prompt。像”一直尝试直到成功”这种措辞会让死循环更严重。
  • 留意死循环是确定性的(每次同一个网站都循环)还是偶发的(有时能跑通)。偶发指向时序问题,确定性指向结构或缩放问题。

需要收集的信息

  • 死循环的逐轮截图(至少 3 个连续迭代)。
  • 目标网站 URL 和让 Claude 执行的具体操作。
  • 工具版本(computer_20251124 还是 computer_20250124)、模型,以及你是直接跑 API、走参考容器,还是用桌面端壳子。
  • 你声明的确切 display_width_px / display_height_px、真实屏幕分辨率,以及 device pixel ratio。
  • 你提供的任何自定义 system prompt 或 tool-use 指令。

一步步修复

按 ROI 排序,便宜的检查在前。

第 1 步:加上官方的”等待 - 截图 - 验证”指令

单点收益最高的修复。Anthropic 在 Computer use 工具文档(“Optimize model performance with prompting”一节)里专门为这种情况发布了一段推荐 prompt —— 用他们的原文或近似变体(下面保留官方英文原句,因为 Claude 在英文 prompt 下表现更稳):

After each step, take a screenshot and carefully evaluate if you have
achieved the right outcome. Explicitly show your thinking: "I have
evaluated step X..." If not correct, try again. Only when you confirm a
step was executed correctly should you move on to the next one.

在上面再叠加一条专门防死循环的规则:

If a screenshot looks identical to the one before your last click, do
NOT click the same element again. Scroll, take a wider screenshot, or
look elsewhere on the page for an error message.

这能在大多数情况下打破第 1、2、3、6 类死循环,因为 Claude 不再假设操作已经成功,也不再盲目重试。

第 2 步:判定状态前先强制滚到顶部

如果你怀疑确认信息渲染在当前滚动位置之上(成因 5):

Before deciding whether the action succeeded, scroll the page to the
top, wait 1 second, then take a screenshot. Modals and toasts often
render at the top of the document body.

第 3 步:用文字标签重新定位,粘滞控件改用键盘

引导 prompt 优先用可见文字定位目标,这能中和 resize 漂移(成因 4):

When clicking a button, identify it by its visible text label first,
not by remembered pixel coordinates. If the same coordinates fail
twice, the button has likely moved — re-locate it by label.

Anthropic 还指出,下拉框(dropdown)和滚动条对纯鼠标控制特别难。对这类控件,引导 Claude 用键盘快捷键(Tab 聚焦、方向键、Enter)而不是点击。另外按文档,把你的指令文字放在每个用户回合的截图图像 之前 —— 在图像被处理之前先描述目标,能显著提升点击准确率。

第 4 步:校正 display 尺寸和 Retina 缩放

“每一击都偏”最常见的静默成因。让 display_width_px / display_height_px 精确等于你实际发出去的那张图的像素尺寸,并保持在 Anthropic 推荐范围内:

  • 通用桌面任务:1024x7681280x720
  • Web 应用:1280x8001366x768
  • 避免超过 1920x1080
# 工具定义(computer_20251124)
tools = [{
    "type": "computer_20251124",
    "name": "computer",
    "display_width_px": 1280,
    "display_height_px": 800,
    "display_number": 1,
    # enable_zoom 让 Claude 能看清细小标签 / 状态文字
    "enable_zoom": True,
}]

在 macOS Retina 屏幕上,Claude 按 device pixel ratio 为 2 抓图,所以图像分辨率是逻辑坐标空间的两倍。按 Anthropic 文档,你必须要么在发送前把截图降采样 2 倍,要么把 Claude 返回的坐标除以 2 再点击。只要你的源图超过单模型图像上限(Sonnet 4.6、Opus 4.6、Opus 4.5 长边 1568px;Opus 4.7 是 2576px 且坐标 1:1),也是同一套”先降采样,再把坐标放大回去”的处理。

API 其实同时强制两条约束 —— 长边 1568px 以及 总像素约 1.15 兆 —— 所以文档把缩放因子取两者的最小值,然后把 Claude 返回的坐标除以同一个 scale 再点击:

import math

def get_scale_factor(width, height):
    """预先降采样截图,让坐标与 Claude 看到的画面保持 1:1。"""
    long_edge_scale = 1568 / max(width, height)
    total_pixels_scale = math.sqrt(1_150_000 / (width * height))
    return min(1.0, long_edge_scale, total_pixels_scale)

scale = get_scale_factor(screen_w, screen_h)
# 发送前把截图缩放到 (screen_w*scale, screen_h*scale),
# 再把 Claude 返回的 (x, y) 映射回去:screen_x = x / scale

如果你用 Opus 4.7 且截图不超过 2576px,这一整套可以直接跳过 —— 坐标本来就是 1:1。设置 enable_zoom: True(仅 computer_20251124 支持)能让 Claude 以全分辨率审视某个区域,这同时解决”点击落在附近但漏掉细小目标”和”看不清成功文字”两种变体。按文档,如果该缩放时 Claude 没缩放,就让它针对某个具体元素或 region 提问,而不是问整屏。

第 5 步:用 max-iterations 预算给 agent 循环封顶

这是 Anthropic 自家参考实现里经典的 loop-breaker:让采样循环一直跑,直到 Claude 不再请求工具 或者 触到硬性迭代上限:

def sampling_loop(model, messages, max_iterations=10):
    for _ in range(max_iterations):
        response = client.beta.messages.create(
            model=model,
            max_tokens=4096,
            messages=messages,
            tools=TOOLS,
            betas=["computer-use-2025-11-24"],
        )
        messages.append({"role": "assistant", "content": response.content})
        tool_results = process_tool_calls(response)
        if not tool_results:        # 不再请求工具 -> 任务完成
            return messages
        messages.append({"role": "user", "content": tool_results})
    return messages  # 触到上限 -> 抛给用户处理

再加一道”相同截图检测”,让你在烧光整个预算 之前 就中止冻结的页面:

import hashlib

last_hash, identical_count = None, 0

def on_screenshot(image_bytes):
    global last_hash, identical_count
    h = hashlib.sha256(image_bytes).hexdigest()
    if h == last_hash:
        identical_count += 1
        if identical_count >= 3:
            raise StopIteration("3 张截图连续完全一致 —— 中止循环")
    else:
        identical_count = 0
    last_hash = h

连续 3 张字节完全一致的截图,基本可以判定运行卡死。直接 abort 抛给用户,别再为更多轮次付费。

第 6 步:对”惯犯网站”,尴尬的那一步用脚本预编排

有些网站(银行、老旧企业系统、重度 SPA 仪表盘)对 Computer Use 出了名地不友好。对这类站,把”点击 + 等待”那一步退回给确定性的 Playwright 或 Selenium 脚本,只把需要推理的部分交给 Claude。

怎么确认修好了

  • 用新 prompt 和工具配置重跑原任务,确认 Claude 不再连续三次点同一个元素。
  • 检查截图序列:连续两次操作之间,截图应当肉眼可见地不同(弹窗打开了、页面变了、toast 出现了)。
  • 任务的总轮数应当比原来那次循环明显下降,而且现在应以”任务完成”结束,而不是触到 max_iterations
  • 如果你怀疑过缩放 bug,点一个已知目标(比如某个角上的按钮),确认光标恰好落在它身上,而不是偏移。

诊断点击偏移问题(Anthropic 的对照表)

如果是点击偏移而不是死循环,Anthropic 文档把症状映射到修复:

症状可能原因试试
一致地朝某个方向偏display_*_px 与实际发出的图不匹配,或被静默降采样让 display 尺寸等于缩放后的截图;在 API 上限内预先降采样
落在正确区域但漏掉小目标降采样 4K+ 源图丢了细节,或宽高比被扭曲enable_zoom: true;降低 DPI 抓图或裁剪;保持宽高比
点中完全错误的元素指令含糊,或附近有相似元素用方位化 prompt(“右下角那个蓝色 Submit 按钮”);拆小步骤
准确率一直很差截图超过 API 上限,或分辨率太低在上限内预先降采样;以 1280x720 作为基线

长期预防

  • 把每一次 Computer Use prompt 都当作一个状态机:“点 X,验证 Y 出现,再做下一步。“把验证步骤显式写出来。
  • 在 system prompt 模板里固化一条”状态没变化就不允许重复点击同一元素”的规则。
  • 整个会话锁定 display_width_px / display_height_px 和 device pixel ratio,绝不留给宿主环境自动调整。
  • 对高价值网站,在 prompt 里附上一组成功运行的示例截图和工具调用 —— 文档建议对可重复任务这么做。
  • 把截图都落到文件系统,这样任何失败的运行都能端到端复盘,不必再烧 API 重跑。

常见坑

  • 让 Claude “更努力一点”或”持续尝试” —— 这恰恰是死循环的助燃剂。
  • 完全信任按钮的视觉 enabled 状态,不去检查它背后是否还有异步校验在拦截。
  • 不设 max_iterations 预算就跑 —— 一个死循环可以烧掉几百轮和真金白银。
  • 忽略 Retina / 降采样的换算,导致每一击都偏,画面永远不变。
  • 把被验证码挡住或被限流的页面当作”只是慢一点”。Claude 会一直点下去。
  • 在 UI 任务上把 thinking effort 拉满。Anthropic 2026 年 6 月的指引:Sonnet 4.6 和 Opus 4.6 用 medium、别用 max(在这里只增加 token 成本不提升准确率);这两个模型上 low 反而比关掉 thinking 花更少的输出 token,因为出错少了重试也就少了。Opus 4.7 是例外 —— 它默认 high,low 留给高吞吐或对成本敏感的运行。

FAQ

Q:Claude 点对了按钮,但页面突然变白了,怎么办?

很可能是 CSP 或网络拦截:点击触发了一个被沙箱挡掉的外发请求。手动重做一遍流程,看 Network 面板。如果看到 CORS 或 CSP 报错,你的沙箱需要给目标域名加白。另见 Claude 文件连接器陷入重新授权死循环

Q:为什么死循环只发生在某个网站,别的没事?

客户端路由重度、portal 渲染 modal、异步校验多的站最容易循环。纯静态 HTML 表单几乎不会。修复手段是针对单站调 prompt 加上正确的缩放,而不是一刀切全局参数。

Q:能不能把 max-iterations 调大,赌它最后能成功?

不行。一旦两轮之间输入不变,Claude 的推理也不会变,所以无论给多大预算它都会一直循环。你必须打破输入模式(滚动、等待、重新定位、修缩放),否则就 abort。

Q:换模型有帮助吗?

有时有。按 Anthropic 文档,Sonnet 4.6 在机械点击上比 Opus 4.6 更精确,在截图被大幅降采样时也更稳;Opus 4.7 把这个差距拉回到大致相当,而且因为它接受长边最高 2576px 且坐标 1:1,需要的降采样更少。如果你的死循环是降采样 / 偏移问题,换到 Opus 4.7 能把缩放算法整个去掉。但换模型修不了错帧截图,也修不了 Retina DPR-2 的 bug —— 先把那些修好。

Q:我在老的工具版本上,没法 zoom,等效方案是什么?

enable_zoom 需要 computer_20251124。在 computer_20250124 上,发送前降低抓图分辨率或把截图裁剪到关注区域,并引导 Claude 去读某个具体元素而不是整屏。

相关阅读

标签: #排查 #Claude #computer-use #automation #agent