操作電腦

Gemini 的電腦使用工具可讓您建構瀏覽器、行動裝置和電腦控制代理,在圖形使用者介面 (GUI) 之間互動及自動執行工作。啟用電腦使用功能後,模型會透過螢幕截圖觀察畫面,並產生滑鼠點擊、捲動和鍵盤輸入等特定 UI 動作來執行操作。

Gemini 支援多項進階電腦使用功能:

  • 支援多種環境:為瀏覽器、行動裝置和電腦環境建構代理。
  • 透過意圖簡化動作:動作包含 intent 欄位,說明模型在每個步驟背後的推論。
  • 可設定的安全政策:使用內建政策類別和覆寫功能,微調安全行為。
  • 提示詞注入偵測:選擇加入螢幕截圖掃描功能,偵測隱藏的對抗性指令。

您可以運用電腦使用功能,建構能執行下列操作的代理:

  • 自動在網站和電腦應用程式中重複輸入資料或填寫表單。
  • 對網頁、行動裝置和電腦使用者流程執行自動化測試。
  • 瀏覽網站和應用程式,收集研究資料 (例如比較產品資訊、價格和評論)。
  • 在多個應用程式中執行多步驟動作序列,協助使用者。

本指南涵蓋以下內容:

與函式呼叫類似,您需要編寫用戶端應用程式程式碼,才能接收電腦使用函式呼叫並執行相應動作。

本指南假設您使用 Google Gen AI SDK for Python,且熟悉 Playwright API。

您可以在 GitHub 找到電腦使用參考實作。

支援的模型

下列模型支援電腦使用功能:

按一下即可展開支援的模型

電腦使用功能的運作方式

電腦使用功能不會生成文字回覆,而是判斷何時要採取特定 UI 動作 (例如點按滑鼠),並傳回執行這些動作所需的參數。您需要編寫用戶端應用程式程式碼,才能接收電腦使用 function_call 並執行對應動作。

電腦使用互動遵循代理迴圈程序:

  1. 向模型傳送要求

    • 在 API 要求中加入電腦使用功能 (以及任何其他工具,如有需要)。
    • 將提示傳送至模型,其中包含使用者的要求和代表 GUI 目前狀態的螢幕截圖。
  2. 接收模型回覆

    • 模型會分析使用者要求和螢幕截圖,並生成回覆,其中包含代表 UI 動作的建議 function_call (例如「點選座標 (x,y)」或「輸入『文字』」)。如要查看可與模型搭配使用的所有動作,請參閱「支援的動作」。
    • API 回應也可能包含內部安全系統的 safety_decision,該系統會檢查模型建議的操作。safety_decision 會將動作分類為:
      • 一般或允許:系統判定該動作安全無虞。這也可能表示沒有 safety_decision。
      • 需要確認:模型即將執行的動作可能有風險 (例如點選「接受 Cookie 橫幅」)。
  3. 執行收到的動作

    • 用戶端程式碼會收到 function_call 和任何隨附的 safety_decision。
    • 如果 safety_decision 指出一般或允許 (或沒有 safety_decision),用戶端程式碼可以在目標環境 (例如網路瀏覽器) 中執行指定的 function_call。
    • 如果 safety_decision 指出需要確認,應用程式必須先提示使用者確認,才能執行 function_call。如果使用者確認,請繼續執行動作。如果使用者拒絕,請勿執行動作。
  4. 擷取新環境狀態

    • 如果動作已執行,用戶端會擷取 GUI 和目前網址的新螢幕截圖,並以 function_response 的一部分傳回模型。
    • 如果動作遭到安全系統封鎖,或使用者拒絕確認,應用程式可能會向模型傳送不同形式的回饋,或結束互動。

系統會將新要求傳送至模型,並附上更新後的狀態。模型會使用新的螢幕截圖 (如有提供) 和持續進行的目標,建議下一個動作,並從步驟 2 開始重複執行。這個迴圈會持續執行,直到工作完成、發生錯誤或程序終止 (例如回應遭安全篩選器或使用者決定封鎖)。

下圖說明電腦使用功能的運作方式:

流程圖:顯示電腦使用互動循環。首先是「初始工作」,接著是「螢幕截圖 + 先前情境」。步驟 1:「向模型傳送要求」會將這項資料傳送至「模型」。步驟 2:「接收模型回覆」將動作傳遞至「電腦環境 (用戶端應用程式)」。步驟 3:
「執行收到的動作」會更新「電腦環境 (用戶端應用程式)」。步驟 4:「擷取新環境狀態」會將更新後的螢幕截圖和背景資訊,傳回迴圈的起點。

啟用「操作電腦」功能

如要啟用電腦使用功能,請確認應用程式使用支援的模型,並將電腦使用功能加入已啟用的工具清單:

Python

from google import genai
from google.genai import types
from google.genai.types import Content, Part

client = genai.Client(
    enterprise=True,
    project="PROJECT_ID",
    location="global",
)

# Add computer use to the list of tools
generate_content_config = types.GenerateContentConfig(
    tools=[
        types.Tool(
            computer_use=types.ComputerUse(
                environment=types.Environment.ENVIRONMENT_BROWSER,
            )
        ),
    ]
)

contents = [
    Content(
        role="user",
        parts=[
            Part(text="Go to google.com and search for 'weather in New York'"),
        ],
    )
]

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=contents,
    config=generate_content_config,
)
print(response)
      

Node.js

import { GoogleGenAI, Environment } from '@google/genai';

const ai = new GoogleGenAI({
  enterprise: true,
  project: 'PROJECT_ID',
  location: 'global',
});

const response = await ai.models.generateContent({
  model: 'gemini-3.8-flash',
  contents: "Go to google.com and search for 'weather in New York'",
  config: {
    tools: [
      {
        computerUse: {
          environment: Environment.ENVIRONMENT_BROWSER,
        },
      },
    ],
  },
});

console.log(response);
      

REST API

curl -X POST "https://aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-3.8-flash:generateContent" \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "Go to google.com and search for '\''weather in New York'\''"
          }
        ]
      }
    ],
    "tools": [
      {
        "computer_use": {
          "environment": "ENVIRONMENT_BROWSER"
        }
      }
    ]
  }'
      

設定執行環境

使用電腦使用工具建構前,請先完成下列設定:

  • 安全的執行環境:在沙箱虛擬機器 (VM) 或容器 (例如 Docker) 中執行代理,與主機系統隔離。
  • 用戶端動作處理常式:實作用戶端邏輯,執行滑鼠點擊、鍵盤輸入和螢幕截圖。

首先,請安裝 SDK 和瀏覽器依附元件,然後設定環境:

pip install --upgrade google-genai playwright termcolor
playwright install chromium

export GOOGLE_CLOUD_PROJECT="PROJECT_ID"
export GOOGLE_CLOUD_LOCATION="global"
export GOOGLE_GENAI_USE_ENTERPRISE=True

接著,使用明確的可視區域尺寸初始化 Playwright 瀏覽器執行個體,讓正規化座標 (0 至 1000) 能準確縮放:

from playwright.sync_api import sync_playwright

SCREEN_WIDTH = 1440
SCREEN_HEIGHT = 900

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False)

context = browser.new_context(
    viewport={"width": SCREEN_WIDTH, "height": SCREEN_HEIGHT}
)
page = context.new_page()
page.goto("https://www.google.com")

傳送要求

設定電腦使用工具後,請向模型傳送提示,其中包含使用者的目標和 GUI 的初始螢幕截圖。

您也可以視需要新增下列項目:

  • 排除的動作:如果支援的 UI 動作清單中,有任何您不希望模型執行的動作,請在 excluded_predefined_functions 中指定這些動作。
  • user-defined function:除了電腦使用功能外,您可能也想加入自訂 user-defined function。

下列程式碼範例會啟用電腦使用功能,並將要求傳送至模型:

Python

from google import genai
from google.genai import types
from google.genai.types import Content, Part

client = genai.Client()

# Specify predefined functions to exclude (optional)
excluded_functions = ["drag_and_drop"]

# Configuration for computer use with browser environment
generate_content_config = genai.types.GenerateContentConfig(
    tools=[
        # 1. Computer Use tool with browser environment
        types.Tool(
            computer_use=types.ComputerUse(
                environment=types.Environment.ENVIRONMENT_BROWSER,
                # Optional: Exclude specific predefined functions
                excluded_predefined_functions=excluded_functions
                )
              ),
        # 2. Optional: Custom user-defined functions (need to defined above)
        # types.Tool(
           # function_declarations=custom_functions
           #   )
    ],
)

# Create the content with user message
contents: list[Content] = [
    Content(
        role="user",
        parts=[
            Part(text="Search for highly rated smart fridges with touchscreen, 2 doors, around 25 cu ft, priced below 4000 dollars on Google Shopping. Create a bulleted list of the 3 cheapest options in the format of name, description, price in an easy-to-read layout."),
            # Optional: include a screenshot of the initial state
            # Part.from_bytes(
                 # data=screenshot_image_bytes,
                 # mime_type='image/png',
            # ),
        ],
    )
]

# Generate content with the configured settings
response = client.models.generate_content(
    model='gemini-3.8-flash',
    contents=contents,
    config=generate_content_config,
)

# Print the response output
print(response.text)
      

您也可以加入自訂的 user-defined function,擴充模型功能。請參閱「Gemini 3.5 Flash 或更新版本,以及行動裝置或電腦用途」,瞭解如何為行動裝置用途設定電腦使用,方法是新增 open_app、long_press_at 和 go_home 等動作,同時排除瀏覽器專屬動作。

接收回應

如果模型判斷需要 UI 動作或 user-defined function 才能完成工作,就會傳回一或多個 FunctionCalls。應用程式程式碼需要剖析這些動作、執行動作並收集結果。電腦使用功能支援平行函式呼叫,也就是說,模型可以在單一回合中傳回多個獨立動作。

如果是 Gemini 3.5 Flash 和後續模型,每項動作都會包含 intent 引數,說明模型在該步驟背後的推論:

{
  "content": {
    "parts": [
      {
        "function_call": {
          "name": "type",
          "args": {
            "x": 450,
            "y": 320,
            "text": "smart fridge touchscreen 2 doors 25 cu ft under $4000",
            "press_enter": true,
            "intent": "Type the search query into the Google search box and submit."
          }
        }
      }
    ]
  }
}

視動作而定,API 回應也可能在函式呼叫引數中傳回 safety_decision:

{
  "content": {
    "parts": [
      {
        "function_call": {
          "name": "click",
          "args": {
            "x": 60,
            "y": 100,
            "intent": "Click the 'I'm not a robot' verification checkbox.",
            "safety_decision": {
              "explanation": "I have encountered a CAPTCHA challenge that requires interaction. I need you to complete the challenge by clicking the 'I'm not a robot' checkbox and any subsequent verification steps.",
              "decision": "require_confirmation"
            }
          }
        }
      }
    ]
  }
}

執行收到的動作

收到回應後,剖析 function_call,將座標從正規化的 0-1000 網格縮放至實際可視區域像素尺寸,然後執行動作:

import time
from typing import Any, Dict, List, Tuple
import termcolor


def denormalize_x(x: int, screen_width: int) -> int:
    """Convert normalized x coordinate (0-1000) to actual pixel coordinate."""
    return int(x / 1000 * screen_width)


def denormalize_y(y: int, screen_height: int) -> int:
    """Convert normalized y coordinate (0-1000) to actual pixel coordinate."""
    return int(y / 1000 * screen_height)


def get_safety_confirmation(safety_decision: Dict[str, Any]) -> str:
    """Prompt user for confirmation when safety check is triggered."""
    termcolor.cprint("Safety service requires explicit confirmation!", color="red")
    print(safety_decision.get("explanation", ""))

    decision = ""
    while decision.lower() not in ("y", "n", "ye", "yes", "no"):
        decision = input("Do you wish to proceed? [Y]es/[N]o\n")

    if decision.lower() in ("n", "no"):
        return "TERMINATE"
    return "CONTINUE"


def execute_function_calls(
    response, page, screen_width: int, screen_height: int
) -> List[Tuple[str, Dict[str, Any]]]:
    """Extract and execute modern and legacy function calls from Gemini response."""
    candidate = response.candidates[0]
    function_calls = []
    thoughts = []

    for part in candidate.content.parts:
        if hasattr(part, "function_call") and part.function_call:
            function_calls.append(part.function_call)
        elif hasattr(part, "text") and part.text:
            thoughts.append(part.text)

    if thoughts:
        print(f"Model Reasoning: {' '.join(thoughts)}")

    results: List[Tuple[str, Dict[str, Any]]] = []
    for function_call in function_calls:
        fname = function_call.name
        args = function_call.args or {}
        action_result: Dict[str, Any] = {}

        print(f" -> Executing: {fname} (Intent: {args.get('intent', 'N/A')})")

        # Check for safety decision before executing
        if "safety_decision" in args:
            decision = get_safety_confirmation(args["safety_decision"])
            if decision == "TERMINATE":
                print("Terminating agent loop")
                break
            action_result["safety_acknowledgement"] = "true"

        try:
            if fname in ("open_web_browser", "open_app", "take_screenshot"):
                pass

            elif fname in (
                "click",
                "click_at",
                "double_click",
                "triple_click",
                "middle_click",
                "right_click",
                "mouse_down",
                "mouse_up",
                "move",
                "hover_at",
            ):
                actual_x = denormalize_x(args["x"], screen_width)
                actual_y = denormalize_y(args["y"], screen_height)

                if fname in ("click", "click_at"):
                    page.mouse.click(actual_x, actual_y)
                elif fname == "double_click":
                    page.mouse.dblclick(actual_x, actual_y)
                elif fname == "triple_click":
                    page.mouse.click(actual_x, actual_y, click_count=3)
                elif fname == "middle_click":
                    page.mouse.click(actual_x, actual_y, button="middle")
                elif fname == "right_click":
                    page.mouse.click(actual_x, actual_y, button="right")
                elif fname == "mouse_down":
                    page.mouse.move(actual_x, actual_y)
                    page.mouse.down()
                elif fname == "mouse_up":
                    page.mouse.move(actual_x, actual_y)
                    page.mouse.up()
                elif fname in ("move", "hover_at"):
                    page.mouse.move(actual_x, actual_y)

            elif fname in ("type", "type_text_at"):
                actual_x = denormalize_x(args["x"], screen_width) if "x" in args else None
                actual_y = denormalize_y(args["y"], screen_height) if "y" in args else None
                text = args["text"]
                press_enter = args.get("press_enter", False)
                clear_before_typing = args.get("clear_before_typing", True)

                if actual_x is not None and actual_y is not None:
                    page.mouse.click(actual_x, actual_y)
                    time.sleep(0.1)

                if clear_before_typing:
                    page.keyboard.press("ControlOrMeta+A")
                    page.keyboard.press("Backspace")

                page.keyboard.type(text)
                if press_enter:
                    page.keyboard.press("Enter")

            elif fname in ("scroll", "scroll_at", "scroll_document"):
                if "x" in args and "y" in args:
                    page.mouse.move(denormalize_x(args["x"], screen_width), denormalize_y(args["y"], screen_height))
                direction = args.get("direction", "down")
                magnitude = args.get("magnitude_in_pixels", args.get("magnitude", 300))
                dx, dy = 0, 0
                if direction == "down":
                    dy = magnitude
                elif direction == "up":
                    dy = -magnitude
                elif direction == "right":
                    dx = magnitude
                elif direction == "left":
                    dx = -magnitude
                page.mouse.wheel(dx, dy)

            elif fname == "drag_and_drop":
                start_x = denormalize_x(args.get("start_x", args.get("x", 0)), screen_width)
                start_y = denormalize_y(args.get("start_y", args.get("y", 0)), screen_height)
                end_x = denormalize_x(args.get("end_x", args.get("destination_x", 0)), screen_width)
                end_y = denormalize_y(args.get("end_y", args.get("destination_y", 0)), screen_height)
                page.mouse.move(start_x, start_y)
                page.mouse.down()
                page.mouse.move(end_x, end_y)
                page.mouse.up()

            elif fname == "press_key":
                page.keyboard.press(args["key"])
            elif fname == "key_down":
                page.keyboard.down(args["key"])
            elif fname == "key_up":
                page.keyboard.up(args["key"])
            elif fname == "hotkey":
                page.keyboard.press("+".join(args.get("keys", [])))
            elif fname == "key_combination":
                page.keyboard.press(args["keys"])
            elif fname == "navigate":
                page.goto(args["url"])
            elif fname == "search":
                page.goto("https://www.google.com")
            elif fname == "go_back":
                page.go_back()
            elif fname == "go_forward":
                page.go_forward()
            elif fname in ("wait", "wait_5_seconds"):
                time.sleep(5 if fname == "wait_5_seconds" else args.get("seconds", 1))
            else:
                action_result["warning"] = f"unhandled_function: {fname}"

            page.wait_for_load_state(timeout=5000)
            time.sleep(1)

        except Exception as e:
            print(f"Error executing {fname}: {e}")
            action_result["error"] = str(e)

        results.append((fname, action_result))

    return results

如果傳回的 safety_decision 為 require_confirmation,您必須先要求使用者確認,才能繼續執行動作。根據服務條款,您不得略過真人確認要求。

擷取新狀態

執行動作後,將每個動作結果和更新後的螢幕截圖封裝成 FunctionResponse,傳回給模型:

from google.genai import types
from google.genai.types import Content, FunctionResponse, Part


def get_function_responses(
    page, results: List[Tuple[str, Dict[str, Any]]]
) -> Content:
    """Capture screenshot and URL and package them as FunctionResponses."""
    screenshot = page.screenshot(type="png")
    current_url = page.url
    function_response_parts = []

    for name, action_result in results:
        function_response_parts.append(
            Part(
                function_response=FunctionResponse(
                    name=name,
                    response={
                        "url": current_url,
                        **action_result,
                    },
                    parts=[
                        types.FunctionResponsePart(
                            inline_data=types.FunctionResponseBlob(
                                mime_type="image/png",
                                data=screenshot,
                            )
                        )
                    ],
                )
            )
        )

    return Content(
        role="user",
        parts=function_response_parts,
    )

建構代理迴圈

將這些步驟結合成端對端迴圈,在模型和執行環境之間持續疊代:

Python

from google import genai
from google.genai import types
from google.genai.types import Content, Part
from playwright.sync_api import sync_playwright

def has_function_calls(response) -> bool:
    """Check if model response contains any function calls."""
    candidate = response.candidates[0]
    return any(
        hasattr(part, "function_call") and part.function_call
        for part in candidate.content.parts
    )

def main():
    client = genai.Client(
        enterprise=True,
        project="PROJECT_ID",
        location="global",
    )

    generate_content_config = types.GenerateContentConfig(
        tools=[
            types.Tool(
                computer_use=types.ComputerUse(
                    environment=types.Environment.ENVIRONMENT_BROWSER,
                    enable_prompt_injection_detection=True,
                )
            )
        ],
    )

    screen_width, screen_height = 1440, 900

    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        context = browser.new_context(
            viewport={"width": screen_width, "height": screen_height}
        )
        page = context.new_page()
        page.goto("https://www.google.com")

        initial_screenshot = page.screenshot(type="png")
        contents: list[Content] = [
            Content(
                role="user",
                parts=[
                    Part(text="Search for flights from San Francisco to Honolulu departing June 30 and returning July 6."),
                    Part.from_bytes(data=initial_screenshot, mime_type="image/png"),
                ],
            )
        ]

        # Agent loop: iterate until model provides a final text response
        for iteration in range(10):
            print(f"\n--- Iteration {iteration + 1} ---")

            response = client.models.generate_content(
                model="gemini-3.8-flash",
                contents=contents,
                config=generate_content_config,
            )

            contents.append(response.candidates[0].content)

            if not has_function_calls(response):
                print(f"FINAL RESPONSE:\n{response.text}")
                break

            results = execute_function_calls(response, page, screen_width, screen_height)
            if not results:
                break

            user_feedback_content = get_function_responses(page, results)
            contents.append(user_feedback_content)

        browser.close()

if __name__ == "__main__":
    main()
      

Gemini 3.5 Flash 以上版本,以及行動裝置或電腦用途

電腦使用功能支援設定行動裝置 (ENVIRONMENT_MOBILE)、電腦 (ENVIRONMENT_DESKTOP) 或瀏覽器 (ENVIRONMENT_BROWSER) 環境。預設值為 ENVIRONMENT_BROWSER。

下列範例說明如何設定執行環境,以便使用 Gemini 3.5 Flash 以上版本執行電腦操作:

REST API

使用任何要求資料之前,請先修改下列項目的值:

  • PROJECT_ID:專案 ID。

HTTP 方法和網址:

POST https://aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-3.5-flash:generateContent

JSON 要求主體:

{
  "contents": [
    {
      "role": "user",
      "parts": {
        "text": "find me a flight from SF to Hawaii on Jun 30th, coming back on Jul 6th. start by navigating directly to flights.google.com"
      }
    }
  ],
  "generation_config": {
    "candidateCount": 1
  },
  "tools": [
    {
      "computer_use": {
        "environment": "ENVIRONMENT_BROWSER"
      }
    }
  ]
}

請展開以下其中一個選項,以傳送要求:

您應該會收到執行成功的狀態碼 (2xx) 和空白回應。

Python

以下範例需要 python-genai 2.7.0 以上版本。

from google import genai
from google.genai.types import (
    Part,
    GenerateContentConfig,
    Content,
    Tool,
    ComputerUse,
    Environment,
    ThinkingConfig,
)
client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.6-flash",
    contents=[
        Content(
            role="user",
            parts=[
                Part(text="find me a flight from SF to Hawaii on Jun 30th, coming back on Jul 6th"),
            ],
        )
    ],
    config=GenerateContentConfig(
        temperature=1,
        top_p=0.95,
        top_k=40,
        max_output_tokens=8192,
        tools=[
            Tool(
                computer_use=ComputerUse(
                    environment=Environment.ENVIRONMENT_MOBILE
                ),
            ),
        ],
        thinking_config=ThinkingConfig(
            include_thoughts=True
        ),
    )
)

自訂 user-defined function

您可以將 computer_use 與自訂 user-defined function (function_declarations) 結合,擴充模型功能。舉例來說,在人工介入迴路 (HITL) 情境中,您可以使用 excluded_predefined_functions 排除特定預先定義的動作,並註冊自訂 yield_to_user 函式,讓代理在遇到雙重驗證提示或不明確的畫面時,將控制權交還給真人:

Python

from google import genai
from google.genai import types
from google.genai.types import Content, Part

client = genai.Client()

def yield_to_user(reason: str) -> dict[str, str]:
    """Yields control back to the user for assistance or verification when an automated action is unsafe or ambiguous.

    Args:
        reason: The reason why the agent is yielding control to the human.
    """
    return {"status": "yielded", "reason": reason}

generate_content_config = types.GenerateContentConfig(
    tools=[
        types.Tool(
            computer_use=types.ComputerUse(
                environment=types.Environment.ENVIRONMENT_BROWSER,
                excluded_predefined_functions=["drag_and_drop"],
            )
        ),
        types.Tool(
            function_declarations=[
                types.FunctionDeclaration.from_callable(
                    client=client, callable=yield_to_user
                )
            ]
        ),
    ]
)

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=[
        Content(
            role="user",
            parts=[
                Part(
                    text="Click the submit button. If you need a second-factor authentication code, ask me."
                ),
            ],
        )
    ],
    config=generate_content_config,
)
print(response)
      

支援的動作

電腦使用工具可讓模型使用 FunctionCall 要求下列動作。用戶端程式碼必須實作這些動作的執行邏輯。如需範例,請參閱參考實作。下表列出瀏覽器環境支援的操作。Gemini 3 Flash 和 Gemini 3.5 Flash 或更新版本模型,有不同的 FunctionCall 名稱組合。

Gemini 3.5 Flash 以上版本

Gemini 3.5 Flash:視選取的環境而定,您可以使用不同的函式呼叫組合:

瀏覽器環境

指令名稱 說明 引數 (在函式呼叫中)
click 在指定座標上按一下滑鼠左鍵。 y:int (0-999)
x:int (0-999)
intent:str
double_click 在指定座標按兩下。 y:int (0-999)
x:int (0-999)
intent:str
triple_click 在指定座標上按三下。 y:int (0-999)
x:int (0-999)
intent:str
middle_click 在指定座標按下滑鼠中鍵。 y:int (0-999)
x:int (0-999)
intent:str
right_click 在指定座標按一下滑鼠右鍵。 y:int (0-999)
x:int (0-999)
intent:str
mouse_down 在指定座標按住滑鼠按鈕。 y:int (0-999)
x:int (0-999)
intent:str
mouse_up 在指定座標放開滑鼠按鈕。 y:int (0-999)
x:int (0-999)
intent:str
move 將游標移至指定位置。 y:int (0-999)
x:int (0-999)
intent:str
type 輸入文字 (可選擇先點選 x、y)。 y:int (0-999,選填)
x:int (0-999,選填)
text:str
press_enter:bool (選填,預設為 false)
intent:str
drag_and_drop 將項目從 (start_x, start_y) 拖曳到 (end_x, end_y)。 start_y:int (0-999)
start_x:int (0-999)
end_y:int (0-999)
end_x:int (0-999)
intent:str
wait 等待指定的秒數。 seconds:int (選用,預設為 1)
intent:str
press_key 按下指定按鍵後放開。 key: str
intent: str
key_down 按住指定按鍵。 key: str
intent: str
key_up 放開指定按鍵。 key: str
intent: str
hotkey 按下指定的按鍵組合。 keys:List[str]
intent:str
take_screenshot 傳回目前畫面的螢幕截圖。 intent:str
scroll 在座標處向上、向下、向左或向右捲動,捲動距離以像素為單位。 y:int (0-999)
x:int (0-999)
direction:str ("up", "down", "left", "right")
magnitude_in_pixels:int (0-999,選用,預設值為 300)
intent:str
open_web_browser 開啟網路瀏覽器。 intent:str
navigate 直接將瀏覽器導向指定網址。 url: str
intent: str
go_back 返回瀏覽器記錄中的上一個網頁。 intent:str
go_forward 前往瀏覽器記錄中的下一個網頁。 intent:str

行動環境

指令名稱 說明 引數 (在函式呼叫中)
open_app 依名稱開啟應用程式。 intent: str
click 在座標處按一下滑鼠左鍵。 y:int (0-999)
x:int (0-999)
intent:str
list_apps 列出裝置上可用的應用程式,並傳回其名稱和套件名稱。 intent:str
wait 等待指定的秒數。 intent:str
seconds:int(選用,預設為 1)
go_back 返回瀏覽器記錄中的上一個網頁。 intent:str
type 輸入文字。 text: str
intent: str
press_enter: bool(選用,預設為 false)
drag_and_drop 將項目從 start_y 和 start_x 拖曳至 end_y 和 end_x start_y:int (0-999)
start_x:int (0-999)
end_y:int (0-999)
end_x:int (0-999)
intent:str
long_press 在螢幕上指定的 y (0-999)、x (0-999) 座標執行長按動作。 y:int (0-999)
x:int (0-999)
intent:str
seconds:int (選用,預設為 2)
press_key 按下指定按鍵後放開。 key: str
intent: str
take_screenshot 傳回目前畫面的螢幕截圖。 intent:str

桌面環境

指令名稱 說明 引數 (在函式呼叫中)
click 在座標處按一下滑鼠左鍵。 y:int (0-999)
x:int (0-999)
intent:str
double_click 在座標處按兩下。 y:int (0-999)
x:int (0-999)
intent:str
triple_click 在座標上連按三下。 y:int (0-999)
x:int (0-999)
intent:str
middle_click 在座標處按下滑鼠中鍵。 y:int (0-999)
x:int (0-999)
intent:str
right_click 在座標上按一下滑鼠右鍵。 y:int (0-999)
x:int (0-999)
intent:str
mouse_down 在指定座標按住滑鼠按鈕。 y:int (0-999)
x:int (0-999)
intent:str
mouse_up 在指定座標放開滑鼠按鈕。 y:int (0-999)
x:int (0-999)
intent:str
move 將游標移至指定位置。 y:int (0-999)
x:int (0-999)
intent:str
type 輸入文字。 text:str
intent:str
press_enter:bool(選用,預設為 false)
drag_and_drop 將項目從 start_y 和 start_x 拖曳到 end_y 和 end_x。 start_y:int (0-999)
start_x:int (0-999)
end_y:int (0-999)
end_x:int (0-999)
intent:str
wait 等待指定秒數。 intent:str
seconds:int(選用,預設為 1)
press_key 按下指定按鍵後放開。 key: str
intent: str
key_down 按住指定按鍵。 key: str
intent: str
key_up 放開指定按鍵。 key: str
intent: str
hotkey 按下指定的按鍵組合。 keys:List[str]
intent:str
take_screenshot 傳回目前畫面的螢幕截圖。 intent:str
scroll 在座標處向上、向下、向左或向右捲動,捲動距離以像素為單位。 y:int (0-999)
x:int (0-999)
direction:str ("up"、"down"、"left"、"right")
intent:str
magnitude_in_pixels:int (0-999,選用,預設為 300)

Gemini 3 Flash

指令名稱 說明 引數 (在函式呼叫中) 函式呼叫範例
open_web_browser 開啟網路瀏覽器。 無 {"name": "open_web_browser", "args": {}}
wait_5_seconds 暫停執行 5 秒,讓動態內容載入或動畫完成。 無 {"name": "wait_5_seconds", "args": {}}
go_back 前往瀏覽器記錄中的上一頁。 無 {"name": "go_back", "args": {}}
go_forward 前往瀏覽器記錄中的下一頁。 無 {"name": "go_forward", "args": {}}
search 前往預設搜尋引擎的首頁 (例如 Google)。適合用於開始新的搜尋工作。 無 {"name": "search", "args": {}}
navigate 直接將瀏覽器導向指定網址。 url:str {"name": "navigate", "args": {"url": "https://www.wikipedia.org"}}
click_at 點選網頁上的特定座標。x 和 y 值是以 1000x1000 格線為基準,並會根據螢幕尺寸調整。 y:int (0-999),x:int (0-999) {"name": "click_at", "args": {"y": 300, "x": 500}}
hover_at 521963309 將滑鼠懸停在網頁上的特定座標。適合用來顯示子選單。x 和 y 是以 1000x1000 格線為基準。 y:int (0-999) x:int (0-999) {"name": "hover_at", "args": {"y": 150, "x": 250}}
type_text_at 在特定座標輸入文字,預設為先清除欄位,並在輸入後按下 ENTER 鍵,但可以停用這些功能。x 和 y 是以 1000x1000 格線為基礎。 y:int (0-999)、x:int (0-999)、text:str、press_enter:bool (選用,預設為 True)、clear_before_typing:bool (選用,預設為 True) {"name": "type_text_at", "args": {"y": 250, "x": 400, "text": "search query", "press_enter": false}}
key_combination 按下鍵盤按鍵或組合鍵,例如「Control+C」或「Enter」。適合用於觸發動作 (例如按下「Enter」鍵提交表單) 或剪貼簿操作。 keys:str (例如「enter」、「control+c」。如需允許金鑰的完整清單,請參閱 API 參考資料 {"name": "key_combination", "args": {"keys": "Control+A"}}
scroll_document 將整個網頁「向上」、「向下」、「向左」或「向右」捲動。 direction:str (「up」、「down」、「left」或「right」) {"name": "scroll_document", "args": {"direction": "down"}}
scroll_at 在座標 (x, y) 處,以特定幅度朝指定方向捲動特定元素或區域。座標和大小 (預設為 800) 是以 1000x1000 格線為基準。 y:int (0-999),x:int (0-999),direction:str (「up」、「down」、「left」、「right」),magnitude:int (0-999,選用,預設為 800) {"name": "scroll_at", "args": {"y": 500, "x": 500, "direction": "down", "magnitude": 400}}
drag_and_drop 從起始座標 (x, y) 拖曳元素,並將其拖曳至目的地座標 (destination_x, destination_y)。所有座標都是以 1000x1000 的格線為基準。 y:int (0-999),x:int (0-999),destination_y:int (0-999),destination_x:int (0-999) {"name": "drag_and_drop", "args": {"y": 100, "x": 100, "destination_y": 500, "destination_x": 500}}

安全與安全性

本節說明電腦使用工具採取的防護措施,旨在提升使用者控管能力和安全性。此外,也說明瞭最佳做法,可降低工具可能帶來的新風險。

確認安全決策

視動作而定,模型的回覆可能包含內部安全系統的 safety_decision。這項決策會驗證工具建議的安全措施。

{
  "content": {
    "parts": [
      {
        "text": "I have evaluated step 2. It seems Google detected unusual traffic and is asking me to verify I'm not a robot. I need to click the 'I'm not a robot' checkbox located near the top left (y=98, x=95)."
      },
      {
        "function_call": {
          "name": "click_at",
          "args": {
            "x": 60,
            "y": 100,
            "safety_decision": {
              "explanation": "I have encountered a CAPTCHA challenge that requires interaction. I need you to complete the challenge by clicking the 'I'm not a robot' checkbox and any subsequent verification steps.",
              "decision": "require_confirmation"
            }
          }
        }
      }
    ]
  }
}

如果 safety_decision 為 require_confirmation,您必須先要求使用者確認,才能繼續執行動作。

以下程式碼範例會在執行動作前,提示使用者確認。如果使用者未確認動作,迴圈就會終止。如果使用者確認動作,系統就會執行動作,並將 safety_acknowledgement 欄位標示為 True。

import termcolor

def get_safety_confirmation(safety_decision):
    """Prompt user for confirmation when safety check is triggered."""
    termcolor.cprint("Safety service requires explicit confirmation!", color="red")
    print(safety_decision["explanation"])

    decision = ""
    while decision.lower() not in ("y", "n", "ye", "yes", "no"):
        decision = input("Do you wish to proceed? [Y]es/[N]o\n")

    if decision.lower() in ("n", "no"):
        return "TERMINATE"
    return "CONTINUE"

def execute_function_calls(response, page, screen_width: int, screen_height: int):

    # ... Extract function calls from response ...

    for function_call in function_calls:
        extra_fr_fields = {}

        # Check for safety decision
        if 'safety_decision' in function_call.args:
            decision = get_safety_confirmation(function_call.args['safety_decision'])
            if decision == "TERMINATE":
                print("Terminating agent loop")
                break
            extra_fr_fields["safety_acknowledgement"] = "true" # Safety acknowledgement

        # ... Execute function call and append to results ...

如果使用者確認,您必須在 FunctionResponse 中加入安全聲明。

function_response_parts.append(
    FunctionResponse(
        name=name,
        response={"url": current_url,
                  **extra_fr_fields},  # Include safety acknowledgement
        parts=[
            types.FunctionResponsePart(
                inline_data=types.FunctionResponseBlob(
                    mime_type="image/png", data=screenshot
                )
             )
           ]
         )
       )

提示插入偵測

Gemini 3.5 Flash 以上版本的電腦使用功能,支援進階安全機制,可偵測提示詞注入式攻擊。啟用後,這項功能會檢查隨附的螢幕截圖是否可能引發提示詞注入式攻擊。您可以在電腦使用設定中設定這項功能。預設為 false。

下列範例示範如何啟用電腦使用設定,以啟用提示詞注入偵測功能:

REST API

使用任何要求資料之前,請先修改下列項目的值:

  • PROJECT_ID:專案 ID。

HTTP 方法和網址:

POST https://aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-3.5-flash:generateContent

JSON 要求主體:

{
  "contents": [
    {
      "role": "user",
      "parts": {
        "text": "find me a flight from SF to Hawaii on Jun 30th, coming back on Jul 6th. start by navigating directly to flights.google.com"
      }
    }
  ],
  "generation_config": {
    "candidateCount": 1
  },
  "tools": [
    {
      "computer_use": {
        "environment": "ENVIRONMENT_BROWSER",
        "enable_prompt_injection_detection": true
      }
    }
  ]
}

請展開以下其中一個選項,以傳送要求:

您應該會收到執行成功的狀態碼 (2xx) 和空白回應。

Python

以下範例需要 python-genai 2.7.0 以上版本。

from google import genai
from google.genai.types import (
    Part,
    GenerateContentConfig,
    Content,
    Tool,
    ComputerUse,
    Environment,
    ThinkingConfig,
)
client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.6-flash",
    contents=[
        Content(
            role="user",
            parts=[
                Part(text="find me a flight from SF to Hawaii on Jun 30th, coming back on Jul 6th"),
            ],
        )
    ],
    config=GenerateContentConfig(
        temperature=1,
        top_p=0.95,
        top_k=40,
        max_output_tokens=8192,
        tools=[
            Tool(
                computer_use=ComputerUse(
                    environment=Environment.ENVIRONMENT_MOBILE,
                    enable_prompt_injection_detection=True
                ),
            ),
        ],
        thinking_config=ThinkingConfig(
            include_thoughts=True
        ),
    )
)

安全性最佳做法

開發人員應留意電腦使用功能帶來的風險:

  • 不可信的內容和詐騙:模型在嘗試達成使用者目標時,可能會依賴不可信的資訊來源和畫面上的指示。
  • 偶爾會執行非預期動作:模型可能會誤解使用者的目標或網頁內容,導致執行錯誤動作,例如點選錯誤按鈕或填寫錯誤表單。
  • 違反政策:API 功能可能用於違反 Google 條款和政策的活動,例如繞過 CAPTCHA 或破壞系統完整性。

為因應這些風險,請採取下列安全措施和最佳做法:

  1. 人工介入迴路 (HITL):
    • 實作使用者確認:如果安全回應指出 require_confirmation,您必須在執行前實作使用者確認。
    • 提供自訂安全指令:除了內建的使用者確認檢查外,開發人員也可以選擇新增自訂系統指令,強制執行自己的安全政策,例如封鎖特定模型動作,或要求使用者確認後,模型才能執行特定高風險且不可逆的動作。

    按一下查看自訂安全系統指令範例

    ## **RULE 1: Seek User Confirmation (USER_CONFIRMATION)**
    
    This is your first and most important check. If the next required action falls
    into any of the following categories, you MUST stop immediately, and seek the
    user's explicit permission.
    
    **USER_CONFIRMATION Categories:**
    *   **Consent and Agreements:** Terms of Service, Privacy Policies, Cookie banners.
    *   **Robot Detection:** CAPTCHAs of any kind.
    *   **Financial Transactions:** Completing purchases or moving funds.
    *   **Sending Communications:** Emails, forum posts, or chat messages.
    *   **Accessing/Modifying Sensitive Information:** Healthcare, financial, or ID records.
    *   **User Data Management:** Downloading files, transferring user data.
    *   **Browser Data Usage:** Chrome history, bookmarks, autofill passwords.
    *   **Security and Identity:** Logging into accounts or impersonation.
    
    ## **RULE 2: Default Behavior (ACTUATE)**
    If an action does NOT fall under USER_CONFIRMATION, proactively perform all
    necessary steps to move the user's request forward.
        
  2. 安全執行環境:在安全的沙箱環境中執行代理,限制其潛在影響 (例如沙箱虛擬機器 (VM)、容器 (例如 Docker),或權限有限的專用瀏覽器設定檔)。
  3. 輸入內容清理:清理提示詞中所有使用者生成的文字,降低非預期指令或提示詞注入的風險。這項安全防護機制很有幫助,但無法取代安全執行環境。
  4. 內容護欄:使用護欄和內容安全 API (例如 Model Armor),評估使用者輸入內容、工具輸入和輸出內容,以及代理的回覆是否適當,並偵測提示詞注入和越獄行為。
  5. 許可清單和封鎖清單:實施篩選機制,控管模型可瀏覽的位置和可執行的操作。建議先建立禁止網站的封鎖清單,再建立更嚴格的許可清單,進一步提升安全性。
  6. 觀測能力和記錄:保留詳細記錄,用於偵錯、稽核和事件應變。用戶端應記錄提示、螢幕截圖、模型建議動作 (function_call)、安全回應,以及用戶端最終執行的所有動作。
  7. 環境管理:確保 GUI 環境一致。非預期的彈出式視窗、系統通知或版面配置移位,都可能使模型混淆。盡可能從已知、乾淨的狀態開始執行每項新工作。

人工介入迴路 (HITL) 確認

人工介入迴路 (HITL) 確認是指在執行模型建議的動作前,先徵求使用者確認。如果模型因安全考量而無法執行動作,就必須進行這項程序。

Gemini 的電腦使用工具提供下列機制,可控制 HITL 確認:

覆寫 HITL 確認

您可以覆寫下列預設 HITL 確認:

  • FINANCIAL_TRANSACTIONS:完成金融交易的最後一個步驟 (例如付款、轉帳付款、匯票、開始或修改訂閱,或完成預訂)。
  • SENSITIVE_DATA_MODIFICATION:修改私密資訊,例如醫療照護、財務或政府記錄。
  • COMMUNICATION_TOOL:存取或使用通訊工具,傳送、分享、發布或以其他方式傳輸通訊內容。
  • ACCOUNT_CREATION:與註冊或申請流程互動,建立或佈建新的使用者或服務帳戶。
  • DATA_MODIFICATION:修改、管理、共用、儲存、提交或刪除瀏覽器資料或檔案。
  • USER_CONSENT_MANAGEMENT:與使用者同意聲明對話方塊或橫幅互動,做出決定。
  • LEGAL_TERMS_AND_AGREEMENTS:與具有法律約束力的協議對話方塊互動,例如接受服務條款、隱私權政策對話方塊或法律聲明。

如要覆寫任何或所有 HITL 確認,請在電腦使用設定的 disabled_safety_policies 欄位中列出這些確認:

Python

GenerateContent API

generate_content_config = genai.types.GenerateContentConfig(
    tools=[
        types.Tool(
            computer_use=types.ComputerUse(                
                environment=types.Environment.ENVIRONMENT_MOBILE,
                disabled_safety_policies=[
                    types.SafetyPolicy.FINANCIAL_TRANSACTIONS,
                    types.SafetyPolicy.COMMUNICATION_TOOL,
                ]
            )
        ),
    ],
)

contents = [
    types.Content(
        role="user",
        parts=[
            types.Part(text="Open the Maps app and find the nearest coffee shop."),
        ],
    )
]

response = client.models.generate_content(
    model='gemini-3.5-flash',
    contents=contents,
    config=generate_content_config,
)

Interactions API

from google import genai
client = genai.Client()

interaction = client.interactions.create(
    model='gemini-3.5-flash',
    input='Open the Maps app and find the nearest coffee shop.',
    tools=[
        {
            'type': 'computer_use',
            'environment': 'mobile',
            'disabled_safety_policies': [
                'financial_transactions',
                'communication_tool',
            ],
        }
    ]
)

REST

GenerateContent API

{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "Open the Maps app and find the nearest coffee shop."
        }
      ]
    }
  ],
  "tools": [
    {
      "computer_use": {
        "environment": "ENVIRONMENT_MOBILE",
        "disabled_safety_policies" : [
          "FINANCIAL_TRANSACTIONS",
          "COMMUNICATION_TOOL"
         ]
      }
    }
  ]
}

Interactions API

{
  "model": "gemini-3.5-flash",
  "input": "Open the Maps app and find the nearest coffee shop.",
  "tools": [
    {
      "type": "computer_use",
      "environment": "mobile",
      "disabled_safety_policies": [
        "financial_transactions",
        "communication_tool"
      ]
    }
  ]
}

建立組織政策

如果您是組織管理員,可以使用組織政策服務建立組織層級政策,防止個別開發人員停用部分或所有 HITL 確認。這項政策會取代任何開發人員層級的設定。

您可以使用 Google Cloud 控制台或 Google Cloud CLI 建立政策。限制 ID 為 vertexai.configurableComputerUseToolSafetyPolicies。組織政策變更最多可能需要一小時才會生效。

如要進一步瞭解如何建立及管理組織政策,請參閱「建立組織政策」。

定價

電腦使用功能的費率與 Gemini 相同,且使用相同的 SKU。如要拆分電腦使用費用,請使用自訂中繼資料標籤。如要進一步瞭解如何使用自訂中繼資料標籤監控費用,請參閱「自訂中繼資料標籤」。