エージェント向けコンピューター操作ツールを使用する(プレビュー)

重要

この記事でマークされている項目 (プレビュー) は、現在パブリック プレビュー段階です。 このプレビューはサービス レベル アグリーメントなしで提供されており、運用環境のワークロードにはお勧めしません。 特定の機能がサポートされていないか、機能が制限されている可能性があります。 詳細については、「Microsoft Azure プレビューの使用条件を参照してください。

警告

コンピューター使用ツールには、迅速なインジェクション攻撃など、重大なセキュリティとプライバシーのリスクが付属しています。 ユース ケースを選択するときの目的の用途、機能、制限事項、リスク、および考慮事項の詳細については、Azure OpenAI の透明性に関するメモを参照してください。

スクリーンショットを解釈し、クリック、入力、スクロールなどの UI 操作を自動化するエージェントを作成します。 コンピューター使用ツールでは、 computer-use-preview Foundry モデルを使用して、ビジュアル コンテンツに基づくアクションを提案し、エージェントがユーザー インターフェイスを介してデスクトップおよびブラウザー アプリケーションと対話できるようにします。

このガイドでは、最新の SDK を使用して、コンピューター使用ツールをアプリケーション ループに統合する方法 (スクリーンショット→アクション→スクリーンショット) を示します。

前提 条件

使用サポート

次の表に、SDK とセットアップのサポートを示します。

Microsoft Foundry のサポート Python SDK C# SDK JavaScript SDK Java SDK REST API 基本的なエージェントのセットアップ 標準エージェントのセットアップ
✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️

この記事のコード スニペットでは、エージェントと Responses API の統合に重点を置きます。 これらはヘルパー コードとサンプルのスクリーンショットに依存するため、スタンドアロンではありません。 次の提供されているサンプルとヘルパーを使用してください:

PythonおよびJava ヘルパーは、要求されたアクションの事前にキャプチャされたスクリーンショットを返すことによって、ステート マシンをシミュレートします。 サンドボックス内のアクションを検証して実行し、結果の状態をキャプチャし、保留中の安全性チェックを確認する前に明示的なユーザー承認を必要とするアプリケーション所有のコードは置き換えられません。

ヒント

ヘルパー ファイルと事前にキャプチャされたスクリーンショットアセットが想定される相対位置に残るように、サンプル リポジトリを複製します。

アクセスを要求する

computer-use-preview モデルにアクセスするには、登録する必要があります。 Microsoftは、適格性基準に基づいてアクセス権を付与します。 他の制限付きアクセス モデルにアクセスできる場合でも、このモデルへのアクセスを要求する必要があります。

アクセス権を要求するには、 アプリケーション フォームを参照してください。

Microsoftがアクセスを許可すると、モデルをデプロイする必要があります。

コード サンプル

警告

機密データや重要なリソースにアクセスできない仮想マシンでコンピューター使用ツールを使用します。 ユース ケースを選択するときの目的の用途、機能、制限事項、リスク、および考慮事項の詳細については、「Azure OpenAI の透明性に関するメモを参照してください。

最新の SDK パッケージが必要です。 .NET SDK は現在プレビュー段階です。

コンピューター使用ツールの実行に関するスクリーンショットの初期化

次の抜粋では、コンピューター使用ツールを使用してエージェント バージョンを作成し、スクリーンショットで最初の要求を送信し、複数のイテレーションを実行してタスクを完了する方法を示します。 Prompt Agents の抜粋は、前述のリンク先にある保守されている Python サンプルとヘルパーに基づいています。 Azure AI Projects SDK を使用してサーバー側プロンプト エージェントを作成する場合は Prompt Agents を選択します。エージェント フレームワーク を使用してエフェメラルなインプロセス エージェントを作成するには、FoundryChatClient を選択します。

エージェントに指示を促す

from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import PromptAgentDefinition, ComputerUsePreviewTool

# Import shared helper functions
from computer_use_util import (
    SearchState,
    load_screenshot_assets,
    handle_computer_action_and_take_screenshot,
    print_final_output,
)

"""Main function to demonstrate Computer Use Agent functionality."""
# Initialize state machine
current_state = SearchState.INITIAL

# Load screenshot assets
try:
    screenshots = load_screenshot_assets()
    print("Successfully loaded screenshot assets")
except FileNotFoundError:
    print("Failed to load required screenshot assets. Use the maintained SDK sample on GitHub to get the helper file and images.")
    exit(1)

ツールを使用してエージェント バージョンを作成する

# Format: "https://resource_name.ai.azure.com/api/projects/project_name"
PROJECT_ENDPOINT = "your_project_endpoint"

project = AIProjectClient(
    endpoint=PROJECT_ENDPOINT,
    credential=DefaultAzureCredential(),
)

computer_use_tool = ComputerUsePreviewTool(display_width=1026, display_height=769, environment="windows")

agent = project.agents.create_version(
    agent_name="ComputerUseAgent",
    definition=PromptAgentDefinition(
        model="computer-use-preview",
        instructions="""
        You are a computer automation assistant. 

        Be direct and efficient. When you reach the search results page, read and describe the actual search result titles and descriptions you can see.
        """,
        tools=[computer_use_tool],
    ),
    description="Computer automation agent with screen interaction capabilities.",
)
print(f"Agent created (id: {agent.id}, name: {agent.name})")

ツールがスクリーンショットを処理し、次の手順を実行するための 1 つのイテレーション

openai = project.get_openai_client()

# Initial request with screenshot - start with Bing search page
response = openai.responses.create(
    input=[
        {
            "role": "user",
            "content": [
                {
                    "type": "input_text",
                    "text": "I need you to help me search for 'OpenAI news'. Please type 'OpenAI news' and submit the search. Once you see search results, the task is complete.",
                },
                {
                    "type": "input_image",
                    "image_url": screenshots["browser_search"]["url"],
                    "detail": "high",
                },  # Start with Bing search page
            ],
        }
    ],
    extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
    truncation="auto",
)

print(f"Initial response received (ID: {response.id})")

複数のイテレーションを実行する

各イテレーションとアクションを確認してください。 次のコード サンプルは、基本的な API 要求を示しています。 最初の API 要求を送信した後、アプリケーション コードが指定したアクションを実行するループを実行します。 モデルが環境の更新された状態を評価できるように、ターンごとにスクリーンショットを送信します。 このサンプルには、無限ループを防ぐための最大反復回数が含まれていますが、必要に応じてこれを調整できます。


max_iterations = 10  # Allow enough iterations for completion
iteration = 0

while True:
    if iteration >= max_iterations:
        print(f"\nReached maximum iterations ({max_iterations}). Stopping.")
        break

    iteration += 1
    print(f"\n--- Iteration {iteration} ---")

    # Check for computer calls in the response
    computer_calls = [item for item in response.output if item.type == "computer_call"]

    if not computer_calls:
        print_final_output(response)
        break

    # Process the first computer call
    computer_call = computer_calls[0]
    action = computer_call.action
    call_id = computer_call.call_id

    # Never execute an action with pending safety checks without user approval.
    safety_checks = computer_call.pending_safety_checks or []
    if safety_checks:
      for check in safety_checks:
        print(f"Safety check: {check.code}: {check.message}")
      if input("Approve this action? Type yes to continue: ").lower() != "yes":
        print("Action rejected by the user.")
        break

    # Handle the action and get the screenshot info
    screenshot_info, current_state = handle_computer_action_and_take_screenshot(action, current_state, screenshots)

    # Regular response with just the screenshot
    response = openai.responses.create(
        previous_response_id=response.id,
        input=[
            {
                "call_id": call_id,
                "type": "computer_call_output",
                "acknowledged_safety_checks": safety_checks,
                "output": {
                    "type": "computer_screenshot",
                    "image_url": screenshot_info["url"],
                },
            }
        ],
        extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
        truncation="auto",
    )

    print(f"Iteration {iteration}: response received (ID: {response.id})")

クリーンアップ

project.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
print("Agent deleted")

予期される出力

次の例は、前のコード サンプルの実行時に予想される出力を示しています。

Successfully loaded screenshot assets
Agent created (id: ..., name: ComputerUseAgent, version: 1)
Starting computer automation session (initial screenshot: cua_browser_search.png)...
Initial response received (ID: ...)
--- Iteration 1 ---
Processing computer call (ID: ...)
  Typing text "OpenAI news" - Simulating keyboard input
  -> Action processed: type
Sending action result back to agent (using cua_search_typed.png)...
Follow-up response received (ID: ...)
--- Iteration 2 ---
Processing computer call (ID: ...)
    Click at (512, 384) - Simulating click on UI element
    -> Assuming click on Search button when search field was populated, displaying results.
    -> Action processed: click
Sending action result back to agent (using cua_search_results.png)...
Follow-up response received (ID: ...)
OpenAI news - Latest Updates
Agent deleted

ホスト型エージェント

このサンプルでは、Microsoft Agent Framework から FoundryChatClient を使用し、get_computer_use_tool() を呼び出して、プレビュー ツールを使用してコンピューターをアタッチします。 pip install agent-framework-foundry aiohttpでパッケージをインストールし、FOUNDRY_PROJECT_ENDPOINT (FOUNDRY_MODEL 展開でポイント computer-use-preview) を設定し、az loginでサインインします。 スクリーンショット キャプチャ ループはアプリケーション固有です。以下で参照されているアップストリームのサンプル ヘルパー ファイルを参照してください。

import asyncio

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential


async def main() -> None:
    agent = Agent(
        client=FoundryChatClient(credential=AzureCliCredential()),
        instructions=(
            "You are a computer automation assistant. Be direct and efficient. "
            "When you reach the search results page, describe the actual result titles you can see."
        ),
        tools=[
            FoundryChatClient.get_computer_use_tool(
                environment="windows",
                display_width=1026,
                display_height=769,
            )
        ],
    )

    # Replace this with your screenshot capture + action handler loop.
    # See the upstream samples folder for a reference implementation.
    result = await agent.run(
        "Help me search for 'OpenAI news'. Type the query and submit the search."
    )
    print(f"Agent: {result.text}")


if __name__ == "__main__":
    asyncio.run(main())

予期される出力

エージェントは、タスクが完了するまでコンピューター使用アクション (クリック、キーストローク、スクリーンショット) を発行し、到達したページについて説明します。

Agent: I searched for "OpenAI news" in the address bar. The top results include articles from OpenAI's blog, TechCrunch, and The Verge ...

完全なスクリーンショット ループの実装については、 Foundry プロバイダーのサンプルを参照してください。


コンピューター使用ツールでエージェントを使用するためのサンプル

次の C# コード サンプルでは、コンピューター使用ツールを使用してエージェントを作成し、スクリーンショットで最初の要求を送信し、複数のイテレーションを実行してタスクを完了する方法を示します。 Prompt Agents を選択して、Azure AI Projects SDK を使用してサーバー側プロンプト エージェントを作成するか、Hosted Agents を使用して、Microsoft Agent Framework を使用してエフェメラルなインプロセス エージェントを構築します。

エージェントに指示を促す

エージェントがコンピューター使用ツールを使用できるようにするには、エージェントのツールを構成するときに ResponseTool.CreateComputerTool() を使用します。 この例では、同期コードを使用します。 非同期の使用については、GitHubのリポジトリのAzure SDKのサンプル コード< .NET/c0>の例を参照してください。

using System;
using System.Runtime.CompilerServices;
using Azure.AI.Projects;
using Azure.AI.Extensions.OpenAI;
using Azure.Identity;

class ComputerUseDemo
{
    // Format: "https://resource_name.ai.azure.com/api/projects/project_name"
    private const string ProjectEndpoint = "your_project_endpoint";

    // Read image files using `ReadImageFile` method.
    private static BinaryData ReadImageFile(string name, [CallerFilePath] string pth = "")
    {
        var dirName = Path.GetDirectoryName(pth) ?? "";
        return new BinaryData(File.ReadAllBytes(Path.Combine(dirName, name)));
    }

    // Create a helper method to parse the ComputerTool outputs and to respond
    // to Agents queries with new screenshots. Note that throughout
    // this sample the media type for image is set. Agents support `image/jpeg`,
    // `image/png`, `image/gif` and `image/webp` media types.
    private static string ProcessComputerUseCall(ComputerCallResponseItem item, string oldScreenshot)
    {
        string currentScreenshot = "browser_search";
        switch (item.Action.Kind)
        {
            case ComputerCallActionKind.Type:
                Console.WriteLine($"  Typing text \"{item.Action.TypeText}\" - Simulating keyboard input");
                currentScreenshot = "search_typed";
                break;
            case ComputerCallActionKind.KeyPress:
                HashSet<string> codes = new(item.Action.KeyPressKeyCodes);
                if (codes.Contains("Return") || codes.Contains("ENTER"))
                {
                    // If we have typed the value to the search field, go to search results.
                    if (string.Equals(oldScreenshot, "search_typed"))
                    {
                        Console.WriteLine("  -> Detected ENTER key press, when search field was populated, displaying results.");
                        currentScreenshot = "search_results";
                    }
                    else
                    {
                        Console.WriteLine("  -> Detected ENTER key press, on results or unpopulated search, do nothing.");
                        currentScreenshot = oldScreenshot;
                    }
                }
                else
                {
                    Console.WriteLine($"  Key press: {item.Action.KeyPressKeyCodes.Aggregate("", (agg, next) => agg + "+" + next)} - Simulating key combination");
                }
                break;
            case ComputerCallActionKind.Click:
                Console.WriteLine($"  Click at ({item.Action.ClickCoordinates.Value.X}, {item.Action.ClickCoordinates.Value.Y}) - Simulating click on UI element");
                if (string.Equals(oldScreenshot, "search_typed"))
                {
                    Console.WriteLine("  -> Assuming click on Search button when search field was populated, displaying results.");
                    currentScreenshot = "search_results";
                }
                else
                {
                    Console.WriteLine("  -> Assuming click on Search on results or when search was not populated, do nothing.");
                    currentScreenshot = oldScreenshot;
                }
                break;
            case ComputerCallActionKind.Drag:
                string pathStr = item.Action.DragPath.ToArray().Select(p => $"{p.X}, {p.Y}").Aggregate("", (agg, next) => $"{agg} -> {next}");
                Console.WriteLine($"  Drag path: {pathStr} - Simulating drag operation");
                break;
            case ComputerCallActionKind.Scroll:
                Console.WriteLine($"  Scroll at ({item.Action.ScrollCoordinates.Value.X}, {item.Action.ScrollCoordinates.Value.Y}) - Simulating scroll action");
                break;
            case ComputerCallActionKind.Screenshot:
                Console.WriteLine("  Taking screenshot - Capturing current screen state");
                break;
            default:
                break;
        }
        Console.WriteLine($"  -> Action processed: {item.Action.Kind}");

        return currentScreenshot;
    }

    public static void Main()
    {
        // Create project client
        AIProjectClient projectClient = new(endpoint: new Uri(ProjectEndpoint), tokenProvider: new DefaultAzureCredential());

        // Read in three example screenshots and place them into a dictionary.
        Dictionary<string, BinaryData> screenshots = new() {
            { "browser_search", ReadImageFile("Assets/cua_browser_search.png")},
            { "search_typed", ReadImageFile("Assets/cua_search_typed.png")},
            { "search_results", ReadImageFile("Assets/cua_search_results.png")},
        };

        // Create a PromptAgentDefinition with ComputerTool.
        DeclarativeAgentDefinition agentDefinition = new(model: "computer-use-preview")
        {
            Instructions = "You are a computer automation assistant.\n\n" +
                            "Be direct and efficient. When you reach the search results page, read and describe the actual search result titles and descriptions you can see.",
            Tools = {
                ResponseTool.CreateComputerTool(
                    environment: new ComputerToolEnvironment("windows"),
                    displayWidth: 1026,
                    displayHeight: 769
                ),
            }
        };
        AgentVersion agentVersion = projectClient.AgentAdministrationClient.CreateAgentVersion(
            agentName: "myAgent",
            options: new(agentDefinition)
        );
        // Create an `ResponseResult` using `ResponseItem`, containing two `ResponseContentPart`:
        // one with the image and another with the text. In the loop, request Agent
        // while it is continuing to browse web. Finally, print the tool output message.
        ProjectResponsesClient responseClient = projectClient.ProjectOpenAIClient.GetProjectResponsesClientForAgent(agentVersion.Name);
        CreateResponseOptions responseOptions = new()
        {
            TruncationMode = ResponseTruncationMode.Auto,
            InputItems =
            {
                ResponseItem.CreateUserMessageItem(
                [
                    ResponseContentPart.CreateInputTextPart("I need you to help me search for 'OpenAI news'. Please type 'OpenAI news' and submit the search. Once you see search results, the task is complete."),
                    ResponseContentPart.CreateInputImagePart(imageBytes: screenshots["browser_search"], imageBytesMediaType: "image/png", imageDetailLevel: ResponseImageDetailLevel.High)
                ]),
            },
        };
        bool computerUseCalled = false;
        string currentScreenshot = "browser_search";
        int limitIteration = 10;
        ResponseResult response;
        do
        {
            response = responseClient.CreateResponse(responseOptions);
            computerUseCalled = false;
            responseOptions.InputItems.Clear();
            responseOptions.PreviousResponseId = response.Id;
            foreach (ResponseItem responseItem in response.OutputItems)
            {
                responseOptions.InputItems.Add(responseItem);
                if (responseItem is ComputerCallResponseItem computerCall)
                {
                  if (computerCall.PendingSafetyChecks.Count > 0)
                  {
                    throw new InvalidOperationException(
                      "Pause execution and obtain end-user approval before acknowledging safety checks."
                    );
                  }
                    currentScreenshot = ProcessComputerUseCall(computerCall, currentScreenshot);
                    responseOptions.InputItems.Add(ResponseItem.CreateComputerCallOutputItem(callId: computerCall.CallId, output: ComputerCallOutput.CreateScreenshotOutput(screenshotImageBytes: screenshots[currentScreenshot], screenshotImageBytesMediaType: "image/png")));
                    computerUseCalled = true;
                }
            }
            limitIteration--;
        } while (computerUseCalled && limitIteration > 0);
        Console.WriteLine(response.GetOutputText());

        // Clean up resources by deleting Agent.
        projectClient.AgentAdministrationClient.DeleteAgentVersion(agentName: agentVersion.Name, agentVersion: agentVersion.Version);
    }
}

予期される出力

次の例は、前のコード サンプルの実行時に予想される出力を示しています。

Agent created (id: ..., name: myAgent, version: 1)
Starting computer automation session (initial screenshot: cua_browser_search.png)...
Initial response received (ID: ...)
--- Iteration 1 ---
Processing computer call (ID: ...)
  Typing text "OpenAI news" - Simulating keyboard input
  -> Action processed: Type
Sending action result back to agent (using cua_search_typed.png)...
Follow-up response received (ID: ...)
--- Iteration 2 ---
Processing computer call (ID: ...)
  Click at (512, 384) - Simulating click on UI element
  -> Assuming click on Search button when search field was populated, displaying results.
  -> Action processed: Click
Sending action result back to agent (using cua_search_results.png)...
Follow-up response received (ID: ...)
OpenAI news - Latest Updates
Agent deleted

ホスト型エージェント

このサンプルでは、Microsoft Agent Framework を使用し、AsAIAgent(...)AIProjectClientFoundryAITool.CreateComputerTool(...) から Microsoft.Agents.AI.Foundry と共に呼び出して、エージェントにコンピューター使用ツールを提供します。 Microsoft.Agents.AI.Foundry パッケージと Azure.AI.Projects パッケージをインストールし、AZURE_AI_PROJECT_ENDPOINTAZURE_AI_COMPUTER_USE_DEPLOYMENT_NAME 環境変数を設定し、az login でサインインします。 このサンプルでは、スクリーンショット ヘルパーを省略しています。アクション ループとアセット ユーティリティの完全なサンプルを参照してください。

using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Foundry;
using Microsoft.Extensions.AI;
using OpenAI.Responses;

string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT")
    ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_COMPUTER_USE_DEPLOYMENT_NAME") ?? "computer-use-preview";

AIProjectClient projectClient = new(new Uri(endpoint), new DefaultAzureCredential());
using IHostedFileClient fileClient = projectClient.GetProjectOpenAIClient().AsIHostedFileClient();

AIAgent agent = projectClient.AsAIAgent(
    model: deploymentName,
    name: "ComputerAgent",
    instructions: "You are a computer automation assistant.",
    tools: [FoundryAITool.CreateComputerTool(ComputerToolEnvironment.Browser, 1026, 769)]);

// Upload pre-captured screenshots that simulate browser state transitions.
// (See the full sample for ComputerUseUtil implementation.)
Dictionary<string, string> screenshots = await ComputerUseUtil.UploadScreenshotAssetsAsync(fileClient);

ChatClientAgentRunOptions runOptions = new()
{
    ChatOptions = new ChatOptions
    {
        RawRepresentationFactory = (_) => new CreateResponseOptions { TruncationMode = ResponseTruncationMode.Auto },
    }
};

ChatMessage message = new(ChatRole.User,
[
    new TextContent("Search for 'OpenAI news'. Type it and submit. Once you see results, the task is complete."),
    new AIContent { RawRepresentation = ResponseContentPart.CreateInputImagePart(imageFileId: screenshots["browser_search"], imageDetailLevel: ResponseImageDetailLevel.High) }
]);

AgentSession session = await agent.CreateSessionAsync();
AgentResponse response = await agent.RunAsync(message, session: session, options: runOptions);

// Loop: parse computer call actions from response, simulate them, return new screenshots.
for (int i = 0; i < 10; i++)
{
    ComputerCallResponseItem? computerCall = response.Messages
        .SelectMany(m => m.Contents)
        .Select(c => c.RawRepresentation as ComputerCallResponseItem)
        .FirstOrDefault(item => item is not null);

    if (computerCall is null) break;

    (_, string fileId) = await ComputerUseUtil.GetScreenshotAsync(computerCall.Action, default, screenshots);

    AIContent callOutput = new()
    {
        RawRepresentation = new ComputerCallOutputResponseItem(
            computerCall.CallId,
            output: ComputerCallOutput.CreateScreenshotOutput(screenshotImageFileId: fileId))
    };

    response = await agent.RunAsync([new ChatMessage(ChatRole.User, [callOutput])], session: session, options: runOptions);
}

await ComputerUseUtil.EnsureDeleteScreenshotAssetsAsync(fileClient, screenshots);
Console.WriteLine($"Response: {response.Text}");

予期される出力

アクション ループが完了すると、最終的なエージェントの応答で、到達したページが記述されます。

Response: I searched for "OpenAI news" in the address bar. The top results include articles from OpenAI's blog, TechCrunch, and The Verge ...

完全なスクリーンショット ヘルパーの実装とエンドツーエンドのアクション ループについては、 Agent_Step15_ComputerUseを参照してください。


コンピューター使用ツールでエージェントを使用するためのサンプル

次の TypeScript の抜粋は、コンピューター使用ツールを使用してエージェント バージョンを作成し、スクリーンショットで最初の要求を送信し、複数のイテレーションを実行する方法を示しています。 ローカル computerUseUtil.js ヘルパーをインポートし、この記事に含まれていないスクリーンショットアセットを想定しています。 抜粋を統合アウトラインとして扱い、保留中の安全性チェックを確認する前に、アプリケーション所有のアクションの実行、スクリーンショットキャプチャ、および明示的な安全性の承認を提供します。

import { DefaultAzureCredential } from "@azure/identity";
import { AIProjectClient } from "@azure/ai-projects";
import { createInterface } from "node:readline/promises";
import { stdin, stdout } from "node:process";
import {
  SearchState,
  loadScreenshotAssets,
  handleComputerActionAndTakeScreenshot,
  printFinalOutput,
  type ComputerAction,
} from "./computerUseUtil.js";

// Format: "https://resource_name.ai.azure.com/api/projects/project_name"
const PROJECT_ENDPOINT = "your_project_endpoint";

export async function main(): Promise<void> {
  // Initialize state machine
  let currentState = SearchState.INITIAL;

  // Load screenshot assets
  const screenshots = loadScreenshotAssets();
  console.log("Successfully loaded screenshot assets");

  // Create AI Project client
  const project = new AIProjectClient(PROJECT_ENDPOINT, new DefaultAzureCredential());
  const openai = project.getOpenAIClient();

  console.log("Creating Computer Use Agent...");
  const agent = await project.agents.createVersion("ComputerUseAgent", {
    kind: "prompt" as const,
    model: "computer-use-preview",
    instructions: `
You are a computer automation assistant.

Be direct and efficient. When you reach the search results page, read and describe the actual search result titles and descriptions you can see.
    `.trim(),
    tools: [
      {
        type: "computer_use_preview",
        display_width: 1026,
        display_height: 769,
        environment: "windows" as const,
      },
    ],
  });
  console.log(`Agent created (id: ${agent.id}, name: ${agent.name}, version: ${agent.version})`);

  // Initial request with screenshot - start with Bing search page
  console.log(
    "Starting computer automation session (initial screenshot: cua_browser_search.png)...",
  );
  let response = await openai.responses.create(
    {
      input: [
        {
          role: "user" as const,
          content: [
            {
              type: "input_text",
              text: "I need you to help me search for 'OpenAI news'. Please type 'OpenAI news' and submit the search. Once you see search results, the task is complete.",
            },
            {
              type: "input_image",
              image_url: screenshots.browser_search.url,
              detail: "high",
            },
          ],
        },
      ],
      truncation: "auto",
    },
    {
      body: { agent_reference: { name: agent.name, type: "agent_reference" } },
    },
  );

  console.log(`Initial response received (ID: ${response.id})`);

  // Main interaction loop with deterministic completion
  const maxIterations = 10; // Allow enough iterations for completion
  let iteration = 0;

  while (iteration < maxIterations) {
    iteration++;
    console.log(`\n--- Iteration ${iteration} ---`);

    // Check for computer calls in the response
    const computerCalls = response.output.filter((item) => item.type === "computer_call");

    if (computerCalls.length === 0) {
      printFinalOutput({
        output: response.output,
        status: response.status ?? "",
      });
      break;
    }

    // Process the first computer call
    const computerCall = computerCalls[0];
    const action: ComputerAction = computerCall.action;
    const callId: string = computerCall.call_id;

    // Never execute an action with pending safety checks without user approval.
    const safetyChecks = computerCall.pending_safety_checks ?? [];
    if (safetyChecks.length > 0) {
      for (const check of safetyChecks) {
        console.warn(`Safety check: ${check.code}: ${check.message}`);
      }
      const prompt = createInterface({ input: stdin, output: stdout });
      const answer = await prompt.question("Approve this action? Type yes to continue: ");
      prompt.close();
      if (answer.toLowerCase() !== "yes") {
        throw new Error("Action rejected by the user.");
      }
    }

    console.log(`Processing computer call (ID: ${callId})`);

    // Handle the action and get the screenshot info
    const [screenshotInfo, updatedState] = handleComputerActionAndTakeScreenshot(
      action,
      currentState,
      screenshots,
    );
    currentState = updatedState;

    console.log(`Sending action result back to agent (using ${screenshotInfo.filename})...`);
    // Regular response with just the screenshot
    response = await openai.responses.create(
      {
        previous_response_id: response.id,
        input: [
          {
            call_id: callId,
            type: "computer_call_output",
            acknowledged_safety_checks: safetyChecks,
            output: {
              type: "computer_screenshot",
              image_url: screenshotInfo.url,
            },
          },
        ],
        truncation: "auto",
      },
      {
        body: { agent_reference: { name: agent.name, type: "agent_reference" } },
      },
    );

    console.log(`Follow-up response received (ID: ${response.id})`);
  }

  if (iteration >= maxIterations) {
    console.log(`\nReached maximum iterations (${maxIterations}). Stopping.`);
  }

  // Clean up resources
  console.log("\nCleaning up...");
  await project.agents.deleteVersion(agent.name, agent.version);
  console.log("Agent deleted");

  console.log("\nComputer Use Agent sample completed!");
}

main().catch((err) => {
  console.error("The sample encountered an error:", err);
});

予期される出力

次の例は、前のコード サンプルの実行時に予想される出力を示しています。

Successfully loaded screenshot assets
Creating Computer Use Agent...
Agent created (id: ..., name: ComputerUseAgent, version: 1)
Starting computer automation session (initial screenshot: cua_browser_search.png)...
Initial response received (ID: ...)
--- Iteration 1 ---
Processing computer call (ID: ...)
  Typing text "OpenAI news" - Simulating keyboard input
  -> Action processed: type
Sending action result back to agent (using cua_search_typed.png)...
Follow-up response received (ID: ...)
--- Iteration 2 ---
Processing computer call (ID: ...)
    Click at (512, 384) - Simulating click on UI element
    -> Assuming click on Search button when search field was populated, displaying results.
    -> Action processed: click
Sending action result back to agent (using cua_search_results.png)...
Follow-up response received (ID: ...)
OpenAI news - Latest Updates
Cleaning up...
Agent deleted
Computer Use Agent sample completed!

Java エージェント内でコンピューターを操作する

依存関係を pom.xmlに追加します。

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-ai-agents</artifactId>
    <version>2.4.0</version>
</dependency>

コンピューター使用エージェントを作成する

import com.azure.ai.agents.AgentsClient;
import com.azure.ai.agents.AgentsClientBuilder;
import com.azure.ai.agents.ResponsesClient;
import com.azure.ai.agents.models.*;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;

import java.util.Collections;

public class ComputerUseExample {
    // Format: "https://resource_name.ai.azure.com/api/projects/project_name"
    private static final String PROJECT_ENDPOINT = "your_project_endpoint";

    public static void main(String[] args) {

        AgentsClientBuilder builder = new AgentsClientBuilder()
            .credential(new DefaultAzureCredentialBuilder().build())
            .endpoint(PROJECT_ENDPOINT);

        AgentsClient agentsClient = builder.buildAgentsClient();
        ResponsesClient responsesClient = builder.buildResponsesClient();

        // Create computer use tool
        ComputerUsePreviewTool tool = new ComputerUsePreviewTool(
            ComputerEnvironment.WINDOWS,
            1024,
            768
        );

        // Create agent with computer use tool
        PromptAgentDefinition agentDefinition = new PromptAgentDefinition("computer-use-preview")
            .setInstructions("You are a computer automation assistant.")
            .setTools(Collections.singletonList(tool));

        AgentVersionDetails agent = agentsClient.createAgentVersion("computer-use-agent", agentDefinition);
        System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion());

        // Create a response with initial screenshot
        AgentReference agentReference = new AgentReference(agent.getName())
            .setVersion(agent.getVersion());

        Response response = responsesClient.createAzureResponse(
            new AzureCreateResponseOptions().setAgentReference(agentReference),
            ResponseCreateParams.builder()
                .input("Open the browser and navigate to microsoft.com"));

        System.out.println("Response: " + response.output());

        // The response will contain computer_call items with actions
        // to execute. Process each action, take screenshots, and
        // send results back using responsesClient.createAzureResponse()
        // with the previousResponseId and computer call output.

        // Clean up
        agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion());
    }
}

完全なシミュレートループには、そのComputerUseSync.java サンプルと付属のComputerUseUtil.java ヘルパーを使用してください。 ヘルパーは、要求されたアクションを事前にキャプチャされたスクリーンショットにマップします。 そのシミュレーションを、アプリケーションのアクション 実行プログラム、スクリーンショット キャプチャ、および安全承認フローに置き換えます。

REST API を使ってコンピューターを利用する

アクセス トークンを取得します。

export AGENT_TOKEN=$(az account get-access-token --scope "https://ai.azure.com/.default" --query accessToken -o tsv)

コンピューターを使用してエージェントを作成する

curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/agents?api-version=v1" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -d '{
    "name": "computer-use-agent",
    "definition": {
      "kind": "prompt",
      "model": "computer-use-preview",
      "instructions": "You are a computer automation assistant.",
      "tools": [
        {
          "type": "computer_use_preview",
          "environment": "windows",
          "display_width": 1024,
          "display_height": 768
        }
      ]
    }
  }'

応答を生成する

curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/responses" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -d '{
    "agent_reference": {"type": "agent_reference", "name": "computer-use-agent"},
    "input": "Open the browser and navigate to microsoft.com"
  }'

応答には、実行するアクション computer_call 出力項目が含まれます。 アクションを実行する前に、 pending_safety_checksを調べます。 配列が空でない場合は、一時停止し、アクションと安全性チェックをエンド ユーザーに表示します。 ユーザーがアクションを明示的に承認した後にのみ続行します。

スクリーンショットを使用してアクションの結果を送信する

ユーザーが保留中の安全性チェックを承認し、アプリケーションがコンピューターアクションを実行したら、スクリーンショットをキャプチャして返送します。 各承認済みチェックをacknowledged_safety_checksに含めます。 チェックが返されなかった場合は、空の配列を使用します。

curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/responses" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -d '{
    "agent_reference": {"type": "agent_reference", "name": "computer-use-agent"},
    "previous_response_id": "<RESPONSE_ID>",
    "input": [
      {
        "type": "computer_call_output",
        "call_id": "<CALL_ID>",
        "acknowledged_safety_checks": [],
        "output": {
          "type": "computer_screenshot",
          "image_url": "data:image/png;base64,<BASE64_SCREENSHOT>"
        }
      }
    ]
  }'

<RESPONSE_ID><CALL_ID>、および<BASE64_SCREENSHOT>を前の応答の値に置き換えます。 モデルが computer_callではなくテキスト応答を返すまで、このサイクルを繰り返します。

クリーンアップ

curl -X DELETE "$FOUNDRY_PROJECT_ENDPOINT/agents/computer-use-agent?api-version=v1" \
  -H "Authorization: Bearer $AGENT_TOKEN"

コンピューター使用ツールでできること

要求と応答のループ (スクリーンショット -> アクション -> スクリーンショット) を統合した後、コンピューター使用ツールはエージェントを支援できます。

  • クリック、入力、スクロール、新しいスクリーンショットの要求などの UI アクションを提案します。
  • 各アクションの後に最新のスクリーンショットを再評価して、UI の変更に適応します。
  • サンドボックス環境のホスト方法に応じて、ブラウザーとデスクトップ UI 間で動作します。

このツールは、デバイスを直接制御しません。 アプリケーションは、要求された各アクションを実行し、更新されたスクリーンショットを返します。

ブラウザーの自動化とコンピューターの使用の違い

次の表に、コンピューター使用ツールと ブラウザーオートメーション ツールの違いをいくつか示します。

機能 ブラウザーの自動化 コンピューター使用ツール
モデルのサポート すべての GPT モデル computer-use-preview モデルのみ
何が起こっているのかを視覚化できますか? いいえ はい
画面を理解する方法 HTML または XML ページを DOM ドキュメントに解析します。 スクリーンショットからの生ピクセル データ
動作方法 モデルによって提供されるアクションの一覧 仮想キーボードとマウス
マルチステップですか? はい はい
インターフェイス ブラウザー コンピューターとブラウザー
自分のリソースを持ち込む必要がありますか? 接続として格納されているキーを持つ独自の Playwright リソース。 追加のリソースは必要ありませんが、サンドボックス環境でこのツールを実行します。

各ツールを使用する場合

必要に応じ、コンピューターの使用を選択します。

  • ブラウザー以外のデスクトップ アプリケーションと対話する
  • スクリーンショットを使用してエージェントに表示される内容を視覚化する
  • DOM 解析が使用できない環境で作業する

必要に応じ、ブラウザーの自動化を選択します。

  • 制限付きアクセス要件なしで Web のみの対話を実行する
  • 任意の GPT モデルを使用する ( computer-use-previewに限定されない)
  • スクリーンショットキャプチャとアクション実行ループの管理を避ける

地域サポート

コンピューター使用ツールを使用するには、 コンピューター使用モデル の展開が必要です。 コンピューターの使用モデルは、次のリージョンで使用できます。

地域 ステータス
eastus2 利用 可能
swedencentral 利用 可能
southindia 利用 可能

コンピューターの使用統合について

コンピューター使用ツールを使用する場合は、次の手順を実行してアプリケーションに統合します。

  1. コンピューター使用ツール、表示サイズ、環境の呼び出しを含む要求をモデルに送信します。 また、最初の API 要求に環境の初期状態のスクリーンショットを含めることもできます。

  2. モデルから応答を受け取ります。 応答にアクション 項目がある場合、それらの項目には、指定された目標に向けて進行するための推奨アクションが含まれます。 たとえば、アクションが screenshot され、モデルは更新されたスクリーンショットを使用して現在の状態を評価したり、マウスを移動する場所を示す X/Y 座標で click したりできます。

  3. コンピューターまたはブラウザー環境でアプリケーション コードを使用してアクションを実行します。

  4. アクションを実行した後、環境の更新された状態をスクリーンショットとしてキャプチャします。

  5. 更新された状態を tool_call_outputとして新しい要求を送信し、モデルがアクションの要求を停止するか停止するまで、このループを繰り返します。

    メモ

    ツールを使用する前に、スクリーンショットをキャプチャし、エージェントによって推奨されるアクションを実行できる環境を設定します。 安全上の理由から、Playwright などのサンドボックス環境を使用してください。

会話履歴を管理する

previous_response_id パラメーターを使用して、現在の要求を前の応答にリンクします。 このパラメーターは、各呼び出しで完全な会話履歴を送信しない場合に使用します。

このパラメーターを使用しない場合は、前の要求の応答出力で返されるすべての項目を入力配列に含めるようにしてください。 この要件には、理由項目 (存在する場合) が含まれます。

安全性チェックとセキュリティに関する考慮事項

警告

コンピューターの使用には、セキュリティとプライバシーに関する大きなリスクとユーザーの責任が伴います。 AI による判断のエラーと、WEB ページ、デスクトップ、または AI が検出したその他の運用環境での悪意のある、または混乱を招く命令の存在の両方が、ユーザーまたは他のユーザーが意図しないコマンドを実行する原因になる可能性があります。 これらのリスクにより、ユーザーまたは他のユーザーのブラウザー、コンピューター、および AI がアクセスできるアカウント (個人、財務、エンタープライズ システムなど) のセキュリティが損なわれる可能性があります。

機密データや重要なリソースにアクセスできない仮想マシンでコンピューター使用ツールを使用します。 ユース ケースを選択するときの目的の用途、機能、制限事項、リスク、および考慮事項の詳細については、「Azure OpenAI の透明性に関するメモを参照してください。

API には、迅速な挿入とモデルの間違いから保護するための安全性チェックがあります。 これらのチェックには次のものが含まれます。

悪意のある命令検出: システムはスクリーンショット画像を評価し、モデルの動作を変更する可能性のある敵対的なコンテンツが含まれているかどうかを確認します。

関係のないドメイン検出: システムは current_url パラメーター (指定されている場合) を評価し、会話履歴を使用して現在のドメインが関連しているかどうかを確認します。

機密性の高いドメインの検出: システムは、 current_url パラメーター (指定されている場合) をチェックし、ユーザーが機密ドメインに存在することが検出されると警告を発生させます。

上記のチェックの 1 つ以上がトリガーされた場合、モデルは、computer_call パラメーターを使用して次のpending_safety_checksを返したときに安全性チェックを発生させます。

"output": [ 
    { 
        "type": "reasoning", 
        "id": "rs_67cb...", 
        "summary": [ 
            { 
                "type": "summary_text", 
                "text": "Exploring 'File' menu option." 
            } 
        ] 
    }, 
    { 
        "type": "computer_call", 
        "id": "cu_67cb...", 
        "call_id": "call_nEJ...", 
        "action": { 
            "type": "click", 
            "button": "left", 
            "x": 135, 
            "y": 193 
        }, 
        "pending_safety_checks": [ 
            { 
                "id": "cu_sc_67cb...", 
                "code": "malicious_instructions", 
                "message": "We've detected instructions that may cause your application to perform malicious or unauthorized actions. Please acknowledge this warning if you'd like to proceed." 
            } 
        ], 
        "status": "completed" 
    } 
]

続行するには、次の要求の acknowledged_safety_checks として安全性チェックに合格する必要があります。

"input":[ 
        { 
            "type": "computer_call_output", 
            "call_id": "<call_id>", 
            "acknowledged_safety_checks": [ 
                { 
                    "id": "<safety_check_id>", 
                    "code": "malicious_instructions", 
                    "message": "We've detected instructions that may cause your application to perform malicious or unauthorized actions. Please acknowledge this warning if you'd like to proceed." 
                } 
            ], 
            "output": { 
                "type": "computer_screenshot", 
                "image_url": "<image_url>" 
            } 
        } 
    ]

安全チェックの取り扱い

pending_safety_checksが返されるすべての場合は、エンド ユーザーにアクションを渡して、適切なモデルの動作と精度を確認します。

malicious_instructions irrelevant_domain: エンド ユーザーはモデルアクションを確認し、モデルが意図したとおりに動作することを確認する必要があります。

sensitive_domain: エンド ユーザーがこれらのサイトでモデル アクションをアクティブに監視していることを確認します。 この "ウォッチ モード" の正確な実装はアプリケーションによって異なりますが、たとえば、サイト上でユーザーのインプレッション データを収集して、アプリケーションに対するアクティブなエンド ユーザーエンゲージメントがあることを確認できます。

トラブルシューティング

問題 原因 解決方法
応答に computer_call が表示されません。 エージェントがコンピューター使用ツールで構成されていないか、展開がコンピューター使用モデルではないか、プロンプトに UI 操作が必要ありません。 エージェントに computer_use_preview ツールがあり、デプロイが computer-use-preview モデルであり、プロンプトに UI アクション (種類、クリック、またはスクリーンショット) が必要であることを確認します。
サンプル コードは、ヘルパー ファイルまたはスクリーンショットが見つからない場合に失敗します。 抜粋では、このドキュメント リポジトリに含まれていないヘルパー ユーティリティとサンプル イメージを参照します。 ヘルパーとアセットが想定される相対位置に残るように、「管理されている SDK サンプルを実行する」セクションで、保守されているサンプルの 1 つを複製します。 TypeScript の場合は、独自のヘルパーとスクリーンショットアセットを指定します。
ループは反復制限で停止します。 タスクに必要なターンが増えるか、アプリがモデルが要求するアクションを適用していません。 イテレーションの制限を増やし、コードが要求されたアクションを実行し、ターンのたびに新しいスクリーンショットを送信することを確認します。
pending_safety_checksを受け取ります。 サービスによって潜在的なセキュリティ リスク (プロンプトインジェクションや機密性の高いドメインなど) が検出されました。 自動化を一時停止し、エンド ユーザーに要求の確認を要求し、次のacknowledged_safety_checkscomputer_call_outputを送信した後にのみ続行します。
このモデルでは、進行せずに "スクリーンショットを撮る" が繰り返されます。 スクリーンショットが更新されていない、品質が低い、または関連する UI の状態が表示されない。 各アクションの後に新しいスクリーンショットを送信し、必要に応じより詳細な画像を使用します。 スクリーンショットに関連する UI が含まれていることを確認します。
computer-use-previewモデルを要求したときにアクセスが拒否されました。 アクセスに登録していないか、アクセス権が付与されていません。 申請フォームを送信し、承認を待ちます。 確認のためにメールを確認します。
エンコード エラーのスクリーンショット。 イメージ形式がサポートされていないか、base64 エンコードの問題。 PNG または JPEG 形式を使用します。 破損することなく、適切な base64 エンコードを確認します。 画像の寸法が display_widthdisplay_heightと一致するかどうかを確認します。
アクションは間違った座標で実行されます。 スクリーンショットと実際の表示の間の画面解像度の不一致。 display_width display_heightComputerUsePreviewToolが実際の画面解像度と一致していることを確認します。
モデルは UI 要素を幻覚します。 スクリーンショットの品質が低すぎるか、ターン間で UI が変更されました。 解像度の高いスクリーンショットを使用します。 各アクションの直後に新しいスクリーンショットを送信します。 アクションとスクリーンショットの間の遅延を減らします。