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.idEl uso de la computadora permite que un modelo interactúe con la interfaz de un navegador o de un escritorio. Úsalo para completar formularios, probar flujos de usuario o realizar tareas en una aplicación.
Elige una opción según lo que el modelo necesite ver y quién ejecute el entorno:
| Tarea | Por dónde empezar |
|---|---|
| Usar capturas de pantalla y realizar acciones con el mouse o el teclado en tu navegador o escritorio | Usa ComputerToolset con la herramienta de computadora de Responses. |
| Leer el texto de una página o usar controles y pestañas en tu navegador | Usa BrowserToolset. Tu controlador expone las operaciones seleccionadas como herramientas de función. |
| Ejecutar un navegador alojado por OpenAI | Sigue la guía de uso de la computadora con la API de Agentes, que se publica por separado. |
Para consultar información pública que no requiere interacción, usa la búsqueda web.
Usar el SDK
El SDK ejecuta el ciclo de llamadas a herramientas de Responses en Python o Node. Tu aplicación proporciona un controlador, es decir, el código que lee el estado del entorno o realiza una acción permitida. Tu aplicación se encarga de la sesión, los permisos y la liberación de recursos.
Conectar un entorno alojado
Usa el navegador o el escritorio de un proveedor para que no tengas que ejecutar uno por tu cuenta. Algunas integraciones incluyen un controlador. Otras exponen controles que tu aplicación vincula con el SDK. Consulta la guía del proveedor para conocer los pasos de configuración y las versiones compatibles de los paquetes.
| Entorno | Integración |
|---|---|
| Browserbase | Usa el controlador de navegador de Stagehand con una sesión alojada en Browserbase. Sigue la guía de integración de Stagehand o consulta los ejemplos en Python y TypeScript. |
| Browser Use | Usa el controlador de la biblioteca Browser Use o conecta tu código de Playwright con la integración de Browser Use Cloud. Ambas guías usan Python. |
| Daytona | Usa ComputerToolset con un sandbox de escritorio de Daytona. Sigue la guía de funciones auxiliares de Daytona para el uso de la computadora (Python). Para ver un ejemplo con el SDK de Agentes, consulta la receta de uso de la computadora con Daytona. |
| E2B Desktop | Realiza acciones de computadora o ejecuta código en un sandbox de escritorio. Sigue la guía de E2B para el uso de la computadora o consulta los ejemplos en Python y TypeScript. |
Establece un tiempo de espera máximo para la sesión y ciérrala o libérala incluso si falla la ejecución. Revisa el panel del proveedor si falla la liberación de recursos. Usa las reglas de red del proveedor para limitar los sitios y recursos a los que puede acceder la sesión.
Ejecutar tu primera tarea
Usa Python 3.11 o posterior, o Node.js 22.6 o posterior. Crea y exporta una clave de API. Ambos ejemplos usan un navegador local temporal y hacen llamadas a la API de Responses que pueden generar cargos.
Instala los paquetes y Chromium en una carpeta nueva:
# Python
python3 -m venv .venv
.venv/bin/python -m pip install openai==3.31.0 playwright==1.61.0
.venv/bin/python -m playwright install chromium
# Node
npm install openai@7.33.0 playwright@1.61.1
npx playwright install chromium
En Windows, usa py -3 en lugar de python3 y .venv\Scripts\python.exe en lugar de .venv/bin/python.
El modelo ve una captura de pantalla de una página ficticia de retiro de paquetes y hace clic para ver los detalles del retiro. El controlador solo permite tomar capturas de pantalla y hacer clic con el botón izquierdo en ese control. Bloquea las solicitudes de la página y cierra el navegador al finalizar la ejecución. El script envía como máximo seis solicitudes a Responses y comprueba la página antes de informar que la tarea se completó correctamente. Tu proyecto necesita acceso a un modelo compatible con la herramienta de computadora.
Guarda el ejemplo correspondiente como pickup.py o pickup.mjs:
import asyncio
import base64
from openai import AsyncComputerToolset, AsyncOpenAI
from playwright.async_api import async_playwright
class PickupDriver:
def __init__(self, page):
self.page = page
async def screenshot(self):
image = await self.page.screenshot(type="png")
return {
"type": "computer_screenshot",
"image_url": "data:image/png;base64," + base64.b64encode(image).decode(),
}
async def allowed(self, action):
if action.type == "screenshot":
return True
if action.type != "click" or action.button != "left" or action.keys:
return False
box = await self.page.locator("summary").bounding_box()
return bool(
box
and box["x"] <= action.x < box["x"] + box["width"]
and box["y"] <= action.y < box["y"] + box["height"]
)
async def click(self, action):
# The page may have changed after approval, so bind the click again.
if not await self.allowed(action):
raise RuntimeError("Pickup details moved or the click is not allowed.")
await self.page.mouse.click(action.x, action.y)
async def refuse(self, action):
raise RuntimeError(f"This exercise does not allow {action.type}.")
double_click = drag = keypress = move = scroll = type = wait = refuse
async def main():
async with (
async_playwright() as playwright,
AsyncOpenAI(timeout=30, max_retries=0) as client,
):
browser = await playwright.chromium.launch(env={}, chromium_sandbox=True)
try:
page = await browser.new_page(viewport={"width": 1024, "height": 768})
await page.route("**/*", lambda route: route.abort())
await page.set_content(
"<title>Parcel pickup</title><main>"
"<h1>Parcel pickup</h1><p>Order #1042 is ready.</p>"
"<details><summary>Show pickup details</summary>"
"<p>Locker 18. Pickup code: 6249.</p></details></main>"
)
driver = PickupDriver(page)
tools = AsyncComputerToolset(driver)
try:
response = await tools.run(
client,
{
"model": "gpt-6.1-sol",
"store": False,
"input": "Take a screenshot. Open 'Show pickup details' and report the locker and pickup code. Use only screenshots and left clicks.",
},
before_action=driver.allowed,
max_steps=6,
)
if await page.locator("details").get_attribute("open") is None:
raise RuntimeError("Pickup details are still closed.")
print(
"Verified pickup details:",
await page.locator("details p").inner_text(),
)
print("Answer:", response.output_text)
finally:
tools.close()
finally:
await browser.close()
if __name__ == "__main__":
asyncio.run(main())Ejecuta .venv/bin/python pickup.py o node pickup.mjs. Si la tarea se completa correctamente, el script muestra Verified pickup details: Locker 18. Pickup code: 6249. y, a continuación, la respuesta del modelo. Si hay comprobaciones de seguridad pendientes en la API, el ejemplo se detiene. Agrega una función de aprobación humana solo cuando tu aplicación pueda gestionar esas comprobaciones.
El modelo escribe un nombre en un formulario de credenciales para visitantes y hace clic en Create badge. El controlador solo permite leer la página, escribir y hacer clic. Su función de confirmación solo permite usar los controles de ese formulario y el nombre Mira. El script verifica el resultado en la página antes de informar que la tarea se completó correctamente.
Guarda el ejemplo correspondiente como badge.py o badge.mjs:
import asyncio
from openai import AsyncOpenAI
from openai.lib.browser import AsyncBrowserToolset
from openai.lib.responses_tool_runner import AsyncResponsesToolRunner
from playwright.async_api import async_playwright
class BadgeForm:
def __init__(self, page):
self.page = page
async def state(self):
return {
"tabs": [
{
"id": "badge",
"title": await self.page.title(),
"url": self.page.url,
"active": True,
}
]
}
async def read_page(self, args):
return {
"version": 1,
"text": await self.page.locator("body").inner_text(),
"elements": [
{"ref": "name", "role": "textbox", "label": "Name"},
{"ref": "save", "role": "button", "label": "Create badge"},
],
"omitted": [],
}
async def type(self, args):
await self.page.locator("#name").fill(args["text"])
async def click(self, args):
await self.page.locator("#save").click()
async def confirm(self, context):
args = context["arguments"]
if self.page.url != "about:blank" or args["tab_id"] not in (None, "badge"):
return False
return (
context["member"] == "type"
and args["target"] == "name"
and args["text"] == "Mira"
) or (context["member"] == "click" and args["target"] == "save")
async def main():
async with (
async_playwright() as playwright,
AsyncOpenAI(timeout=30, max_retries=0) as client,
):
browser = await playwright.chromium.launch(env={}, chromium_sandbox=True)
try:
page = await browser.new_page()
await page.route("**/*", lambda route: route.abort())
await page.set_content("""
<title>Visitor badge</title>
<label>Name <input id="name"></label>
<button id="save" onclick="document.querySelector('output').innerText =
'Badge ready: ' + document.querySelector('#name').value">Create badge</button>
<output></output>
""")
driver = BadgeForm(page)
tools = AsyncBrowserToolset(
driver, members=["read_page", "type", "click"], confirm=driver.confirm
)
response = await AsyncResponsesToolRunner(browser=tools).run(
client,
{
"model": "gpt-6-astra",
"store": False,
"input": "Create a visitor badge for Mira.",
},
max_steps=6,
)
result = await page.locator("output").inner_text()
if result != "Badge ready: Mira":
raise RuntimeError(f"The badge was not created: {result!r}")
print(result)
print("Answer:", response.output_text)
finally:
await browser.close()
if __name__ == "__main__":
asyncio.run(main())Ejecuta .venv/bin/python badge.py o node badge.mjs. Si la tarea se completa correctamente, el script muestra Badge ready: Mira y, a continuación, la respuesta del modelo.
Si la API rechaza la herramienta o Chromium no se inicia, consulta cómo solucionar problemas de ejecución. Si los clics no llegan al lugar correcto, revisa la captura de pantalla y las coordenadas.
Revisar el acceso al modelo, el costo y los datos
- Modelo: para usar herramientas de función en el navegador, comprueba que el modelo sea compatible con Responses y con la llamada a funciones. Si tu controlador devuelve imágenes, comprueba también que el modelo admita imágenes de entrada. Para realizar acciones de computadora a partir de capturas de pantalla, verifica en la sección Herramientas del modelo que admita el uso de la computadora. Consulta el catálogo de modelos y comprueba a cuáles tiene acceso tu proyecto.
- Costo: cada solicitud a Responses puede generar cargos por los tokens de entrada y salida. Las capturas de pantalla cuentan como imágenes de entrada. Consulta los precios de la API, estima el costo de las imágenes de entrada o revisa el consumo de una solicitud. El proveedor de un entorno alojado puede cobrar por separado.
- Datos: el SDK envía a OpenAI el texto de la página o las capturas de pantalla que devuelve el controlador. Los ejemplos establecen
storeenfalse, pero esto no elimina todas las formas de retención de datos. Revisa los controles de datos y las excepciones para imágenes de entrada. El proveedor de tu entorno tiene su propia política de datos.
Ver y aprobar cambios
Ahora prueba la demo de reservas en Python o Node. La demo completa una reserva ficticia, solicita aprobación antes de enviarla y comprueba los campos guardados y la confirmación. Puedes observar el navegador, tomar el control, devolverlo o detener la ejecución. Ambas versiones incluyen una prueba local con un navegador real que se ejecuta sin llamar a la API.
Para observar las acciones del SDK en un escritorio, prueba la demo visual de escritorio.
Adaptar el controlador
Reemplaza la página de ejemplo por un entorno que controle tu aplicación. Si usas un controlador de navegador, expón con members solo las operaciones necesarias para la tarea. Si usas un controlador de computadora, implementa los métodos requeridos y rechaza las acciones que no admita. Mantén la sesión abierta hasta que termine la ejecución y luego cierra los recursos que haya creado tu aplicación.
El contenido de la página puede influir en el modelo. Usa un perfil de navegador nuevo o un escritorio aislado. Limita el acceso a la red y evita que las credenciales aparezcan en el texto de la página o en las capturas de pantalla. Solicita aprobación antes de hacer cambios y comprueba el resultado guardado antes de informar que la tarea se completó correctamente. Consulta la referencia de controladores para conocer los contratos de los métodos, el proceso de aprobación, la política de URL y las opciones de recuperación.
Cambiar a Decisions cuando las opciones están predefinidas
Usa Responses cuando el modelo deba elegir acciones y generar sus argumentos. Usa Decisions solo cuando tu aplicación ya conozca todas las acciones permitidas y los valores de todos sus argumentos. Por ejemplo, una aplicación podría ofrecer route_billing, route_technical y review. Decisions selecciona una opción. Tu aplicación sigue siendo responsable de aprobarla, ejecutarla y comprobar el resultado. Descarta las opciones cuando cambie la página. Consulta la guía de Decisions.
Para probar Decisions en la demo de reservas, usa una clave con acceso a Decisions, configura OPENAI_DECISIONS_MODEL y reinicia el servidor. Inicia una nueva ejecución y selecciona Decisions.
Usar la API directamente
Usa la API de Responses directamente cuando necesites gestionar por tu cuenta el ciclo de llamadas a herramientas. Tú proporcionas el entorno y ejecutas lo que solicita el modelo. Elige cómo conectar el entorno a tu aplicación:
- Ejecución de código: el modelo escribe código que usa una biblioteca como PyAutoGUI o Playwright para interactuar con la interfaz. Una sola llamada puede combinar acciones, ciclos o lógica condicional.
- Herramienta de computadora: el modelo devuelve acciones estructuradas de mouse y teclado que tu aplicación convierte en entradas para el navegador o el escritorio.
Para GPT-6 Astra, recomendamos la ejecución de código. La herramienta computer sigue disponible como alternativa.
Si ya expones operaciones de la interfaz de usuario mediante la llamada a funciones o herramientas MCP remotas, puedes conservar esa interfaz. Consulta Usar tus propias herramientas de interfaz de usuario para ver en qué se diferencian esas integraciones al ejecutar herramientas y devolver resultados.
Usar la ejecución de código
Una integración de ejecución de código proporciona al modelo una herramienta de función que acepta un script. Tu aplicación ejecuta el script en un entorno aislado de navegador o de escritorio y devuelve su salida, incluidas las capturas de pantalla. Mantén el entorno disponible entre llamadas para que el modelo pueda continuar con el trabajo anterior.
Ejecutar la aplicación de ejemplo
La aplicación de ejemplo de CUA (AUC) incluye implementaciones en JavaScript con Playwright y en Python con PyAutoGUI, con tareas locales y una consola compartida:
- Sigue las instrucciones de configuración de la implementación que elijas en un entorno aislado.
- Elige uno de los escenarios incluidos e inicia una ejecución.
- Revisa las acciones, las capturas de pantalla y el estado final para determinar si la tarea se completó correctamente.
Consulta el README de la aplicación para obtener información sobre la instalación, los permisos de escritorio y los entornos compatibles. Revisa la sección Ejecutar tareas de forma segura antes de adaptar la aplicación a sitios o cuentas reales.
Conectar tu propio entorno de ejecución
El siguiente ejemplo muestra el ciclo de llamadas a la API para un entorno de ejecución que tú proporcionas. Los clientes de Python, Ruby y Go envían código Python a un entorno de ejecución de escritorio que usa PyAutoGUI. El cliente de JavaScript usa Playwright para controlar un navegador. Cada cliente expone una herramienta de función convencional y devuelve texto o imágenes con el call_id original.
La función auxiliar execute_in_sandbox o executeInSandbox envía código a tu entorno de ejecución y devuelve lo que observa allí. Debe conservar la sesión del navegador o del escritorio, hacer cumplir los límites de ejecución y aplicar tus reglas de permisos. Estos ejemplos de integración son independientes de la ejecución de la aplicación de ejemplo.
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
endfunc runComputerUse(ctx context.Context, client openai.Client, endpoint, prompt string, terminal *bufio.Scanner, output io.Writer) error {
session := make([]byte, 16)
if _, err := rand.Read(session); err != nil {
return err
}
sessionID := hex.EncodeToString(session)
tool := responses.ToolParamOfFunction("exec_py", map[string]any{
"type": "object", "properties": map[string]any{"code": map[string]any{"type": "string"}},
"required": []string{"code"}, "additionalProperties": false,
}, true)
tool.OfFunction.Description = openai.String("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.")
params := responses.ResponseNewParams{
Model: "gpt-6-astra", Tools: []responses.ToolUnionParam{tool},
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(prompt)},
}
for turn := 0; turn < 20; turn++ {
response, err := client.Responses.New(ctx, params)
if err != nil {
return err
}
if response.Status != "completed" {
return fmt.Errorf("response stopped with status: %s", response.Status)
}
var calls []responses.ResponseFunctionToolCall
finalMessage := false
for _, item := range response.Output {
if item.Type == "function_call" {
calls = append(calls, item.AsFunctionCall())
}
if item.Type == "message" && item.AsMessage().Phase != "commentary" {
finalMessage = true
}
}
if len(calls) == 0 && finalMessage {
fmt.Fprintln(output, response.OutputText())
return nil
}
if turn == 19 {
return fmt.Errorf("task reached the 20-response limit; inspect the last result")
}
nextInput := responses.ResponseInputParam{}
for _, call := range calls {
if call.Name != "exec_py" {
return fmt.Errorf("unexpected tool: %s", call.Name)
}
var arguments struct {
Code *string `json:"code"`
}
if err := json.Unmarshal([]byte(call.Arguments), &arguments); err != nil {
return err
}
if arguments.Code == nil {
return fmt.Errorf("exec_py requires code")
}
observations, err := executeInSandbox(ctx, endpoint, sessionID, *arguments.Code, terminal, output)
if err != nil {
return err
}
nextInput = append(nextInput, responses.ResponseInputItemUnionParam{
OfFunctionCallOutput: &responses.ResponseInputItemFunctionCallOutputParam{
CallID: openai.String(call.CallID),
Output: responses.ResponseInputItemFunctionCallOutputOutputUnionParam{OfResponseFunctionCallOutputItemArray: observations},
},
})
}
params.Input = responses.ResponseNewParamsInputUnion{OfInputItemList: nextInput}
params.PreviousResponseID = openai.String(response.ID)
}
return nil
}Para ver un adaptador de cliente completo y el formato esperado de las salidas de texto e imagen, consulta Conectar tu servicio de ejecución. En esos ejemplos, tu aplicación proporciona la interfaz del servicio. OpenAI no aloja ese punto de acceso.
Conservar el estado y devolver observaciones
Mantén activa la sesión del navegador o del escritorio entre llamadas. Un espacio de nombres persistente de Python o JavaScript también puede conservar variables. Describe los objetos y las funciones auxiliares disponibles en la definición de la herramienta para que el modelo sepa qué puede usar.
Si se desconoce el estado de la interfaz de usuario, proporciona al modelo una captura de pantalla actual. Después de unas pocas acciones, devuelve otra captura para que pueda comprobar el resultado. Mantén las imágenes en memoria y usa detail: "original" para conservar la resolución. Si reduces la resolución de una captura, convierte las coordenadas del modelo al sistema de coordenadas del entorno antes de ejecutar las acciones. Consulta Capturas de pantalla y resolución.
La conversación de la API y el entorno de ejecución mantienen estados independientes. Conserva las llamadas a herramientas y sus salidas en la conversación, y mantén disponible el entorno correspondiente en tu aplicación. Continuar una respuesta no restaura la sesión del navegador, el estado de autenticación ni las variables del entorno de ejecución.
Usar la herramienta de computadora
Usa esta alternativa cuando tu integración espere acciones estructuradas en lugar de código generado.
Para probar esta opción, sigue los mismos pasos de configuración de la aplicación de ejemplo, selecciona el modo Native y ejecuta uno de los escenarios incluidos. Usa un modelo compatible con la herramienta de computadora.
El intercambio con la API consta de tres pasos: enviar una tarea, ejecutar las acciones devueltas y devolver una captura de pantalla. Los fragmentos de código de esta sección usan una página con un control Show filters y un campo de búsqueda. Adapta esa tarea a tu propia interfaz cuando integres la herramienta.
Para configurar el entorno e implementar los manejadores de acciones, consulta las recetas de integración.
Enviar la tarea
Habilita computer en el arreglo tools y describe el resultado que quieres obtener:
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-6.1-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)Ejecutar las acciones solicitadas
Cada computer_call contiene un arreglo ordenado de acciones llamado actions. Por ejemplo, esta llamada selecciona el campo de búsqueda y escribe penguin:
{
"output": [
{
"type": "computer_call",
"call_id": "call_002",
"actions": [
{ "type": "click", "button": "left", "x": 405, "y": 157 },
{ "type": "type", "text": "penguin" }
],
"status": "completed"
}
]
}Tu manejador de acciones convierte estas solicitudes en entradas para el navegador o el sistema operativo. Ejecuta las acciones permitidas en orden y luego captura la pantalla actualizada. El modelo puede solicitar click, double_click, drag, move, scroll, keypress, type, wait o screenshot.
La primera llamada puede contener únicamente una acción screenshot. En ese caso, captura la pantalla actual y devuelve la imagen sin cambiar la interfaz de usuario. Si la llamada tiene status: "completed", el modelo terminó de generarla. Tu aplicación aún debe ejecutarla.
Consulta los ejemplos de manejadores de acciones para ver cómo asignar teclas, definir trayectorias de arrastre y usar teclas modificadoras.
Devolver la captura de pantalla
Devuelve un computer_call_output cuyo call_id coincida con el de la llamada que procesaste. Usa previous_response_id para continuar la conversación con el modelo:
from openai import OpenAI
client = OpenAI()
def send_computer_screenshot(response, call_id, screenshot_base64):
return client.responses.create(
model="gpt-6.1-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",
},
}
],
)Las mismas indicaciones sobre las capturas de pantalla y el estado se aplican a este ciclo. Mantén el entorno disponible mientras usas previous_response_id para continuar la conversación con el modelo.
Continúa hasta que el modelo deje de devolver elementos computer_call. Revisa el resto de la salida para ver si contiene una respuesta, una solicitud de ayuda u otra llamada a una herramienta, y verifica el resultado en la aplicación. En este ejemplo, el panel Filters debe estar abierto y el campo de búsqueda debe contener penguin.
Consulta Repetir el ciclo de uso de la computadora para ver la estructura del ciclo y las funciones auxiliares que requiere para ejecutar acciones y tomar capturas de pantalla.
Ejecutar tareas de forma segura
El uso de la computadora puede afectar cuentas y datos reales. Aplica estos controles en tu aplicación y en el entorno de ejecución, y también en las instrucciones del modelo:
- Restringe el entorno. Usa un navegador o una máquina virtual en un entorno aislado, con una lista de sitios y acciones permitidos. Limita el acceso a lo necesario para la tarea.
- Trata el contenido de la pantalla como información no confiable. El texto de una página, de un documento o del resultado de una herramienta no puede otorgar permisos ni anular las instrucciones del usuario.
- Confirma las acciones que tengan consecuencias importantes. Asegúrate de que los usuarios mantengan el control de las compras, la transmisión de datos, los cambios destructivos y otras acciones difíciles de revertir. Ingresar información sensible en un formulario cuenta como transmisión de datos.
- Establece límites y verifica la ejecución. Define límites de pasos, tiempo o costo, permite cancelar la ejecución y comprueba el resultado real sin depender únicamente de la respuesta final del modelo.
Consulta la guía de confirmación y consentimiento para conocer los requisitos específicos de aprobación, ver cómo transferir el control a una persona y revisar ejemplos de prompts.
Próximos pasos
- Usa las recetas de integración para configurar el entorno, implementar manejadores de acciones, tomar capturas de pantalla y crear adaptadores para el servicio de ejecución.
- Sigue la guía de migración desde computer-use-preview cuando actualices una integración anterior.
- Explora la aplicación de ejemplo de CUA (AUC) para ver flujos de trabajo completos de navegador y de escritorio.