计算机使用让模型能够操作浏览器和桌面界面。您可以用它填写表单、测试用户流程,或通过应用的 UI 完成任务。
您负责提供环境并执行模型的请求。模型根据截图和其他工具结果决定下一步操作。请选择将模型接入您的应用的方式:
- 代码执行: 模型编写代码,使用 PyAutoGUI 或 Playwright 等库操作界面。一次调用可以组合多个操作、循环或条件逻辑。
- 计算机工具: 模型返回结构化的鼠标和键盘操作,由您的应用将其转换为浏览器或桌面输入。
对于 GPT-6 Astra,我们推荐使用代码执行。computer 工具仍受支持,可作为另一种选择。
如果您已经通过函数调用或远程 MCP 工具提供 UI 操作,可以保留现有接口。有关这些集成在执行工具和返回结果方面的差异,请参阅使用您自己的 UI 工具。
使用代码执行
代码执行集成向模型提供一个接受脚本的函数工具。您的应用在隔离的浏览器或桌面环境中运行脚本,并返回包括截图在内的输出。请在调用之间保持环境可用,以便模型在先前工作的基础上继续操作。
运行示例应用
CUA 示例应用包含 JavaScript/Playwright 和 Python/PyAutoGUI 两种实现,并提供本地任务和共享控制台:
- 请在隔离环境中按照您所选实现的设置说明进行操作。
- 选择一个内置场景并开始运行。
- 检查操作、截图和最终状态,评估任务是否成功。
有关安装、桌面权限和支持的环境,请参阅应用的 README。在将其用于真实网站或账户之前,请阅读安全运行。
接入您自己的运行时
以下示例展示了如何通过 API 循环调用您提供的运行时。Python 和 Ruby 将 Python 代码发送到使用 PyAutoGUI 的桌面运行时;JavaScript 使用 Playwright 操作浏览器。每个客户端都提供一个普通的函数工具,并在返回文本或图像时附带原始的 call_id。
execute_in_sandbox 或 executeInSandbox 辅助函数将代码发送到您的执行环境,并返回观测结果。它必须保持浏览器或桌面会话、落实执行限制,并应用您的权限规则。这些是集成示例,与运行示例应用是两回事。
import json
import uuid
from openai import OpenAI
from openai.types.responses import (
FunctionToolParam,
ResponseInputParam,
)
def run_computer_use(endpoint, prompt, model="gpt-6-astra"):
client = OpenAI()
session_id = str(uuid.uuid4())
tools: list[FunctionToolParam] = [
{
"type": "function",
"name": "exec_py",
"description": (
"Run Python in a persistent desktop. Variables persist across calls. "
"PyAutoGUI operations are synchronous. Available: pyautogui, time, "
"log(value), and display(PIL_image). Inspect the screen with "
"display(pyautogui.screenshot()) before acting. Use screenshot "
"coordinates and check the screen after a short group of actions. "
"Keep screenshots in memory and PyAutoGUI's fail-safe enabled."
),
"parameters": {
"type": "object",
"properties": {"code": {"type": "string"}},
"required": ["code"],
"additionalProperties": False,
},
"strict": True,
}
]
next_input: ResponseInputParam = [{"role": "user", "content": prompt}]
previous_response_id = None
for turn in range(20):
response = client.responses.create(
model=model,
tools=tools,
input=next_input,
previous_response_id=previous_response_id,
)
if response.status != "completed":
raise RuntimeError(f"Response stopped with status: {response.status}")
calls = [item for item in response.output if item.type == "function_call"]
if not calls and any(
item.type == "message" and item.phase != "commentary"
for item in response.output
):
print(response.output_text)
return
if turn == 19:
raise RuntimeError(
"The task reached the 20-response limit. Inspect the last result."
)
next_input = []
for call in calls:
if call.name != "exec_py":
raise ValueError(f"Unexpected tool: {call.name}")
code = json.loads(call.arguments)["code"]
output = execute_in_sandbox(code, session_id, endpoint)
next_input.append(
{
"type": "function_call_output",
"call_id": call.call_id,
"output": output,
}
)
previous_response_id = response.idimport { randomUUID } from "node:crypto";
import OpenAI from "openai";
async function runComputerUse(endpoint, prompt, model = "gpt-6-astra") {
const client = new OpenAI();
const sessionId = randomUUID();
const tools = [
{
type: "function",
name: "exec_js",
description: `Run JavaScript in a persistent browser. Available: Playwright's
browser, context, and page objects; console.log(value); and display(base64Image).
Save reusable variables on globalThis. Inspect a screenshot before acting and
check the screen after a short group of actions. Keep screenshots in memory.
Use top-level await for async operations. Return images with display() and concise
text with console.log(). The context viewport is 1440x900.`,
parameters: {
type: "object",
properties: { code: { type: "string" } },
required: ["code"],
additionalProperties: false,
},
strict: true,
},
];
let nextInput = [{ role: "user", content: prompt }];
let previousResponseId;
for (let turn = 0; turn < 20; turn++) {
const response = await client.responses.create({
model,
tools,
input: nextInput,
previous_response_id: previousResponseId,
reasoning: { effort: "low" },
});
if (response.status !== "completed") {
throw new Error(`Response stopped with status: ${response.status}`);
}
const calls = response.output.filter(
(item) => item.type === "function_call"
);
if (
calls.length === 0 &&
response.output.some(
(item) => item.type === "message" && item.phase !== "commentary"
)
) {
console.log(response.output_text);
return;
}
if (turn === 19) {
throw new Error(
"The task reached the 20-response limit. Inspect the last result."
);
}
nextInput = [];
for (const call of calls) {
if (call.name !== "exec_js")
throw new Error(`Unexpected tool: ${call.name}`);
const { code } = JSON.parse(call.arguments);
const output = await executeInSandbox(code, sessionId, endpoint);
nextInput.push({
type: "function_call_output",
call_id: call.call_id,
output,
});
}
previousResponseId = response.id;
}
}require "json"
require "openai"
require "securerandom"
def run_computer_use(endpoint, prompt)
client = OpenAI::Client.new
session_id = SecureRandom.uuid
tools = [
{
type: :function,
name: "exec_py",
description: "Run Python in a persistent desktop. Variables persist across calls. PyAutoGUI operations are synchronous. Available: pyautogui, time, log(value), and display(PIL_image). Inspect the screen with display(pyautogui.screenshot()) before acting. Use screenshot coordinates and check the screen after a short group of actions. Keep screenshots in memory and PyAutoGUI's fail-safe enabled.",
parameters: {
type: :object,
properties: { code: { type: :string } },
required: ["code"],
additionalProperties: false
},
strict: true
}
]
next_input = []
next_input << {
role: :user,
content: prompt
}
history = {}
20.times do |turn|
response = client.responses.create(
model: "gpt-6-astra", tools: tools, input: next_input, previous_response_id: history[:id]
)
raise "Response stopped with status: #{response.status}" unless response.status == OpenAI::Responses::ResponseStatus::COMPLETED
calls = response.output.grep(OpenAI::Responses::ResponseFunctionToolCall)
if calls.empty? && response.output.any? { |item| item.is_a?(OpenAI::Responses::ResponseOutputMessage) && item.phase != :commentary }
puts(response.output_text)
return response
end
raise "The task reached the 20-response limit" if turn == 19
next_input.clear
calls.each do |call|
raise "Unexpected tool: #{call.name}" unless call.name == "exec_py"
code = JSON.parse(call.arguments).fetch("code")
raise "Expected Python source text" unless code.is_a?(String)
output = execute_in_sandbox(code, session_id, endpoint)
next_input << {
type: :function_call_output,
call_id: call.call_id,
output: output
}
end
history[:id] = response.id
end
end有关完整的客户端适配器以及预期的文本和图像输出结构,请参阅连接到您的执行服务。这些示例中的服务接口属于您的应用,并非由 OpenAI 托管的端点。
保留状态并返回观测结果
在调用之间保持浏览器或桌面会话运行。持久化的 Python 或 JavaScript 命名空间还可以保留变量。请在工具定义中描述可用的对象和辅助函数,让模型知道可以使用哪些内容。
当 UI 状态未知时,请向模型提供当前截图。执行一小组操作后,再返回一张截图,以便模型检查结果。将图像保留在内存中,并使用 detail: "original" 保持原始分辨率。如果您缩小了截图,请在执行操作之前,将模型给出的坐标映射回环境的坐标空间。请参阅截图捕获与分辨率。
API 对话和执行环境各自维护独立的状态。请在对话中保留工具调用及其输出,并在您的应用中保持对应环境可用。延续响应不会恢复浏览器会话、登录状态或运行时变量。
使用计算机工具
如果您的集成需要结构化操作而非生成的代码,可以采用这种替代方案。如需采用推荐方案,请从代码执行开始。
要尝试这种方式,请按照相同的示例应用设置步骤操作,选择 原生 模式,然后运行一个内置场景。请使用支持计算机工具的模型。
API 交互分为三个步骤:发送任务、执行返回的操作、返回截图。这里的代码片段使用的页面包含一个 显示筛选条件 控件和一个搜索框。集成工具时,请根据您自己的界面调整该任务。
有关环境设置和操作处理程序,请参阅集成示例。
发送任务
在 tools 数组中启用 computer,并描述您想要的结果:
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-5.6-sol",
tools=[{"type": "computer"}],
input="Check whether the Filters panel is open. If it is not open, click Show filters. Then type penguin in the search box. Use the computer tool for UI interaction.",
)
print(response.output)执行请求的操作
computer_call 包含一个有序的 actions 数组。例如,以下调用会选中搜索框并输入 penguin:
{
"output": [
{
"type": "computer_call",
"call_id": "call_002",
"actions": [
{ "type": "click", "button": "left", "x": 405, "y": 157 },
{ "type": "type", "text": "penguin" }
],
"status": "completed"
}
]
}您的操作处理程序将这些请求转换为浏览器或操作系统输入。请按顺序执行获准的操作,然后捕获更新后的屏幕。模型可以请求 click、double_click、drag、move、scroll、keypress、type、wait 或 screenshot。
首次调用可能只包含一个 screenshot 操作。在这种情况下,请捕获当前屏幕并返回,不要更改 UI。调用中的 status: "completed" 表示模型已完成该调用的生成;您的应用仍需执行该调用。
有关按键映射、拖动路径和修饰键,请参阅操作处理程序示例。
返回截图
返回一个 computer_call_output,其 call_id 应与您处理的调用相匹配。使用 previous_response_id 继续与模型对话:
from openai import OpenAI
client = OpenAI()
def send_computer_screenshot(response, call_id, screenshot_base64):
return client.responses.create(
model="gpt-5.6-sol",
tools=[{"type": "computer"}],
previous_response_id=response.id,
input=[
{
"type": "computer_call_output",
"call_id": call_id,
"output": {
"type": "computer_screenshot",
"image_url": f"data:image/png;base64,{screenshot_base64}",
"detail": "original",
},
}
],
)同样的截图与状态指导也适用于此循环。在使用 previous_response_id 继续与模型对话期间,请保持环境可用。
继续循环,直到模型不再返回 computer_call 项。检查其余输出中是否包含回答、求助请求或其他工具调用,并在应用中验证结果。在本例中,筛选面板应处于打开状态,搜索框中应包含 penguin。
有关循环的基本结构及其所需的操作和截图辅助函数,请参阅重复计算机使用循环。
安全运行
计算机使用可能影响真实账户和数据。请在您的应用、执行环境以及模型指令中落实以下控制措施:
- 限制环境的访问范围。 使用隔离的浏览器或虚拟机,并为网站和操作设置允许列表。仅开放任务所需的访问权限。
- 将屏幕内容视为不可信内容。 页面、文档或工具结果中的文本不能授予权限,也不能覆盖用户的指令。
- 对影响重大的操作进行确认。 让用户掌控购买、数据传输、破坏性更改以及其他难以撤销的操作。在表单中输入敏感信息也属于数据传输。
- 为运行设置限制并验证结果。 设置步数、时间或成本限制,支持取消,并检查实际结果,而不是仅依赖模型的最终回答。
有关具体的审批要求、人工接管和提示示例,请参阅确认与同意指南。
后续步骤
- 有关环境设置、操作处理程序、屏幕截图获取和执行服务适配器,请参阅集成示例。
- 更新旧版集成时,请遵循从 computer-use-preview 迁移中的说明。
- 探索 CUA 示例应用,了解完整的浏览器和桌面工作流。