はじめに
2026年1月に gemini-3.1-pro-preview と gemini-3-flash-preview が Computer Use に対応し、2026年3月18日には他の Built-in Tools(google_search・code_execution)と組み合わせての利用も可能になりました。
Gemini の Computer Use は ブラウザ環境 を操作対象として、クリック・テキスト入力・スクロール・ナビゲーションといったアクションを JSON で返します。スクリーンショットを渡すたびに次のアクションを指示するマルチターン方式で動作します。
この記事で学べること
- Gemini API Computer Use の基本構造とサポートアクション一覧
- Playwright と組み合わせたブラウザ自動操作の実装方法
- Built-in Tools(google_search、code_execution)との組み合わせ方
- 座標の正規化・変換ロジック
対象読者
- Python でブラウザ自動化を実装したい方
- Gemini API を既に使っており Computer Use を追加したい方
- Claude Computer Use との比較を検討している方
前提環境
- Python 3.11 以上
-
google-genaiSDK(pip install google-genai) - Playwright(
pip install playwright && playwright install chromium) - Gemini API キー(
GOOGLE_API_KEY環境変数)
TL;DR
-
gemini-3.1-pro-preview/gemini-3-flash-previewで Computer Use が利用可能(2026年1月〜) - 操作環境は ブラウザのみ (
ENVIRONMENT_BROWSER) - 座標は 0〜999 の正規化グリッド で返され、実ピクセルへの変換が必要
- Built-in Tools との組み合わせは 2026年3月18日から対応
- マルチターンループでスクリーンショット → アクション → 実行 を繰り返す
Gemini API Computer Use の概要
対応モデル
| モデル | 状態 | 用途 | 料金(入力) |
|---|---|---|---|
gemini-3-flash-preview |
現行・推奨 | 高速・コスト効率重視 | 無料(プレビュー中) |
gemini-3.1-pro-preview |
現行 | 高精度・複雑なタスク向け | $2.00/MTok |
gemini-2.5-computer-use-preview-10-2025 |
プレビュー | Computer Use 専用モデル(初期) | $1.25/MTok |
gemini-3-pro-previewは 2026年3月9日に廃止済みです。また、gemini-3.1-pro-previewでは本稿執筆時点(2026年3月)で Computer Use が未有効化の報告1があります。現在はgemini-3-flash-previewの使用を推奨します。
現時点でサポートされる環境は ENVIRONMENT_BROWSER(ブラウザ)のみです。デスクトップ OS 全体の操作は対象外となっています2。
サポートされるアクション一覧
| アクション名 | 主な引数 | 説明 |
|---|---|---|
open_web_browser |
なし | ブラウザを開く |
navigate |
url |
指定URLに遷移 |
click_at |
x, y
|
座標をクリック |
type_text_at |
x, y, text, press_enter
|
テキスト入力 |
scroll_document |
direction ("up" / "down" / "left" / "right") |
ページ全体をスクロール |
scroll_at |
x, y, direction, magnitude(省略可、デフォルト 800) |
指定座標の要素をスクロール |
search |
なし | デフォルト検索エンジンのホームページに遷移 |
key_combination |
keys |
キーボードショートカット |
hover_at |
x, y
|
ホバー |
go_back |
なし | ブラウザバック |
go_forward |
なし | ブラウザ進む |
wait_5_seconds |
なし | 5秒待機 |
drag_and_drop |
x, y, destination_x, destination_y
|
ドラッグ&ドロップ |
座標はすべて 0〜999 の正規化グリッド で返されます。実際のピクセル座標への変換は次の式を使います。
real_x = int(norm_x / 1000 * screen_width)
real_y = int(norm_y / 1000 * screen_height)
基本セットアップ
インストール
pip install google-genai playwright
playwright install chromium
export GOOGLE_API_KEY="your-api-key"
最小構成のコード
from google import genai
from google.genai import types
client = genai.Client()
config = types.GenerateContentConfig(
tools=[
types.Tool(
computer_use=types.ComputerUse(
environment=types.Environment.ENVIRONMENT_BROWSER
)
)
]
)
excluded_predefined_functions を使うと特定のアクションを無効化できます。
# drag_and_drop を除外する場合
config = types.GenerateContentConfig(
tools=[
types.Tool(
computer_use=types.ComputerUse(
environment=types.Environment.ENVIRONMENT_BROWSER,
excluded_predefined_functions=["drag_and_drop"]
)
)
]
)
Playwright と組み合わせた実装
実際のブラウザ操作には Playwright を使用します。Gemini が返したアクションを Playwright で実行し、実行後のスクリーンショットを次のターンで返すマルチターンループを構成します。
ヘルパー関数の定義
import time
from playwright.sync_api import sync_playwright, Page
from google import genai
from google.genai import types
from google.genai.types import Content, Part
SCREEN_WIDTH = 1440
SCREEN_HEIGHT = 900
def denormalize(norm: int, size: int) -> int:
"""正規化座標(0-999)を実ピクセルに変換"""
return int(norm / 1000 * size)
def execute_actions(candidate, page: Page) -> list[tuple[str, dict]]:
"""Gemini が返したアクションを Playwright で実行する"""
results = []
for part in candidate.content.parts:
if not part.function_call:
continue
fname = part.function_call.name
args = part.function_call.args
if fname == "click_at":
x = denormalize(args["x"], SCREEN_WIDTH)
y = denormalize(args["y"], SCREEN_HEIGHT)
page.mouse.click(x, y)
elif fname == "type_text_at":
x = denormalize(args["x"], SCREEN_WIDTH)
y = denormalize(args["y"], SCREEN_HEIGHT)
page.mouse.click(x, y)
page.keyboard.press("Meta+A")
page.keyboard.press("Backspace")
page.keyboard.type(args["text"])
if args.get("press_enter"):
page.keyboard.press("Enter")
elif fname == "navigate":
page.goto(args["url"])
elif fname == "scroll_document":
delta = 300 if args["direction"] == "down" else -300
page.evaluate(f"window.scrollBy(0, {delta})")
elif fname == "go_back":
page.go_back()
elif fname == "go_forward":
page.go_forward()
elif fname == "wait_5_seconds":
time.sleep(5)
elif fname == "key_combination":
page.keyboard.press(args["keys"])
elif fname == "drag_and_drop":
sx = denormalize(args["x"], SCREEN_WIDTH)
sy = denormalize(args["y"], SCREEN_HEIGHT)
dx = denormalize(args["destination_x"], SCREEN_WIDTH)
dy = denormalize(args["destination_y"], SCREEN_HEIGHT)
page.mouse.move(sx, sy)
page.mouse.down()
page.mouse.move(dx, dy, steps=10)
page.mouse.up()
try:
page.wait_for_load_state(timeout=5000)
except Exception:
pass
time.sleep(0.8)
results.append((fname, args))
return results
def build_function_responses(page: Page, results: list) -> list:
"""実行後スクリーンショットを FunctionResponse に変換"""
screenshot_bytes = page.screenshot(type="png")
current_url = page.url
return [
types.FunctionResponse(
name=name,
response={"url": current_url},
)
for name, _ in results
]
メインループ
def run_computer_use_agent(task: str, start_url: str = "https://www.google.com"):
client = genai.Client()
config = types.GenerateContentConfig(
tools=[types.Tool(
computer_use=types.ComputerUse(
environment=types.Environment.ENVIRONMENT_BROWSER
)
)]
)
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
ctx = browser.new_context(
viewport={"width": SCREEN_WIDTH, "height": SCREEN_HEIGHT}
)
page = ctx.new_page()
page.goto(start_url)
# 初回スクリーンショット
initial_ss = page.screenshot(type="png")
contents = [Content(role="user", parts=[
Part(text=task),
Part.from_bytes(data=initial_ss, mime_type="image/png"),
])]
for turn in range(20): # 最大 20 ターン
response = client.models.generate_content(
model="gemini-3-flash-preview",
contents=contents,
config=config,
)
candidate = response.candidates[0]
contents.append(candidate.content)
has_calls = any(p.function_call for p in candidate.content.parts)
if not has_calls:
# テキスト応答で完了
text_parts = [p.text for p in candidate.content.parts if p.text]
print(f"[完了] {' '.join(text_parts)}")
break
results = execute_actions(candidate, page)
fn_responses = build_function_responses(page, results)
# 次のターンへスクリーンショット付きで返す
ss_bytes = page.screenshot(type="png")
parts = [Part(function_response=fr) for fr in fn_responses]
parts.append(Part.from_bytes(data=ss_bytes, mime_type="image/png"))
contents.append(Content(role="user", parts=parts))
browser.close()
# 実行例
run_computer_use_agent(
task="GitHubで 'google-gemini python' を検索し、最初のリポジトリのスター数を教えてください",
start_url="https://github.com"
)
Built-in Tools との組み合わせ(2026年3月18日対応)
2026年3月18日のアップデートで、Computer Use と google_search・code_execution などの Built-in Tools を 同一リクエスト内 で組み合わせられるようになりました2。
config = types.GenerateContentConfig(
tools=[
# Computer Use(ブラウザ操作)
types.Tool(
computer_use=types.ComputerUse(
environment=types.Environment.ENVIRONMENT_BROWSER
)
),
# Google 検索による情報補完
types.Tool(google_search=types.GoogleSearch()),
# コード実行による計算・データ変換
types.Tool(code_execution=types.CodeExecution()),
]
)
この組み合わせにより、例えば「Webページからデータを取得(Computer Use)→ Python でデータ変換(code_execution)→ 検索で追加情報を補完(google_search)」といった複合タスクをシングルエージェントで実行できます。
安全性の考慮事項
safety_decision フィールド
アクションが安全性の懸念を引き起こす可能性がある場合、function_call.args に safety_decision フィールドが含まれることがあります。
for part in candidate.content.parts:
if part.function_call:
args = part.function_call.args
if "safety_decision" in args:
decision = args["safety_decision"].get("decision")
if decision == "require_confirmation":
# ユーザー確認を求める
user_input = input(f"操作 '{part.function_call.name}' を実行しますか?(y/n): ")
if user_input.lower() != "y":
continue
プロンプトインジェクション対策
ブラウザが表示するコンテンツには悪意のある指示が含まれる場合があります。以下の点に注意が必要です。
-
ドメインホワイトリスト:
navigateアクションで遷移できるドメインを制限する - センシティブ操作の確認: パスワード入力・決済操作は必ずユーザー確認を挟む
-
ヘッドレスモード非推奨: 操作の可視性確保のため
headless=Falseを推奨
ALLOWED_DOMAINS = {"github.com", "google.com", "example.com"}
def is_safe_navigate(url: str) -> bool:
from urllib.parse import urlparse
domain = urlparse(url).netloc.removeprefix("www.")
return domain in ALLOWED_DOMAINS
Claude Computer Use との比較
| 項目 | Gemini Computer Use | Claude Computer Use |
|---|---|---|
| 操作対象 | ブラウザのみ | ブラウザ + デスクトップ OS |
| 座標系 | 1000×1000 正規化グリッド(変換必要) | 実ピクセル |
| アクション形式 | function_call |
tool_use ブロック |
| Built-in Tools 組み合わせ | 対応(2026年3月〜) | MCPサーバーで拡張 |
| API 統合 |
google-genai SDK |
anthropic SDK |
| 料金 | Gemini API 料金体系 | Claude API 料金体系 |
注意点
ブラウザ環境のみサポート: デスクトップアプリ・ファイルシステムへの直接操作は現時点で非対応です。ブラウザを通じて間接的に操作する設計が必要です。
正規化座標の変換: Gemini が返す座標は 0〜999 のグリッドです。
denormalize()関数で実ピクセルへ変換してから Playwright に渡してください。変換漏れがあるとクリック位置がずれます。
本番環境での利用: Computer Use はまだプレビュー機能です。本番環境への適用は公式の GA(General Availability)アナウンス後に検討することを推奨します。
まとめ
- Gemini 3 Pro/Flash は 2026年1月から Computer Use に対応
- ブラウザ環境 を対象に、クリック・入力・スクロール等 13 種のアクションを返す
- 座標は 0〜999 の正規化グリッド で実ピクセルへの変換が必要
- Built-in Tools との組み合わせ(2026年3月〜)で、検索・コード実行と組み合わせた複合エージェントが実現可能
- Playwright と組み合わせたマルチターンループが基本実装パターン
Claude Computer Use と比べるとブラウザ限定の制約はありますが、google_search や code_execution との統合が標準サポートされている点は Gemini の強みです。
参考リンク
- Gemini API - Computer Use(公式ドキュメント)
- Gemini API Changelog
- google-genai Python SDK
- Playwright Python ドキュメント