本文由有道龙虾翻译并发布,原文来自 Anthropic 官方博客:Best practices for computer and browser use with Claude。文章系统总结了 Claude 计算机使用和浏览器使用在截图分辨率、坐标缩放、点击准确性、思考预算、安全防护、上下文管理、批量工具、Advisor 工具和演示学习等方面的工程最佳实践。

Claude 的最新模型在计算机使用和浏览器使用能力上迈出了重要一步。凭借这些特性,LLM 现在能够驱动越来越复杂的智能体系统,用于支撑真实工作,例如构建软件应用,以及跨多个互不相同的技术自动化工作流。

在这篇博客文章中,我们分享了 Claude 计算机使用与浏览器使用的最佳实践,内容从简单的配置变更到更高级的集成模式不等。我们希望这篇文章能在你开始将 Claude 的计算机使用与浏览器使用能力集成到产品中时有所帮助。我们还发布了一个新的演示实现,其中封装了部分最佳实践,并提供了在 Claude 计算机使用能力之上进行开发时有用的附加工具。

请注意,除非另有说明,这些建议适用于 Claude 4.6 系列(Opus 4.6、Sonnet 4.6、Haiku 4.5)以及 Claude Opus 4.7。当 4.6 系列与 Opus 4.7 的指导建议存在差异时,我们会在正文中明确指出。我们的发现基于内部实验,未来可能会随着新模型和新技术的出现而更新。

入门:分辨率与缩放

点击准确性是任何计算机使用集成的基础。如果点击没有落在应有的位置,后续一切都无法正常工作:表单填不上,按钮按不下,工作流也会失败。影响最大的单项优化同时也是最简单的优化之一:在将截图发送给 API 之前,先对截图进行下采样/缩小。

确保正确缩放

当你向 Claude 的 Computer Use API 发送截图时,模型会看到它,并在你指定的 display_width_px / display_height_px 坐标空间中返回点击坐标。但这里有一个重要约束:API 对图像大小有内部处理限制。超过这些限制的图像会在模型看到之前被下采样/缩小,这意味着模型是在图像的降质版本上进行点击判断,而你的执行框架期望的坐标却与原始分辨率对齐。

对于我们的 Claude 4.6 模型系列,API 的限制如下:

  • 最大长边:1568 像素
  • 最大总像素数:1.15 百万像素
  • 超过任一限制的图像都会被内部下采样/缩小

我们的 Opus 4.7 模型支持更高分辨率。限制如下:

  • 最大长边:2576 像素
  • 最大总像素数:3.75 百万像素
  • 超过任一限制的图像都会被内部下采样/缩小

当坐标空间与模型感知到的图像不匹配时,模型预测的点击会落在一个与它实际看到的图像不同的显示尺度上。这是高分辨率下点击不准确的主要原因。修复方法很直接:在将截图发送给 API 之前,始终将其下采样/缩小到这些限制范围内。我们持续观察到,当图像超过限制时,准确性会显著下降,而这一个改动的价值超过几乎任何其他优化。

推荐分辨率

从 1280x720 开始。 对大多数用例而言,这是一个安全、实用的默认值。它使用约 80% 的像素预算,同时远低于长边和总像素限制,而且是模型在训练期间见过的标准分辨率。它对现代 Web UI 和传统桌面应用都表现良好。

如果你使用的是 Opus 4.7,我们建议从 1080p 开始,因为相比 720p,这会带来有意义的质量提升,并且在 token 使用量与性能之间取得良好平衡。

对于希望最大化模型接收视觉信息的开发者,我们还推荐一种“最大 API 适配”(max API fit)方法:基于来源图像的原生宽高比,逐张图像计算最优分辨率:

import math

# 4.6 系列为 1568,Opus 4.7 为 2576
MAX_LONG_EDGE = 1568

# 4.6 系列为 1.15MP,Opus 4.7 为 3.75MP
MAX_PIXELS = 1_150_000

def compute_max_api_fit(native_w, native_h):
    """计算符合 API 限制的最大分辨率,
    同时保持宽高比。"""
    aspect = native_w / native_h

    # 根据像素预算计算最大尺寸
    h_from_pixels = math.sqrt(MAX_PIXELS / aspect)
    w_from_pixels = h_from_pixels * aspect

    # 应用长边约束
    if native_w >= native_h:
        w = min(w_from_pixels, MAX_LONG_EDGE)
        h = w / aspect
    else:
        h = min(h_from_pixels, MAX_LONG_EDGE)
        w = h * aspect

    # 绝不放大到超过原生尺寸
    w = min(w, native_w)
    h = min(h, native_h)

    return int(w), int(h)

这种方法稍微复杂一些,但可以避免宽高比失真,并充分利用每张图像可用的像素预算。相对于固定的 1280x720,它带来的准确性提升较为温和,但实现起来很直接,并且可以避免将非 16:9 来源强行转换为 4:3 显示分辨率时出现的失真。

应避免的分辨率:

  • 原生分辨率(未缩放):除非你的源图像恰好低于分辨率限制,否则发送原生分辨率截图是点击准确性差最常见的原因。
  • 非常低的分辨率(低于 960x540):低分辨率图像会丢失过多细节,导致模型无法准确识别小型 UI 元素。
  • 如果在 MacOS 上: 浏览器使用中的一个常见问题是,MacOS 上的截图通常以 2 的设备像素比捕获,这意味着你最终得到的图像分辨率可能是屏幕坐标的 2 倍。
  • 如果你使用的是 4.6 系列,请避免 1920x1080 及以上分辨率: 这些分辨率会超过像素限制,并被静默下采样/缩小。在 Opus 4.7 上,上限更高(3.75 MP),因此 1080p 和 1440p 在预算范围内;但仍应避免在不下采样/缩小的情况下使用原生 4K。

坐标缩放

当你在发送截图前调整其大小时,模型会在你指定的显示分辨率中返回点击坐标。你必须在执行点击之前,将这些坐标缩放回实际屏幕分辨率:


# 你的屏幕是 screen_w x screen_h

# 你发送了一张调整为 display_w x display_h 的截图
scale_x = screen_w / display_w
scale_y = screen_h / display_h

screen_x = int(api_returned_x * scale_x)
screen_y = int(api_returned_y * scale_y)

这很直接,但至关重要,因为如果你忘记缩放,或者 display_width_px / display_height_px 与你发送的图像实际尺寸不匹配,每一次点击都会出现一致的偏移

messages 数组中的内容顺序

构造 messages content 数组时,请将文本指令放在图像之前,如下方代码片段所示。这样模型在处理截图时会知道自己要寻找什么,从而提高点击准确性。


# 推荐:先放文本指令,再放截图:
content = [
    {"type": "text", "text": "Click on the Submit button"},
    {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": screenshot_b64}},
]

# 不推荐:先放图像,再放文本:
content = [
    {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": screenshot_b64}},
    {"type": "text", "text": "Click on the Submit button"},
]

诊断点击问题

如果点击没有命中目标,通常可以归结为下面某个原因:

症状可能原因可以尝试
点击始终朝某个方向偏移- display_width_px / display_height_px 与发送的实际图像尺寸不匹配 - 截图超过 API 限制并被静默下采样/缩小 - 内容顺序是图像在前,而不是文本在前- 确保显示尺寸与你调整大小后的截图完全匹配,而不是与你的原生分辨率匹配 - 预先下采样/缩小到 1280x720,或使用 compute_max_api_fit - 将文本指令移到 content 数组中图像之前
点击落在大致正确区域,但没有命中目标- 目标非常小(复选框、图标、开关) - 源图像分辨率非常高(4K+),下采样/缩小时丢失了细节 - 强行使用非原生宽高比导致宽高比失真- 对密集 UI 启用 enable_zoom: True - 以较低 DPI 捕获,或在下采样/缩小前裁剪到相关屏幕区域 - 调整大小时保留来源宽高比
模型完全点击了错误元素- 指令含糊(例如页面上有多个类似提交的按钮时只说“click Submit”) - 目标附近有视觉上相似的元素 - UI 对单条指令来说过于复杂- 使用更具体的提示,并加入位置上下文(例如“click the blue Submit button in the bottom-right of the form”) - 将复杂交互拆分为更小步骤 - 提供有关页面布局的附加上下文
整体准确性都很差- 截图发送时超过 API 限制 - 源图像来自非常高分辨率的显示器(4K+),压缩比例极高 - 分辨率过低,丢失了关键细节- 预先将所有截图下采样/缩小到限制范围内 - 对于 4K+ 来源,在 4.6 系列上,Sonnet 比 Opus 4.6 更能承受重度下采样/缩小。在 Opus 4.7 上,这一差距基本缩小;请使用 4.7 的像素预算(最高 3.75 MP),从一开始就减少所需的下采样/缩小。 - 以 1280x720 作为基线;如果损失过大,请使用 compute_max_api_fit

点击任务的模型选择

根据我们的内部测试,Claude Sonnet 4.6 在点击方面往往更加机械精确(空间准确性更好,近距离未命中的情况更少),而 Claude Opus 4.6 则具备更强的推理能力。当源图像需要重度下采样/缩小时,Sonnet 4.6 也更加稳健。

Opus 4.7 缩小了这一差距:通过测试,我们发现它的点击精度大致与 Sonnet 4.6 相当,并且更高的分辨率预算从一开始就减少了所需的下采样/缩小量,因此当你希望同时获得 Opus 级别推理能力和强点击准确性时,它是一个有力选择。

对于大多数任务,我们建议从 Sonnet 4.6 开始,它在点击准确性、推理能力和成本之间提供了最佳平衡。当你需要更强推理能力时,尤其是在使用高分辨率源图像时,请选择 Opus 4.7。当延迟是优先事项时,Haiku 4.5 仍然是极佳选择。高级工作流仍可能受益于 orchestrator + sub-agent 模式,即由推理模型处理规划和决策,而 Sonnet 或 Haiku 执行机械性的点击步骤。

处理小目标

随着目标变小,点击准确性会下降。在安全区域内的所有分辨率下,大型和中型 UI 元素(按钮、输入字段和标准菜单项)都比较可靠。挑战在于小型和微小目标,例如复选框、系统托盘图标、下拉箭头、小型切换开关,以及树视图展开/折叠按钮。

如果你的应用经常需要点击小目标,请考虑以下策略:

对密集 UI 使用缩放。 Claude 4.6 和 4.7 模型支持缩放能力,使模型能够在点击之前以更高分辨率检查特定屏幕区域。请在你的工具配置中启用它:

{
    "type": "computer_20251124",
    "name": "computer",
    "display_width_px": 1280,
    "display_height_px": 720,
    "enable_zoom": True
}

让目标更大。 如果你控制被自动化的 UI,增大点击目标的尺寸(即便只是适度增大)也会对可靠性产生不成比例的影响。这可能意味着使用较低的系统 DPI、在浏览器中放大,或调整 UI 缩放设置。

对微小目标使用键盘替代方案。 对于非常小的元素,例如系统托盘图标或微小复选框),键盘快捷键或基于 Tab 的导航可能比点击更可靠。如果你的工作流允许,提示模型在特定步骤中使用键盘交互可以提高成功率。

考虑源图像分辨率。 来自 4K+ 显示器的截图在压缩到 720p 后会丢失大量细节(例如,原生 3840x2160 下的 16px 复选框,在 1280x720 显示分辨率下大约会变成 5px,这会让目标更小,因此更难命中)。如果你使用的是非常高分辨率的显示器,请考虑使用 Opus 4.7,它的分辨率限制高于此前的模型。如果使用 4.6 模型,请考虑以较低 DPI 捕获、使用显示缩放来放大 UI 元素,或者将截图聚焦在屏幕的相关部分,而不是整个显示器。由于这些模型用更少像素表示更多信息,我们观察到,随着源图像尺度增大,性能会下降,这意味着需要更多压缩。

我们测试过但没有帮助的方法

我们在内部评估中尝试了几种常见的优化技术,但没有发现这些方法能带来一致提升,不过结果可能会因具体情况而异:

  • 将图像拆分为更小的图块:将截图拆分为象限或区域并分别发送,并没有提高点击准确性。
  • 叠加带坐标的网格图案:在截图上添加可视化坐标网格来帮助模型定位目标,并没有产生可靠收益。
  • 调整大小算法的选择:PIL LANCZOS、sips 以及其他常见调整大小算法产生了相同结果。请使用对你的技术栈来说方便的任何方法。

检查失败情况

如果在尝试上述修复后,模型仍然表现不可预测,请记录完整的对话记录,并将预测点击叠加到源截图上,以理解模型实际看到的内容以及它做出的决策。

有些失败根本不是点击准确性问题。例如,某些下拉菜单可能会调用浏览器视口无法捕获的系统级 UI,此时模型看起来像是任务失败了,但它只是看不到自己需要交互的菜单。在这类情况下,模型应依赖替代方法,例如 JavaScript 执行、键盘导航,或直接操作文档对象模型(DOM),而不是点击。

快速参考

如何为计算机使用缩放并准备图像

import math
from PIL import Image
import base64
import io

# 4.6 系列为 1568,Opus 4.7 为 2576
MAX_LONG_EDGE = 1568

# 4.6 系列为 1.15MP,Opus 4.7 为 3.75MP
MAX_PIXELS = 1_150_000

def prepare_screenshot(screenshot: Image.Image, native_w: int, native_h: int) -> tuple[str, int, int]:
    """调整截图大小以符合 API 限制,并返回 base64 + 显示尺寸。"""

    # 方案 A:固定 720p(简单、可靠)
    display_w, display_h = 1280, 720

    # 方案 B:最大 API 适配(最大化保真度)
    # display_w, display_h = compute_max_api_fit(native_w, native_h)

    resized = screenshot.resize((display_w, display_h), Image.LANCZOS)

    buffer = io.BytesIO()
    resized.save(buffer, format="PNG")
    b64 = base64.standard_b64encode(buffer.getvalue()).decode()

    return b64, display_w, display_h

def scale_coordinates(api_x: int, api_y: int, display_w: int, display_h: int,
                      screen_w: int, screen_h: int) -> tuple[int, int]:
    """将 API 返回的坐标缩放回原生屏幕空间。"""
    screen_x = int(api_x * (screen_w / display_w))
    screen_y = int(api_y * (screen_h / display_h))
    return screen_x, screen_y

def compute_max_api_fit(native_w: int, native_h: int) -> tuple[int, int]:
    """在保持宽高比的同时,计算符合 API 限制的最大分辨率。"""
    aspect = native_w / native_h
    h_from_pixels = math.sqrt(MAX_PIXELS / aspect)
    w_from_pixels = h_from_pixels * aspect

    if native_w >= native_h:
        w = min(w_from_pixels, MAX_LONG_EDGE)
        h = w / aspect
    else:
        h = min(h_from_pixels, MAX_LONG_EDGE)
        w = h * aspect

    w = min(w, native_w)
    h = min(h, native_h)
    return int(w), int(h)

用法:

import anthropic
from PIL import Image

client = anthropic.Anthropic()

# 捕获截图(这里使用你自己的方法)
screenshot = Image.open("screenshot.png")
native_w, native_h = screenshot.size

# 为 API 准备数据
b64, display_w, display_h = prepare_screenshot(screenshot, native_w, native_h)

# 发送给 Claude,文本在图片之前
response = client.beta.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=4096,
    betas=["computer-use-2025-11-24"],
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "Click on the Submit button"},
            {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": b64}},
        ]
    }],
    tools=[{
        "type": "computer_20251124",
        "name": "computer",
        "display_width_px": display_w,
        "display_height_px": display_h,
    }],
)

# 将坐标缩放回去以便执行
api_x, api_y = extract_click_coords(response)  # 你的解析逻辑
screen_x, screen_y = scale_coordinates(api_x, api_y, display_w, display_h, native_w, native_h)

为计算机使用调优思考力度

Claude 的最新模型支持自适应思考,这是一项让 Claude 在行动前自行决定需要对中间步骤推理多少的设置。与手动设置思考 token 预算不同,自适应思考让 Claude 能够根据每个请求的复杂度,动态判断何时以及使用多少扩展思考。对于计算机使用,这意味着 Claude 可以思考它在屏幕上看到的内容,规划多步骤交互,并在执行点击或按键前自我纠正。

使用自适应思考时,Claude 的思考深度通过 thinking 参数和 effort 级别控制:low、medium、high、xhigh(适用于 Opus 4.7)以及 max。更多思考意味着每个动作有更多推理,但也意味着更多输出 token、更高延迟和更高成本。

自然会有一个问题:根据模型不同,计算机使用的最佳思考量是多少?

Claude Opus 4.7

我们在一组端到端 UI 自动化任务上测试了每个 thinking effort 级别,这些任务涵盖桌面应用、浏览器以及多应用工作流。

Opus 4.7 优于 4.6 系列。 在 OSWorld Verified 基准测试中,我们发现 Opus 在等价 token 使用量和 effort 设置下优于所有 4.6 系列模型。Opus 4.7 在 low effort 下的得分与 Sonnet 4.6 在 max 下相近,同时每个任务使用的 token 约为后者的 1/10。对于困难任务,Opus 4.7 是显而易见的选择。

将 effort 设置为 high 可以接近最高任务成功率,同时输出 token 约为 max 的一半。与 Opus 4.6 相比,low、medium 和 high 使用的 token 数大致相同,同时提升了 OSWorld 得分。在我们的内部测试中,Max effort 使用了更多 token,并取得了最佳得分。下表概述了我们对何时使用各个 thinking effort 级别的建议。

effort 级别建议

场景Thinking effort原因
大多数用例的默认选择highOpus 4.7 最适合困难任务。使用 high 会给模型足够的推理能力来规划复杂的多步骤交互,而不会显著增加 token 使用量。
高吞吐 / 成本敏感lowtoken 使用量更低,同时质量介于 Opus 4.6 的 high 和 max effort 设置之间。
简单、定义明确的工作流 / 最快建议尝试 Sonnet 4.6如果低延迟是最高优先级,则使用它。适合 UI 一致且工作流已知的短小、可预测任务。
复杂的一次性任务max当任务极具挑战性,并且你需要第一次尝试就做对时使用。

Claude 4.6 模型

我们在一组端到端 UI 自动化任务上测试了每个 thinking effort 级别,这些任务涵盖桌面应用、浏览器以及多应用工作流。

有两个模式非常突出:

Medium effort 是最佳平衡点。 将 effort 设置为 medium 可以接近最高任务成功率,同时输出 token 约为 high 的一半。超过 medium 后,性能会在一定程度上进入平台期。值得注意的是,当任务重试时,medium 和 high 会收敛到相同的成功率。这意味着 high effort 可能有助于模型在第一次尝试时完成困难任务,但如果允许多次尝试,medium 可能以更低成本同样可靠地达到目标。

少量思考就很有用。 low effort 是一个出乎意料地强的选项。它实际使用的总输出 token 比完全禁用思考还要(模型犯错更少,需要的重试循环也更少),同时准确性与无思考相当或略高。这使它成为成本敏感、高吞吐工作负载的最佳选项。下表概述了我们的 effort 建议。

effort 级别建议

场景Thinking effort原因
大多数用例的默认选择medium最佳准确性与成本比。给模型足够的推理能力来规划多步骤交互,而不会过度思考。配合重试时,可以用一半的 token 成本达到 high 的性能。
高吞吐 / 成本敏感low比无思考更准确,但由于错误和重试更少,token 使用量更低。
简单、定义明确的工作流 / 最快禁用思考如果低延迟是最高优先级,则使用它。适合 UI 一致且工作流已知的短小、可预测任务。
复杂的一次性任务high当任务具有挑战性,并且你需要第一次尝试就做对时使用。如果你的系统支持重试,medium 可能达到相同的最终成功率。

我们不建议在计算机使用中使用 max effort。在我们的测试中,与 high 相比,它没有带来准确性收益,却进一步增加了输出 token 成本。UI 任务主要是感知型任务,而不是深度逻辑型任务,额外的推理预算要么未被使用,要么导致过度思考。请记住,随着模型演进,这条建议也会变化。

medium setting effort level 示例配置

import anthropic

client = anthropic.Anthropic()

response = client.beta.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=16000,
    betas=["computer-use-2025-11-24"],
    thinking={"type": "adaptive"},
    output_config={"effort": "medium"},
    messages=[...],
    tools=[
        {
            "type": "computer_20251124",
            "name": "computer",
            "display_width_px": 1280,
            "display_height_px": 720,
        }
    ],
)

为什么更多思考并不总是有帮助

UI 自动化任务与编码或数学问题有本质区别。大多数计算机使用动作都是感知和机械性的:识别正确元素、点击正确位置,而不是深度逻辑推理。思考在模型需要做以下事情时最有帮助:

  • 在开始前规划多步骤序列(例如,“我需要打开 Settings,导航到 Privacy,然后禁用 tracking”)
  • 从意外的 UI 状态中恢复(例如,出现了一个未预料到的对话框)
  • 在屏幕上显示的信息和任务指令之间交叉引用
  • 在专业软件中完成具有挑战性的项目

提升安全性:利用提示注入分类器

本节介绍提示注入防护。如果你使用我们的官方计算机使用工具 header,该防护默认免费提供。不过,如果你希望在自定义计算机或浏览器使用工具上启用此能力,请填写我们的 提示注入分类器意向表。

计算机使用智能体在设计上就会与不受信任的内容交互。Claude 处理的每一张截图、每一个网页或应用 UI 都可能包含对抗性指令,包括隐藏文本、被操纵的图片、欺骗性 UI 元素,或试图劫持智能体行为的社会工程攻击。这个攻击面与典型 API 集成有根本区别,在典型 API 集成中,你可以控制输入。而在计算机使用中,模型的输入是开放互联网以及智能体正在导航的任何软件。

随着计算机使用智能体能力增强并被更广泛部署,提示注入也相应成为更严重的风险。一个能够点击、输入和导航的智能体,可能被操纵去执行现实世界中的操作,例如填写表单、下载文件或导航到恶意 URL。为这些攻击构建稳健防御,是任何生产部署的必要条件。

我们如何处理提示注入防御

我们已经详细介绍过我们针对浏览器使用和计算机使用的提示注入防御方法。我们的防御策略在多个层面运行:

训练时稳健性。 我们使用强化学习,将提示注入抗性直接构建进 Claude 的能力中。在训练期间,Claude 会接触嵌入在模拟网页和应用 UI 中的注入内容,并在正确识别并拒绝遵循恶意指令时获得奖励。这意味着 Claude 的第一道防线是模型本身,因为它已经学会区分合法的用户指令和任务执行过程中遇到的对抗性内容。

实时分类器。 我们运行探针来扫描进入 Claude 上下文窗口的内容,并标记潜在的提示注入尝试。这些探针可以检测多种模态中的对抗性命令,例如隐藏在页面内容中的文本、嵌入图片中的指令,以及旨在欺骗智能体的欺骗性 UI 元素;当它们识别出攻击时,会相应调整 Claude 的行为。

持续红队测试。 我们的安全研究人员持续探测这些防御,并参与外部对抗性评估,以针对不断演进的攻击技术对稳健性进行基准测试。

自最初的计算机使用研究预览以来,我们持续大力投入这三层防御。每一代新模型都纳入更强的训练时防御和更有能力的分类器,并且我们扩展了红队评估所覆盖的攻击技术范围。

使用 Claude 的内置分类器

当你通过 API 使用 Claude 的官方计算机使用工具时,提示注入分类器会自动在每个请求上运行。这些分类器与主模型推理并行运行,给请求增加的额外延迟约为零,且没有额外成本。

你不需要配置任何内容即可启用此防护。当你使用官方 computer_20251124 工具类型时,它默认开启。分类器会评估截图和其他内容是否存在提示注入迹象,并相应影响 Claude 的响应。


# 使用官方 CU 工具时,分类器会自动运行,无需额外配置
tools = [
    {
        "type": "computer_20251124",
        "name": "computer",
        "display_width_px": 1280,
        "display_height_px": 720,
    }
]

如果你没有使用官方计算机使用工具

许多开发者使用自定义工具定义来构建计算机使用集成,而不是使用官方 computer_20251124 工具类型。例如,定义自己的截图和点击工具。如果这描述的是你的设置,那么上文所述的内置分类器目前不会在你的请求上运行。

我们正在积极探索如何将提示注入防护扩展到这些自定义实现。如果你正在构建不使用官方工具类型的计算机使用或浏览器使用集成,并且对提示注入分类器感兴趣,请填写这份意向表,当此能力可用时,我们会跟进联系。

无论是否使用分类器都应遵循的最佳实践

分类器只是防御的一层,而不是完整解决方案。对于任何计算机使用部署,我们建议采用以下实践:

对高风险操作实现人在环路。 在执行不可逆操作之前,让智能体暂停并请求用户确认,例如提交表单、购买商品、发送消息或修改数据。无论分类器性能如何,这是针对提示注入最有效的单一缓解措施。

限定智能体权限范围。 限制智能体能做什么。如果你的工作流不需要下载文件,就不要给智能体下载文件的访问权限。如果它不需要发送电子邮件,就不要给它访问电子邮件客户端的权限。降低成功注入后的影响范围,与防止注入本身同样重要。

监控并记录智能体动作。 记录智能体采取的完整动作序列,包括每一步的截图。这使你能够检测异常行为,在出现问题时审计发生了什么,并构建反馈循环,随着时间推移提升系统稳健性。

将所有网页内容都视为不受信任。 设计智能体的系统提示时,要明确区分用户指令和任务执行过程中遇到的内容。提醒模型:网页、电子邮件或应用 UI 中发现的文本并非来自用户,不应被当作指令。

计算机使用的上下文管理

在构建计算机使用智能体时,截图会快速累积。每个动作都会生成一张新图,而每张图会根据分辨率大约消耗 1,000–1,800 个 token。算上系统提示、工具定义和文本内容后,一个 200k 的上下文窗口可能在远少于 100 张截图时就被填满。

良好管理这些上下文有两个目标:1)让总 token 数保持有界,2)让提示缓存保持有效,这样你就不会为相同前缀反复支付全价。我们发现,有效的上下文管理对长时间运行智能体的成本和延迟的影响,几乎超过任何其他优化。本节介绍三个可以清晰组合的层次:放置缓存断点、在不破坏缓存的情况下裁剪旧截图,以及当裁剪不够时总结历史。

放置缓存断点

只有当断点落在会跨轮次重复出现的内容上时,提示缓存才有帮助。API 总共支持四个缓存断点。把全部四个断点都放在稳定前缀(系统提示、工具定义)上是一种浪费,因为这个前缀已经命中一次并且不会失效,所以一个断点就足够了。其他三个断点更适合用于近期历史,因为那里失效风险最高,而且节省会在长会话中复利累积。

我们建议:

  • 在系统提示或末尾工具定义上放置一个断点。 这个前缀在一个会话内很少变化。
  • 在最近的工具结果上最多再放置三个断点,每轮向前推进,并清除上一轮迭代的断点,这样就不会超过四个断点的限制。

把断点分散到近期位置可以带来优雅降级。如果你最近的断点失效了,例如由于图像裁剪、压缩或工具定义变更,较早的断点仍然可能命中,这样你只需支付完整输入成本的 10%,而不是 100%。

缓存控制和设置断点示例:

def set_trailing_cache_control(messages, max_breakpoints=3):
    """在清除任何已有标记后,在最近的 tool_result 块上放置最多
    `max_breakpoints` 个 ephemeral cache_control 标记。"""
    for msg in messages:
        for block in msg.get("content", []):
            if isinstance(block, dict):
                block.pop("cache_control", None)

    placed = 0
    for msg in reversed(messages):
        for block in reversed(msg.get("content", [])):
            if placed >= max_breakpoints:
                return
            if isinstance(block, dict) and block.get("type") == "tool_result":
                block["cache_control"] = {"type": "ephemeral"}
                placed += 1

方法 1:滚动缓冲区(缓存感知)

让 token 数保持有界的最简单方式,是只保留最近的 N 张截图并丢弃其余截图。在每次 API 调用之前,遍历消息数组,把更旧的图像块替换为一个简短占位符(例如,一个写着“[Image omitted]”的文本块)。

这种模式的朴素版本是在截图过期时逐张丢弃,这会在每一轮都改变前缀,并持续让提示缓存失效。这就是滚动缓冲区会破坏缓存这一名声的来源。修复方法是批量裁剪,这样前缀可以连续几轮保持逐字节一致,然后只失效一次,之后再次保持稳定。

我们测试过的一个具体模式是:

  1. 以完整分辨率保留最近的 keep_n 张截图。
  2. 一旦截图总数超过 keep_n + interval,就在一次遍历中把最旧的 interval 张截图替换为占位符。
  3. 在裁剪事件之间,消息数组跨轮次逐字节一致,因此你的缓存断点会持续命中。

合理的起始默认值:keep_n = 3,interval = 25。这些值可以调优,较高的 interval 意味着裁剪事件更少(缓存效率更好),但上下文中会留下更长的完整分辨率截图尾部(更多 token)。在有代表性的轨迹上测量缓存命中率和总输入 token 数,并据此调整。

在保留缓存断点的同时裁剪先前截图的示例:

def prune_old_screenshots(messages, keep_n=3, interval=25):
    """批量将较旧截图替换为文本占位符。
    只有当总数超过 keep_n + interval 时才裁剪,因此消息前缀会在两次裁剪之间
    保持 `interval` 轮的字节稳定。"""
    image_positions = [
        (msg_idx, block_idx)
        for msg_idx, msg in enumerate(messages)
        for block_idx, block in enumerate(msg.get("content", []))
        if isinstance(block, dict) and block.get("type") == "image"
    ]
    if len(image_positions) <= keep_n + interval:
        return messages

    to_prune = image_positions[:-keep_n][-interval:]
    for msg_idx, block_idx in to_prune:
        messages[msg_idx]["content"][block_idx] = {
            "type": "text",
            "text": "[Image omitted]",
        }
    return messages

滚动缓冲区仍然有一个真正的限制:缓冲区之外的任何内容都会消失。原始指令、智能体已经尝试过什么、以及它在任务中的位置,都会随着被裁剪的截图一起消失。对于短任务(少于约 50 个动作),这没问题。对于更长的任务,请将它与压缩结合使用。

方法 2:基于 LLM 的压缩

不要静默丢弃旧图像,而是在丢弃之前总结完整对话。摘要会保留发生了什么、用户要求什么、已经完成什么,以及从哪里继续。同时保留几张近期截图,这样智能体可以看到它当前正在查看的内容。

压缩和缓存感知滚动缓冲区是互补的。逐轮使用滚动缓冲区来控制 token 增长;偶尔使用压缩来回收窗口的其余部分,同时不丢失早期上下文。每次压缩事件按设计都会导致缓存失效,所以你希望它少发生,而不是每几轮就发生一次。

总结提示

这个示例提示提供了一个脚手架,其中每一节都针对一种特定失败模式。该提示必须捕获智能体继续任务所需的一切,而无需重新阅读原始对话,如下例所示:

COMPACT_PROMPT = """Your task is to create a detailed summary of this conversation that
will REPLACE the conversation history. The agent will continue working with only this
summary and a few recent screenshots as context.

CRITICAL: Preserve ALL user instructions verbatim. User instructions are the most
critical element. If they are lost, the agent will deviate from the task.

Before providing your summary, analyze the conversation in  tags:
1. Extract every user instruction, requirement, and constraint
2. Identify if this is a repeatable workflow (e.g., processing N items)
3. Chronologically trace what actions were taken and what happened

Your summary MUST include these sections:

1. USER INSTRUCTIONS:
   - Complete initial task definition (verbatim when possible)
   - ALL specific requirements and criteria
   - Every "DO NOT", "ALWAYS", "MUST" instruction
   - Any corrections or feedback that changed the approach

2. TASK TEMPLATE (if this is a repeatable workflow):
   - The pattern being repeated
   - Decision criteria for each iteration
   - Standard workflow steps
   - Example of one completed iteration

3. CONSTRAINTS AND RULES:
   - All user-specified rules and restrictions
   - Edge cases and exceptions discovered

4. ACTIONS TAKEN:
   - Pages visited and elements interacted with
   - Forms filled and buttons clicked

5. ERRORS AND FIXES:
   - What went wrong and how it was resolved
   - Approaches that failed (so they aren't retried)

6. PROGRESS TRACKING:
   - Items completed vs. remaining
   - Current position in the workflow

7. CURRENT STATE:
   - Current application, URL and domain (optional)
   - Important page state (logged in, form progress, etc.)

8. NEXT STEP:
   - Exactly what should be done next to continue
"""

在上面的提示中,User Instructions 会防止任务漂移:没有它们,智能体会在压缩后偏离任务。Task Template 捕获可重复模式,让智能体在压缩后无需从头重新推导工作流即可继续迭代。Constraints and Rules 保留任务开始前设定或任务过程中发现的限制与边界情况,这样智能体就不会违反它原本知道应当遵守的现有规则。Actions Taken 有助于跟踪过去的进度。Errors and Fixes 防止重试失败的方法(“我已经尝试点击 Submit;在勾选 Terms 复选框之前它不会生效”)。Progress Tracking 防止重新开始和跳过项目。Current StateNext Step 给出一个明确无歧义的恢复入口点。

服务器端压缩(beta)

使用这个提示的最简单方式,是让 API 通过服务器端压缩(beta)来处理压缩。把你的自定义总结提示作为 context_management 中的 instructions 参数传入,当输入 token 超过触发阈值时,API 会自动总结。instructions 参数会完全替换默认总结提示,因此模型将遵循上面的各个部分。设置 pause_after_compaction,以便在压缩事件之间附加最近的消息(包括截图)。

使用自动压缩工具的示例:


# Minimal — turn on autocompaction with API defaults
response = client.beta.messages.create(
    model="claude-opus-4-7",
    max_tokens=16000,
    betas=["compact-2026-01-12", "computer-use-2025-11-24"],
    context_management={"edits": [{"type": "compact_20260112"}]},
    messages=[...],
    tools=[...],
)

# Customized — set your own trigger threshold and summarization prompt
response = client.beta.messages.create(
    model="claude-opus-4-7",
    max_tokens=16000,
    betas=["compact-2026-01-12", "computer-use-2025-11-24"],
    context_management={
        "edits": [
            {
                "type": "compact_20260112",
                "trigger": {"type": "input_tokens", "value": 150_000},
                "instructions": COMPACT_PROMPT,
            }
        ]
    },
    messages=[...],
    tools=[...],
)

在客户端截断以匹配服务器

当 API 执行服务器端压缩时,它会在服务器端替换压缩前内容,但你的本地 messages 数组仍然保留完整历史。如果你在后续每一轮仍然发送完整历史,你将为服务器不再需要的 token 付费,而且你的滚动缓冲区裁剪器会作用在与服务器实际看到的不同消息切片上,这可能破坏你在上面精心维护的缓存稳定前缀。

修复方法是在客户端镜像服务器的截断,如下面的代码片段所示。当响应报告发生了压缩时,在下一轮之前从你的本地 messages 数组中删除压缩标记之前的一切。这会让客户端和服务器视图保持一致,并让滚动缓冲区继续正确工作。

def truncate_to_last_compaction(messages, response):
    """如果服务器在这一轮进行了压缩,则在本地丢弃压缩前消息,
    这样下一轮的缓存前缀就会匹配服务器看到的内容。"""
    context_mgmt = getattr(response, "context_management", None)
    if not context_mgmt or not context_mgmt.get("applied_edits"):
        return messages

    compaction = next(
        (e for e in context_mgmt["applied_edits"] if e["type"] == "compact"),
        None,
    )
    if compaction is None:
        return messages

    keep_from = compaction["message_index_after_compaction"]
    return messages[keep_from:]

客户端压缩

如果你使用的模型不支持服务器端压缩,或者你想要完全控制,可以用同样的提示在客户端实现压缩。每次 API 调用之后,从响应的 usage 字段检查总输入 token 数。当它超过某个阈值(例如,上下文窗口的 90%)时,把对话发送给一个总结模型,并将 COMPACT_PROMPT 作为系统提示。用摘要加上几张近期截图替换消息历史,然后继续智能体循环。

组合使用

长时间运行的计算机使用智能体的一个良好默认配置如下:

  • 在稳定前缀上放置一个缓存断点,在末尾工具结果上放置三个断点,并在每一轮清除后重新放置。
  • 使用缓存感知滚动缓冲区,keep_n = 3,interval = 25,批量将较旧截图替换为占位符。
  • 在约 150k 输入 token 附近触发服务器端压缩,使用自定义提示,并加上客户端截断步骤,让两种视图保持一致。

有了这三层机制,一个典型的长周期 CU 会话将在绝大多数轮次命中提示缓存,把总输入 token 控制在远低于上下文窗口的范围内,并通过压缩事件保留足够的历史,让智能体不会忘记任务进展。

用于改进计算机使用和浏览器使用的实验性设置

以下模式是我们在实现中一直测试的技术,它们显示出潜力,但尚未成为普遍推荐。每种技术都以复杂性或成本为代价,换取在特定类型工作负载上的潜在提升。我们把它们收录在这里,方便你在自己的工作流中尝试,但请预期本节中的指导会快速演进。

批量工具

在更新后的参考实现中,我们在标准计算机和浏览器工具旁边暴露了两个工具:computer_batchbrowser_batch。每个工具都接受一个子操作列表,并在一次工具调用中执行它们。例如,模型可以发出一个包含点击、输入和按键这三个动作的 computer_batch 调用,而不是分别进行点击、输入和按键的多个轮次。

其吸引力在于效率:包含 N 个机械动作的工作流只需要一次往返,而不是 N 次往返,这会在长周期任务中显著减少墙钟时间和输出 token 开销。风险在于错误会叠加,如果动作 2 依赖动作 1 改变后的视觉状态,而动作 1 没有命中,那么批处理中剩余的动作都会基于过时假设运行,智能体可能在从未看到实际状态截图的情况下发生偏移。

当子操作是自包含的,并且不依赖彼此的视觉结果时,我们推荐使用批量工具(例如填写表单中的多个字段、串联键盘快捷键、滚动并点击已知目标)。在探索式导航、错误恢复序列,或任何存在“如果动作 1 失败,我需要重新规划”这种真实状态的工作流中,我们会避免使用它们。

由于批量工具是你自己的自定义定义,它们可以与标准计算机或浏览器工具干净地叠加。保持两者都可用,并让模型选择。

顾问工具(beta)

顾问工具 将一个执行器模型与一个更高智能的顾问模型配对,执行器可以在生成过程中咨询顾问以获得战略指导。执行器运行循环,当遇到需要更深层推理的问题时,它会调用顾问,接收计划或路线修正,然后继续执行。这发生在单个请求内部的服务器端,你这边不需要额外往返。

对于计算机使用来说,这种模式在长周期任务中最有用:大多数轮次是机械点击,但偶尔的规划时刻(选择打开哪个标签页、从意外模态框中恢复、决定是否放弃某个策略)会受益于 Opus 级别的推理。你可以获得接近顾问单独执行的质量,同时大部分 token 生成都以执行器的费率完成。

启用顾问工具的示例:

response = client.beta.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=16000,
    betas=["advisor-tool-2026-03-01", "computer-use-2025-11-24"],
    tools=[
        {
            "type": "advisor_20260301",
            "name": "advisor",
            "model": "claude-opus-4-7",
        },
        {
            "type": "computer_20251124",
            "name": "computer",
            "display_width_px": 1280,
            "display_height_px": 720,
        },
    ],
    messages=[...],
)

顾问工具的有用控制项包括:

  • max_uses 限制每个请求中的顾问调用次数。当你想限制最坏情况下的成本时很有帮助。
  • 你的框架中的全会话上限: 顾问每次咨询都按 Opus 4.7 费率计费,因此在非常长的会话中,你可能希望在使用一定次数后停止提供顾问。
  • 顾问侧缓存: 在多调用对话中,大约三次咨询后,缓存顾问的前缀就会带来收益。在参考实现中,我们默认使用 5 分钟的临时缓存。

有两点不太显而易见但值得了解:顾问在没有工具、也没有上下文管理的情况下运行,因此它不能代你点击或浏览,只能返回文本建议。另外,由于执行器模型在长周期任务中并不总能记住顾问的存在,请参阅下面的提醒轻推部分。

清理孤立的顾问块

当顾问工具触发时,执行器会发出一个名称为 “advisor” 的 server_tool_use 块,后面跟着返回内容中的一个 advisor_tool_result 块。这些块与你的消息数组中的其他所有内容一起存在。

如果你之后从工具数组中移除了顾问工具,例如因为达到了全会话上限、更改了配置或切换了模型,那么先前的这些 server_tool_use / advisor_tool_result 块就会变成孤立块。API 会在下一个请求中返回 400,因为被引用的工具不再被声明。

修复方法是在发送前做一次简单处理:每当某一轮禁用顾问时,遍历消息历史,并剥离任何类型为 server_tool_use(且 name == “advisor”)和 advisor_tool_result 的内容块。

移除过期顾问块的示例:

def strip_orphaned_advisor_blocks(messages):
    """从历史中移除 advisor server_tool_use / tool_result 块。
    在任何不包含顾问工具的请求之前调用此函数。"""
    for msg in messages:
        content = msg.get("content")
        if not isinstance(content, list):
            continue
        msg["content"] = [
            block for block in content
            if not (
                isinstance(block, dict)
                and (
                    (block.get("type") == "server_tool_use"
                     and block.get("name") == "advisor")
                    or block.get("type") == "advisor_tool_result"
                )
            )
        ]
    return messages

周期性提醒轻推

在长会话中,执行器模型可能会忘记哪些工具可用,或者哪些工具应该优先使用。在我们的测试中,有两种简短的提醒模式很有帮助:

批量提醒。 如果你在标准工具旁边暴露了 computer_batchbrowser_batch,并观察到模型在适合批量调用时仍然串联单动作调用,那么可以在下一个工具结果之后追加一条简短的系统级轻推:“请记住,当顺序动作不依赖中间截图时,你可以使用 computer_batch 将它们组合到单个工具调用中。”目标是把模型拉回到批处理方向,而不是精确规定何时使用。

顾问提醒。 执行器很容易忘记顾问工具的存在,尤其是在很多轮都没有调用过它的情况下。在超过约 20 轮且没有顾问调用的会话中,追加一条简短提醒,说明顾问可用于规划或路线修正时刻。在参考实现中,我们使用 20 轮的节奏,并追加一行提示。

这两种轻推都是轻量级的上下文注入,而不是系统提示重写。每次追加会消耗几十个输入 token。如果你的系统提示已经很长,或者你的缓存断点放置得非常精确,请权衡这种提升是否值得承担额外的失效风险。

参考实现中的调试模式

当某些东西行为异常,而你不确定问题出在你的框架、截图还是模型时,在开始添加日志之前,参考实现中的三个辅助工具值得先试用:

  • 轨迹查看器(streamlit run viewer/app.py)。 加载已记录的轨迹,让你按步骤查看智能体的各轮交互,包括截图、思考、工具调用和每一步的用量。最适合在运行失败后回答“模型实际看到了什么,它做出了什么决定?”
  • 工具调试面板(uvicorn debug.server:app –reload)。一个小型 Web UI,可让你分别测试每个工具:截图、捕获点击坐标、输入、滚动、缩放。用于确认你的捕获流水线和坐标缩放确实产生了预期结果。
  • 定位试验场(uvicorn localize.server:app –reload –port 8001)。上传任意图像并要求模型指向目标。它会在显示分辨率和原生分辨率下,把预测坐标渲染回你的图像上。这是诊断点击未命中究竟是尺寸调整 bug、坐标缩放 bug,还是模型真实错误的最快方法。当客户报告点击不准确,而你想在隔离环境中复现失败时,这尤其有用。

这些工具都不是构建可用集成所必需的;当默认反馈循环(记录日志、重新运行、眯着眼看转录)不够快时,它们是调试辅助工具。

提高可靠性:教 Claude

与其反复迭代文本提示,直到 Claude 正确完成某个工作流,不如直接向它展示正确行为。录制你自己执行任务的过程,在每一步捕获截图、动作,并可选地捕获语音解说,然后在 Claude 执行同一工作流时,把这段演示作为上下文回放给它。录制内容会成为 Claude 可以遵循的可复用规范,并能适应实时 UI 状态中的差异。

我们在 Claude in Chrome 内部使用这种模式(我们称之为“Teach Mode”),并在这里分享它,因为其底层方法对于任何构建计算机使用或浏览器使用产品的人都广泛有用。它在两方面有帮助:提高 Claude 大体能够处理但偶尔会出错的工作流可靠性,以及解锁 Claude 仅凭文本提示无法完成的全新工作流。核心思想(捕获演示,再将其作为上下文反馈给模型)实现起来很直接,并且很好地适配浏览器和桌面环境。

核心概念:展示,而不是讲述

传统提示工程要求用户用文字描述他们想要什么,然后在 AI 误解时反复迭代。这种模式将其反转:用户演示任务,而系统记录他们的动作、截图以及(可选的)语音解说。在回放期间,Claude 会接收完整演示作为上下文,并遵循相同的步骤序列,同时适应当前 UI 状态中的任何差异。

关键洞察是,回放并不是严格重放。Claude 会把演示作为指南,同时对实时环境进行推理。如果某个按钮移动了,或者菜单被重新组织了,Claude 可以在当前 UI 中找到等价元素,而不是盲目点击记录的坐标。

数据模型

基本单位是“工作流步骤”,即录制期间捕获的单个动作。每个步骤都打包了做了什么、发生在哪里,以及当时屏幕是什么样子:

from dataclasses import dataclass, field
from typing import Literal, Optional

@dataclass
class WorkflowStep:
    action: Literal["click", "type", "navigate", "scroll", "select"]
    description: str                         # 人类可读,例如 "Click the Submit button"
    timestamp: float
    selector: Optional[str] = None           # CSS 选择器或 XPath
    coordinates: Optional[dict] = None       # {"x": int, "y": int}
    url: Optional[str] = None
    screenshot: Optional[str] = None         # Base64 编码的截图
    viewport_dimensions: Optional[dict] = None  # {"width": int, "height": int}
    speech_transcript: Optional[str] = None  # 语音解说,如果已捕获
    value: Optional[str] = None              # 用于 type 动作

@dataclass
class SavedWorkflow:
    id: str
    name: str                                # 例如 "Submit expense report"
    steps: list[WorkflowStep] = field(default_factory=list)
    description: Optional[str] = None        # AI 生成的工作流摘要
    start_url: Optional[str] = None
    created_at: float = 0.0
    usage_count: int = 0

同时捕获选择器和坐标是有意为之:选择器对布局变化更稳健,但坐标提供了一个视觉回退,Claude 可以在选择器失效时使用。存储视口尺寸是为了在回放环境不同于录制环境时对坐标进行缩放。

录制:要捕获什么

至少要捕获点击事件、键盘输入、导航变化,以及每个动作处的截图。对于每次点击,生成一个人类可读的描述(来自 aria-label、文本内容,或通过一次快速的 Claude 调用),并在截图上用视觉标记标注点击位置:

def on_click(event):
    step = WorkflowStep(
        action="click",
        selector=generate_selector(event.target),
        coordinates={"x": event.client_x, "y": event.client_y},
        url=current_url(),
        description=generate_description(event.target),
        timestamp=now(),
        viewport_dimensions=get_viewport_size(),
    )
    # 用点击位置处的圆圈标注截图
    screenshot = capture_screenshot()
    step.screenshot = annotate_with_circle(screenshot, event.client_x, event.client_y)
    workflow_steps.append(step)

这种标注(点击位置处的彩色圆圈)有两个目的:帮助用户验证录制是否捕获了正确元素,并在回放期间向 Claude 准确显示动作发生的位置。你的回放提示应说明这些标记是录制产物,不是实时 UI 的一部分。

回放:构建提示

这是最重要的部分。当用户触发保存的工作流时,你会构造一条发给 Claude 的消息,其中包含三项内容:用户意图、解释演示格式的上下文块,以及录制的截图。

上下文块告诉 Claude 如何解释带标注的截图,以及当实时 UI 不同时如何适应:

def generate_playback_context(steps: list[WorkflowStep]) -> str:
    steps_description = "\n".join(
        f"Step {i+1}: {step.description}"
        for i, step in enumerate(steps)
    )

    return f"""<demonstration_context>
The user has recorded a demonstration showing how to perform this task.

RECORDED STEPS:
{steps_description}

ABOUT THE SCREENSHOTS:
- Each screenshot shows the screen state when an action was taken
- BLUE CIRCLES mark where the user clicked — these are recording annotations
- The blue highlighting is NOT part of the actual interface
- Your own screenshots will NOT have these markers

HOW TO USE THIS DEMONSTRATION:
1. Review all steps and screenshots to understand the complete workflow
2. Take your own screenshot to see the CURRENT page state
3. The blue highlights show which element to interact with — find it in your current view
4. Follow the same sequence of actions, adapting to any differences
5. If the UI has changed significantly, use judgment to find equivalent elements
</demonstration_context>"""

然后将用户提示、上下文块和每个步骤的截图作为图像组装成完整消息:

import anthropic

client = anthropic.Anthropic()

content = [
    {"type": "text", "text": user_prompt},
    {"type": "text", "text": generate_playback_context(workflow.steps)},
]

for i, step in enumerate(workflow.steps):
    if step.screenshot:
        content.append({"type": "text", "text": f"[Step {i+1}: {step.description}]"})
        content.append({
            "type": "image",
            "source": {"type": "base64", "media_type": "image/jpeg", "data": step.screenshot},
        })

response = client.beta.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=4096,
    betas=["computer-use-2025-11-24"],
    messages=[{"role": "user", "content": content}],
    tools=[{
        "type": "computer_20251124",
        "name": "computer",
        "display_width_px": 1280,
        "display_height_px": 720,
    }],
)

回放模式

并非每个工作流都需要对录制演示保持相同程度的遵循。有些工作流太长,会消耗大量输入 token,最终降低延迟表现并增加成本。可以考虑支持一个严格程度参数,并将其包含在上下文提示中:

严格: 精确遵循步骤;如果 UI 变化过大,则停止并报告。适合对合规敏感、精确顺序很重要的工作流。

自适应: 将演示作为指南,但适应 UI 变化。这是大多数用例的最佳默认值,它能优雅地处理轻微布局偏移、更新后的按钮标签和重组后的菜单。

目标导向: 关注最终结果;将录制步骤视为提示,而不是指令。当 UI 经常变化但目标保持不变时很有用。使用一个模型对录制演示进行摘要,采用类似下一节所述的策略,然后将该摘要传给 CU 模型。

示例:端到端报销单工作流

下面是一个保存的工作流在实践中的样子。该工作流捕获五个步骤:导航到报销表单、选择报销类型、从下拉菜单中选择 “Travel”、输入金额,以及点击 Submit。

expense_workflow = SavedWorkflow(
    id="wf_abc123",
    name="Submit Expense Report",
    start_url="https://expenses.company.com/new",
    steps=[
        WorkflowStep(
            action="navigate",
            url="https://expenses.company.com/new",
            description="Navigate to new expense form",
            timestamp=1700000000,
        ),
        WorkflowStep(
            action="click",
            selector="#expense-type-dropdown",
            coordinates={"x": 400, "y": 200},
            description="Click on expense type dropdown",
            timestamp=1700000001,
        ),
        WorkflowStep(
            action="click",
            selector="[data-value='travel']",
            coordinates={"x": 400, "y": 280},
            description='Select "Travel" expense type',
            timestamp=1700000002,
        ),
        WorkflowStep(
            action="type",
            selector="#amount-input",
            value="150.00",
            description="Enter expense amount",
            timestamp=1700000003,
        ),
        WorkflowStep(
            action="click",
            selector="#submit-expense-btn",
            coordinates={"x": 1150, "y": 420},
            description="Click the Submit button",
            speech_transcript="Now I'll click submit to send the report for approval",
            timestamp=1700000004,
        ),
    ],
)

当用户稍后说“Submit my expense report for the team lunch ($85.50)”时,回放服务会构造一个包含演示上下文、全部五张标注截图,以及新请求中的具体值的提示。Claude 会准确看到该点击哪里、遵循什么序列,并调整金额和描述以匹配当前任务。如果由于输入 token 数量导致你的工作流太长而无法实际采用这种方法,那么可以考虑先压缩工作流,再将其用作示例。关于管理上下文的技巧,请参阅下一节。

计算机使用与浏览器使用入门

这些实践反映了我们目前对如何让计算机使用集成在生产环境中保持可靠的最佳理解。它们适用于 Claude 4.6 模型系列和 Opus 4.7,并会随着新模型和新技术的出现而更新。

随着你的集成逐步成熟,最重要的模式将取决于你的具体环境、目标应用和可靠性要求。**

可以先阅读 计算机使用文档,查看我们针对这些最佳实践推出的全新 演示实现,或者重温 最初的计算机使用研究文章,了解这些能力是如何构建的,以及未来的发展方向。

致谢:本文及相应的演示由 Lucas Gonzalez 和 Luca Weihs 撰写。作者感谢 Molly Vorwerck、Javier Rando、Maya Nielan、Gabe Mulley 和 Brigit Brown 的贡献。