컴퓨터 사용 모델 및 도구

Gemini 2.5 컴퓨터 사용 모델과 도구를 사용하면 애플리케이션이 브라우저에서 작업을 상호작용하고 자동화할 수 있습니다. 스크린샷을 사용하여 컴퓨터 사용 모델은 컴퓨터 화면에 관한 정보를 추론하고 마우스 클릭 및 키보드 입력과 같은 특정 UI 작업을 생성하여 작업을 실행할 수 있습니다. 함수 호출과 마찬가지로 컴퓨터 사용 모델과 도구 함수 호출을 수신하고 해당 작업을 실행하는 클라이언트 측 애플리케이션 코드를 작성해야 합니다.

컴퓨터 사용 모델과 도구를 사용하면 다음 작업을 할 수 있는 에이전트를 빌드할 수 있습니다.

  • 웹사이트에서 반복적인 데이터 입력 또는 양식 작성을 자동화합니다.
  • 웹사이트를 탐색하여 정보를 수집합니다.
  • 웹 애플리케이션에서 일련의 작업을 실행하여 사용자를 지원합니다.

이 가이드에서는 다음을 다룹니다.

이 가이드에서는 Python용 생성형 AI SDK를 사용하고 Playwright API에 익숙하다고 가정합니다.

이 미리보기에서는 다른 SDK 언어나 Google Cloud 콘솔에서 컴퓨터 사용 모델과 도구가 지원되지 않습니다.

또한 GitHub에서 컴퓨터 사용 모델 및 도구의 참조 구현을 볼 수 있습니다.

컴퓨터 사용 모델 및 도구 작동 방식

텍스트 응답을 생성하는 대신 컴퓨터 사용 모델과 도구는 마우스 클릭과 같은 특정 UI 작업을 실행할 시점을 결정하고 이러한 작업을 실행하는 데 필요한 매개변수를 반환합니다. 컴퓨터 사용 모델과 도구 function_call를 수신하고 해당 작업을 실행하는 클라이언트 측 애플리케이션 코드를 작성해야 합니다.

컴퓨터 사용 모델과 도구 상호작용은 에이전트 루프 프로세스를 따릅니다.

  1. 모델에 요청 전송

    • API 요청에 컴퓨터 사용 모델과 도구, 원하는 경우 추가 도구를 추가합니다.
    • 사용자의 요청과 GUI의 현재 상태를 나타내는 스크린샷을 사용하여 컴퓨터 사용 모델과 도구를 프롬프트합니다.
  2. 모델 응답 수신

    • 모델은 사용자 요청과 스크린샷을 분석하고 UI 작업을 나타내는 추천 function_call('좌표 (x,y) 클릭' 또는 '텍스트 입력' 등)이 포함된 대답을 생성합니다. 모델과 함께 사용할 수 있는 모든 작업 목록은 지원되는 작업을 참고하세요.
    • API 응답에는 모델의 제안된 작업을 확인한 내부 안전 시스템의 safety_response도 포함될 수 있습니다. 이 safety_response는 작업을 다음과 같이 분류합니다.
      • 일반 또는 허용됨: 작업이 안전한 것으로 간주됩니다. safety_response이 없는 것으로도 나타낼 수 있습니다.
      • 확인 필요: 모델이 위험할 수 있는 작업을 실행하려고 합니다 (예: '쿠키 배너 수락' 클릭).
  3. 수신된 작업 실행

    • 클라이언트 측 코드에서 function_call 및 함께 제공되는 safety_response를 수신합니다.
    • safety_response가 일반 또는 허용을 나타내는 경우 (또는 safety_response가 없는 경우) 클라이언트 측 코드는 타겟 환경 (예: 웹브라우저)에서 지정된 function_call를 실행할 수 있습니다.
    • safety_response에 확인이 필요하다고 표시되면 애플리케이션에서 function_call을 실행하기 전에 최종 사용자에게 확인을 요청해야 합니다. 사용자가 확인하면 작업을 실행합니다. 사용자가 거부하면 작업을 실행하지 마세요.
  4. 새 환경 상태 캡처

    • 작업이 실행되면 클라이언트가 GUI와 현재 URL의 새 스크린샷을 캡처하여 function_response의 일부로 컴퓨터 사용 모델과 도구에 다시 전송합니다.
    • 안전 시스템에 의해 작업이 차단되거나 사용자가 확인을 거부한 경우 애플리케이션이 모델에 다른 형태의 의견을 전송하거나 상호작용을 종료할 수 있습니다.

업데이트된 상태로 모델에 새 요청이 전송됩니다. 이 프로세스는 2단계부터 반복되며, 컴퓨터 사용 모델과 도구는 새 스크린샷(제공된 경우)과 지속적인 목표를 사용하여 다음 작업을 제안합니다. 작업이 완료되거나 오류가 발생하거나 프로세스가 종료될 때까지 (예: 안전 필터 또는 사용자 결정에 의해 응답이 차단된 경우) 루프가 계속됩니다.

다음 다이어그램은 컴퓨터 사용 모델과 도구의 작동 방식을 보여줍니다.

컴퓨터 사용 모델 및 도구 개요

컴퓨터 사용 모델 및 도구 사용 설정

컴퓨터 사용 모델과 도구를 사용 설정하려면 gemini-2.5-computer-use-preview-10-2025을 모델로 사용하고 사용 설정된 도구 목록에 컴퓨터 사용 모델과 도구를 추가하세요.

Python

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

client = genai.Client()

# Add Computer Use model and tool to the list of tools
generate_content_config = genai.types.GenerateContentConfig(
    tools=[
        types.Tool(
            computer_use=types.ComputerUse(
                environment=types.Environment.ENVIRONMENT_BROWSER,
                )
              ),
            ]
          )

# Example request using the Computer Use model and tool
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-2.5-computer-use-preview-10-2025",
    contents=contents,
    config=generate_content_config,
  )
      

요청 전송

컴퓨터 사용 모델과 도구를 구성한 후 사용자의 목표와 GUI의 초기 스크린샷이 포함된 프롬프트를 모델에 전송합니다.

선택적으로 다음을 추가할 수도 있습니다.

  • 제외된 작업: 모델이 수행하지 않기를 원하는 작업이 지원되는 UI 작업 목록에 있는 경우 excluded_predefined_functions에 이러한 작업을 지정합니다.
  • 사용자 정의 함수: 컴퓨터 사용 모델 및 도구 외에 맞춤 사용자 정의 함수를 포함할 수 있습니다.

다음 샘플 코드는 컴퓨터 사용 모델과 도구를 사용 설정하고 모델에 요청을 전송합니다.

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 the Computer Use model and tool with browser environment
generate_content_config = genai.types.GenerateContentConfig(
    tools=[
        # 1. Computer Use model and 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-2.5-computer-use-preview-10-2025',
    contents=contents,
    config=generate_content_config,
)

# Print the response output
print(response.text)
      

맞춤 사용자 정의 함수를 포함하여 모델의 기능을 확장할 수도 있습니다. 브라우저별 작업을 제외하면서 open_app, long_press_at, go_home과 같은 작업을 추가하여 모바일 사용 사례에 맞게 컴퓨터 사용을 구성하는 방법에 관한 자세한 내용은 모바일 사용 사례에 컴퓨터 사용 모델 및 도구 사용을 참고하세요.

응답 수신

모델은 작업을 완료하는 데 UI 작업이나 사용자 정의 함수가 필요하다고 판단되면 하나 이상의 FunctionCalls로 응답합니다. 애플리케이션 코드는 이러한 작업을 파싱하고 실행하고 결과를 수집해야 합니다. 컴퓨터 사용 모델과 도구는 병렬 함수 호출을 지원합니다. 즉, 모델이 단일 턴에서 여러 독립적인 작업을 반환할 수 있습니다.

{
  "content": {
    "parts": [
      {
        "text": "I will type the search query into the search bar. The search bar is in the center of the page."
      },
      {
        "function_call": {
          "name": "type_text_at",
          "args": {
            "x": 371,
            "y": 470,
            "text": "highly rated smart fridges with touchscreen, 2 doors, around 25 cu ft, priced below 4000 dollars on Google Shopping",
            "press_enter": true
          }
        }
      }
    ]
  }
}

작업에 따라 API 응답이 safety_response을 반환할 수도 있습니다.

{
  "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"
            }
          }
        }
      }
    ]
  }
}

수신된 작업 실행

대답을 받은 후 모델은 수신된 작업을 실행해야 합니다.

다음 코드는 Gemini 대답에서 함수 호출을 추출하고, 좌표를 0~1000 범위에서 실제 픽셀로 변환하고, Playwright를 사용하여 브라우저 작업을 실행하고, 각 작업의 성공 또는 실패 상태를 반환합니다.

import time
from typing import Any, List, Tuple


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


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


def execute_function_calls(response, page, screen_width: int, screen_height: int) -> List[Tuple[str, Any]]:
    """
    Extract and execute function calls from Gemini response.

    Args:
        response: Gemini API response object
        page: Playwright page object
        screen_width: Screen width in pixels
        screen_height: Screen height in pixels

    Returns:
        List of tuples: [(function_name, result), ...]
    """
    # Extract function calls and thoughts from the model's 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)}")

    # Execute each function call
    results = []
    for function_call in function_calls:
        result = None

        try:
            if function_call.name == "open_web_browser":
                print("Executing open_web_browser")
                # Browser is already open via Playwright, so this is a no-op
                result = "success"

            elif function_call.name == "click_at":
                actual_x = normalize_x(function_call.args["x"], screen_width)
                actual_y = normalize_y(function_call.args["y"], screen_height)

                print(f"Executing click_at: ({actual_x}, {actual_y})")
                page.mouse.click(actual_x, actual_y)
                result = "success"

            elif function_call.name == "type_text_at":
                actual_x = normalize_x(function_call.args["x"], screen_width)
                actual_y = normalize_y(function_call.args["y"], screen_height)
                text = function_call.args["text"]
                press_enter = function_call.args.get("press_enter", False)
                clear_before_typing = function_call.args.get("clear_before_typing", True)

                print(f"Executing type_text_at: ({actual_x}, {actual_y}) text='{text}'")

                # Click at the specified location
                page.mouse.click(actual_x, actual_y)
                time.sleep(0.1)

                # Clear existing text if requested
                if clear_before_typing:
                    page.keyboard.press("Control+A")
                    page.keyboard.press("Backspace")

                # Type the text
                page.keyboard.type(text)

                # Press enter if requested
                if press_enter:
                    page.keyboard.press("Enter")

                result = "success"

            else:
                # For any functions not parsed above
                print(f"Unrecognized function: {function_call.name}")
                result = "unknown_function"

        except Exception as e:
            print(f"Error executing {function_call.name}: {e}")
            result = f"error: {str(e)}"

        results.append((function_call.name, result))

    return results

반환된 safety_decisionrequire_confirmation인 경우 작업을 실행하기 전에 사용자에게 확인을 요청해야 합니다. 서비스 약관에 따라 사람의 확인 요청을 우회하는 것은 허용되지 않습니다.

다음은 이전 코드에 안전 로직을 추가합니다.

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"

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

새 상태 캡처

작업을 실행한 후 함수 실행 결과를 모델에 다시 전송하여 모델이 이 정보를 사용하여 다음 작업을 생성할 수 있도록 합니다. 여러 작업 (병렬 호출)이 실행된 경우 후속 사용자 턴에서 각 작업에 대해 FunctionResponse를 전송해야 합니다. 사용자 정의 함수의 경우 FunctionResponse에는 실행된 함수의 반환 값이 포함되어야 합니다.

function_response_parts = []

for name, result in results:
    # Take screenshot after each action
    screenshot = page.screenshot()
    current_url = page.url

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

# Create the user feedback content with all responses
user_feedback_content = Content(
    role="user",
    parts=function_response_parts
)

# Append this feedback to the 'contents' history list for the next API call
contents.append(user_feedback_content)

에이전트 루프 빌드

이전 단계를 루프로 결합하여 다단계 상호작용을 사용 설정합니다. 루프는 병렬 함수 호출을 처리해야 합니다. 모델 응답과 함수 응답을 모두 추가하여 대화 기록 (콘텐츠 배열)을 올바르게 관리해야 합니다.

Python

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


def has_function_calls(response):
    """Check if 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()

    # ... (config setup from "Send a request to model" section) ...

    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()
        page.goto("https://www.google.com")
        
        screen_width, screen_height = 1920, 1080
        
        # ... (initial contents setup from "Send a request to model" section) ...

        # Agent loop: iterate until model provides final answer
        for iteration in range(10):
            print(f"\nIteration {iteration + 1}\n")

            # 1. Send request to model (see "Send a request to model" section)
            response = client.models.generate_content(
                model='gemini-2.5-computer-use-preview-10-2025',
                contents=contents,
                config=generate_content_config,
            )

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

            # 2. Check if done - no function calls means final answer
            if not has_function_calls(response):
                print(f"FINAL RESPONSE:\n{response.text}")
                break

            # 3. Execute actions (see "Execute the received actions" section)
            results = execute_function_calls(response, page, screen_width, screen_height)
            time.sleep(1)

            # 4. Capture state and create feedback (see "Capture the New State" section)
            contents.append(create_feedback(results, page))

        input("\nPress Enter to close browser...")
        browser.close()


if __name__ == "__main__":
    main()
      

모바일 사용 사례를 위한 컴퓨터 사용 모델 및 도구

다음 예에서는 open_app, long_press_at, go_home와 같은 맞춤 함수를 정의하고, Gemini의 내장 컴퓨터 사용 도구와 결합하고, 불필요한 브라우저별 함수를 제외하는 방법을 보여줍니다. 이러한 맞춤 함수를 등록하면 모델이 표준 UI 작업과 함께 이러한 함수를 지능적으로 호출하여 비브라우저 환경에서 작업을 완료할 수 있습니다.

from typing import Optional, Dict, Any

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


client = genai.Client()

def open_app(app_name: str, intent: Optional[str] = None) -> Dict[str, Any]:
    """Opens an app by name.

    Args:
        app_name: Name of the app to open (any string).
        intent: Optional deep-link or action to pass when launching, if the app supports it.

    Returns:
        JSON payload acknowledging the request (app name and optional intent).
    """
    return {"status": "requested_open", "app_name": app_name, "intent": intent}


def long_press_at(x: int, y: int, duration_ms: int = 500) -> Dict[str, int]:
    """Long-press at a specific screen coordinate.

    Args:
        x: X coordinate (absolute), scaled to the device screen width (pixels).
        y: Y coordinate (absolute), scaled to the device screen height (pixels).
        duration_ms: Press duration in milliseconds. Defaults to 500.

    Returns:
        Object with the coordinates pressed and the duration used.
    """
    return {"x": x, "y": y, "duration_ms": duration_ms}


def go_home() -> Dict[str, str]:
    """Navigates to the device home screen.

    Returns:
        A small acknowledgment payload.
    """
    return {"status": "home_requested"}


#  Build function declarations
CUSTOM_FUNCTION_DECLARATIONS = [
    types.FunctionDeclaration.from_callable(client=client, callable=open_app),
    types.FunctionDeclaration.from_callable(client=client, callable=long_press_at),
    types.FunctionDeclaration.from_callable(client=client, callable=go_home),
]

# Exclude browser functions

EXCLUDED_PREDEFINED_FUNCTIONS = [
    "open_web_browser",
    "search",
    "navigate",
    "hover_at",
    "scroll_document",
    "go_forward",
    "key_combination",
    "drag_and_drop",
]

# Utility function to construct a GenerateContentConfig

def make_generate_content_config() -> genai.types.GenerateContentConfig:
    """Return a fixed GenerateContentConfig with Computer Use + custom functions."""
    return genai.types.GenerateContentConfig(
        tools=[
            types.Tool(
                computer_use=types.ComputerUse(
                    environment=types.Environment.ENVIRONMENT_BROWSER,
                    excluded_predefined_functions=EXCLUDED_PREDEFINED_FUNCTIONS,
                )
            ),
            types.Tool(function_declarations=CUSTOM_FUNCTION_DECLARATIONS),
        ]
    )


# Create the content with user message
contents: list[Content] = [
    Content(
        role="user",
        parts=[
            # text instruction
            Part(text="Open Chrome, then long-press at 200,400."),
            # optional screenshot attachment
            Part.from_bytes(
                data=screenshot_image_bytes,
                mime_type="image/png",
            ),
        ],
    )
]

# Build your fixed config (from helper)
config = make_generate_content_config()

# Generate content with the configured settings
response = client.models.generate_content(
        model="gemini-2.5-computer-use-preview-10-2025",
        contents=contents,
        config=generate_content_config,
    )

    print(response)

지원되는 작업

컴퓨터 사용 모델과 도구를 사용하면 모델이 FunctionCall를 사용하여 다음 작업을 요청할 수 있습니다. 클라이언트 측 코드에서 이러한 작업의 실행 로직을 구현해야 합니다. 예시는 참조 구현을 참고하세요.

명령어 이름 설명 인수 (함수 호출) 함수 호출 예시
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로 직접 이동합니다. 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 웹페이지의 특정 좌표에 마우스를 가져갑니다. 하위 메뉴를 표시하는 데 유용합니다. 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_decisionrequire_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
                )
             )
           ]
         )
       )

안전 권장사항

컴퓨터 사용 모델과 도구는 새로운 도구이며 개발자가 유의해야 하는 새로운 위험을 제시합니다.

  • 신뢰할 수 없는 콘텐츠 및 사기: 모델이 사용자의 목표를 달성하려고 할 때 신뢰할 수 없는 정보 소스와 화면의 안내에 의존할 수 있습니다. 예를 들어 사용자의 목표가 Pixel 휴대전화를 구매하는 것인데 모델이 '설문조사를 완료하면 Pixel 무료' 사기를 발견하면 모델이 설문조사를 완료할 가능성이 있습니다.
  • 가끔 의도하지 않은 작업: 모델이 사용자의 목표나 웹페이지 콘텐츠를 잘못 해석하여 잘못된 버튼을 클릭하거나 잘못된 양식을 작성하는 등 잘못된 작업을 수행할 수 있습니다. 이로 인해 작업이 실패하거나 데이터 유출이 발생할 수 있습니다.
  • 정책 위반: API의 기능이 의도적이든 의도치 않든 Google 정책 (생성형 AI 금지된 사용 정책 및 Gemini API 추가 서비스 약관)을 위반하는 활동으로 향할 수 있습니다. 여기에는 시스템의 무결성을 방해하거나, 보안을 훼손하거나, 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.
    
    **Procedure for Seeking Confirmation:**  * **For Consequential Actions:**
    Perform all preparatory steps (e.g., navigating, filling out forms, typing a
    message). You will ask for confirmation **AFTER** all necessary information is
    entered on the screen, but **BEFORE** you perform the final, irreversible action
    (e.g., before clicking "Send", "Submit", "Confirm Purchase", "Share").  * **For
    Prohibited Actions:** If the action is strictly forbidden (e.g., accepting legal
    terms, solving a CAPTCHA), you must first inform the user about the required
    action and ask for their confirmation to proceed.
    
    **USER_CONFIRMATION Categories:**
    
    *   **Consent and Agreements:** You are FORBIDDEN from accepting, selecting, or
        agreeing to any of the following on the user's behalf. You must ask th e
        user to confirm before performing these actions.
        *   Terms of Service
        *   Privacy Policies
        *   Cookie consent banners
        *   End User License Agreements (EULAs)
        *   Any other legally significant contracts or agreements.
    *   **Robot Detection:** You MUST NEVER attempt to solve or bypass the
        following. You must ask the user to confirm before performing these actions.
    *   CAPTCHAs (of any kind)
        *   Any other anti-robot or human-verification mechanisms, even if you are
            capable.
    *   **Financial Transactions:**
        *   Completing any purchase.
        *   Managing or moving money (e.g., transfers, payments).
        *   Purchasing regulated goods or participating in gambling.
    *   **Sending Communications:**
        *   Sending emails.
        *   Sending messages on any platform (e.g., social media, chat apps).
        *   Posting content on social media or forums.
    *   **Accessing or Modifying Sensitive Information:**
        *   Health, financial, or government records (e.g., medical history, tax
            forms, passport status).
        *   Revealing or modifying sensitive personal identifiers (e.g., SSN, bank
            account number, credit card number).
    *   **User Data Management:**
        *   Accessing, downloading, or saving files from the web.
        *   Sharing or sending files/data to any third party.
        *   Transferring user data between systems.
    *   **Browser Data Usage:**
        *   Accessing or managing Chrome browsing history, bookmarks, autofill data,
            or saved passwords.
    *   **Security and Identity:**
        *   Logging into any user account.
        *   Any action that involves misrepresentation or impersonation (e.g.,
            creating a fan account, posting as someone else).
    *   **Insurmountable Obstacles:** If you are technically unable to interact with
        a user interface element or are stuck in a loop you cannot resolve, ask the
        user to take over.
    ---
    
    ## **RULE 2: Default Behavior (ACTUATE)**
    
    If an action does **NOT** fall under the conditions for `USER_CONFIRMATION`,
    your default behavior is to **Actuate**.
    
    **Actuation Means:**  You MUST proactively perform all necessary steps to move
    the user's request forward. Continue to actuate until you either complete the
    non-consequential task or encounter a condition defined in Rule 1.
    
    *   **Example 1:** If asked to send money, you will navigate to the payment
        portal, enter the recipient's details, and enter the amount. You will then
        **STOP** as per Rule 1 and ask for confirmation before clicking the final
        "Send" button.
    *   **Example 2:** If asked to post a message, you will navigate to the site,
        open the post composition window, and write the full message. You will then
        **STOP** as per Rule 1 and ask for confirmation before clicking the final
        "Post" button.
    
        After the user has confirmed, remember to get the user's latest screen
        before continuing to perform actions.
    
    # Final Response Guidelines:
    Write final response to the user in these cases:
    - User confirmation
    - When the task is complete or you have enough information to respond to the user
        
  2. 안전한 실행 환경: 안전한 샌드박스 환경에서 에이전트를 실행하여 잠재적 영향을 제한합니다 (예: 샌드박스 가상 머신 (VM), 컨테이너 (예: Docker), 권한이 제한된 전용 브라우저 프로필).
  3. 입력 삭제: 의도하지 않은 명령어 또는 프롬프트 삽입의 위험을 완화하기 위해 프롬프트에서 사용자가 생성한 모든 텍스트를 삭제합니다. 이는 유용한 보안 레이어이지만 안전한 실행 환경을 대체하지는 않습니다.
  4. 허용 목록 및 차단 목록: 모델이 탐색할 수 있는 위치와 수행할 수 있는 작업을 제어하는 필터링 메커니즘을 구현합니다. 금지된 웹사이트의 차단 목록이 좋은 시작점이며, 더 제한적인 허용 목록이 훨씬 더 안전합니다.
  5. 관측 가능성 및 로깅: 디버깅, 감사, 사고 대응을 위해 자세한 로그를 유지합니다. 클라이언트는 프롬프트, 스크린샷, 모델 제안 작업 (function_call), 안전 응답, 클라이언트가 최종적으로 실행한 모든 작업을 로깅해야 합니다.

가격 책정

컴퓨터 사용 모델과 도구는 Gemini 2.5 Pro와 동일한 요금으로 가격이 책정되며 동일한 SKU를 사용합니다. 컴퓨터 사용 모델 및 도구 비용을 분할하려면 커스텀 메타데이터 라벨을 사용하세요. 비용 모니터링을 위해 커스텀 메타데이터 라벨을 사용하는 방법에 대한 자세한 내용은 커스텀 메타데이터 라벨을 참고하세요.