Desktop Takeover
概要
エージェントがデスクトップを操作してGUIタスクを完了するための全フローを統一的にオーケストレーションします:最初に最適なルートを判断し、次にcomputer useの権限を確認し、最後にタスクをディスパッチして検証します。computer useは最後の手段であり、最初の選択肢ではありません。タスクがGUIでのみ完了できる場合にのみ使用します。
ワークフロー判断ツリー
デスクトップ操作のリクエストを受け取ったら、以下の順序でルートを判断し、該当した時点で停止します:
1. コネクタ/MCPで直接到達可能?
対象アプリに接続済みのコネクタがある(GitHub、WPSナレッジベース、企業微信など)
→ コネクタを使用、GUIには触れない
例:GitHub PRの確認 → ghコネクタ;WPSライブラリのドキュメント読み取り → wps-knowledgebase
2. 純粋なブラウザ操作?
タスクがWebページ上で発生する(フォーム入力、Webクリック、スクリーンショット比較)
→ browser-useスキルを使用、システムGUIには触れない
例:Webサイトにログインして設定変更 → browser-use
3. Office/WPSファイルの読み書き?
対象がdoc/docx/xls/xlsx/ppt/pptxファイルの内容
→ officeスキル群(workbuddy-docx / sheetagent / local-office-edit)を使用
例:Wordの表を変更 → local-office-edit
4. コマンドライン/スクリプトで到達可能?
タスクが本質的にファイル操作、データ処理、システム設定であり、CLIまたはスクリプトのパスがある
→ Bash/スクリプトを直接使用
例:一括リネーム → スクリプト;システム情報確認 → コマンド
5. 上記すべてが該当しない → computer useデスクトップ操作
タスクがGUIアプリケーションのUI要素(ボタン、メニュー、非Webウィンドウ)を操作する必要がある
例:ある国産ソフトウェアでGUIエントリしかない設定項目を変更
判断原則:レベルが下がるごとに、信頼性と速度が低下し、不確実性が増大します。GUI操作には、要素の特定、ウィンドウフォーカス、UI言語など複数の不確実性が伴うため、最後の手段です。
注意:第5レベルの可視性依存(ウィンドウ列挙 + スクリーンショット)は、台前調達が有効な場合、構造的な弱点です(Pre-flightの第2項目と「不可視ウィンドウの落とし穴」を参照)。AX系ツール(アクセシビリティツリー認識)は論理的なジオメトリを読み取り、台前調達による縮小・移動の影響を受けないため、代替/補完ルートとなります。このスキルに内蔵されたAX代替ツール:
tools/axctl(使用方法は「AX代替層」の章を参照)。
ルーティング時に、対象アプリにコネクタがあるかどうか不明な場合は、まず list_installed_plugins を確認し、記憶に頼って判断しないでください。
事前チェック:権限と環境の二重チェック
computer useを使用する前に、2つの事前チェックを実行する必要があります。どちらも省略できません:
1. 権限チェック
gui_permission_status を呼び出します:
all_granted: true→ 2番目の事前チェックに進む- 権限不足 → references/authorization-macos.md のフローに従ってユーザーの権限設定をガイド(macOS)
- Windows → 現在のバージョンはmacOSのみをサポートしていることを明確にユーザーに伝える
2. 台前調達の事前チェック(必須、ユーザーが台前調達を有効にしていることが多い)
defaults read com.apple.WindowManager GloballyEnabled を実行:
- 戻り値が
1(有効)→ ディスパッチ前に必ずopen -a <アプリケーション名>で対象アプリケーションをアクティブ化して現在のステージに戻します(一瞬フォーカスが奪われるため、事前にユーザーに伝えます)。その後gui_list_windowsで対象ウィンドウが表示されていることを確認してからcreate_taskを実行します。アクティブ化後もウィンドウがリストにない場合は、すぐに「不可視ウィンドウの落とし穴」のトラブルシューティングシーケンスに進みます。create_taskを再試行したり、アプリケーションの障害と判断したりしないでください。 - 戻り値が
0(無効)→ 通常のディスパッチフローを実行
この事前チェックにより、台前調達の落とし穴を「事後診断」から「事前回避」に昇格させます。台前調達はmacOS 15+のユーザーには珍しくなく、有効にしているユーザーにとってこの手順は毎回のディスパッチにおけるデフォルトパスであり、例外ではありません。アクティブ化と表示のメカニズムは同日にmacOS 27.0.1で検証済みですが、「初回アクティブ化で定着しない」と「表示後に戻る」という2つの新しい詳細があります。詳細は「不可視ウィンドウの落とし穴」の27再検証セクションを参照してください。
タスクディスパッチ
権限が準備できたら、内蔵のcomputer useスキルの標準ワークフローに従って実行します:
gui_list_windowsで対象アプリケーションのウィンドウを特定します。見つからない場合はopen_appで起動します。- 起動後の可視性を検証:
open_app後に再度gui_list_windowsを実行し、ウィンドウが実際にリストに表示されていることを確認します。表示されない場合は「アプリケーションが壊れた」と結論付けずに、「不可視ウィンドウの落とし穴」を確認します。 - 台前調達が有効な場合(事前チェックで確認済み):先に
open -aで対象アプリケーションをアクティブ化してからディスパッチします。Pre-flightの第2項目を参照。ここでは再判断しません。 create_task(window_id, task)でタスクをディスパッチします。
不可視ウィンドウの落とし穴(台前調達シナリオ)
結論の適用範囲:macOS 15の対照実験で初めて確立。macOS 27.0.1でも再検証済み(Swiftデュアルチャネルプローブ + AX APIネイティブバイナリ実測、メカニズムは確認され、新しい詳細も発見。以下を参照)。AX層の結論は、27.0.1で権限付与後に実測確認済み(AXError=0パス)。もはや推測に基づくものではありません。
トリガー条件:台前調達(Stage Manager)がアクティブであること。バックグラウンド起動自体とは関係ありません。有効な場合、現在のステージにないアプリケーションのウィンドウは実在するが、ウィンドウ列挙とスクリーンショットで正常にキャプチャできません。プロセスは生きており、ウィンドウは作成されていますが(例:Cmd+Nが機能する)、gui_list_windows は正常なウィンドウを表示しません。アプリケーションをアクティブ化すると(ウィンドウが現在のステージに戻る)、ウィンドウはすぐに表示されます。
macOS 27.0.1 再検証の新発見:
- サムネイルバーのメカニズムの可視化:非アクティブなアプリケーションのウィンドウは、サイドのサムネイル小窓に縮小されます(実測ではCalculatorのメインウィンドウが39×100ptに縮小され左端に配置され、さらに4つの全幅34ptのステージプレースホルダーウィンドウが派生しました)。
gui_list_windowsが「通常サイズのウィンドウ」でフィルタリングしている場合、これらのサムネイルウィンドウは見逃されたり誤判定されたりする可能性があります。 - アクティブ化による表示は依然として有効だが、「初回アクティブ化で定着しない」現象がある:実測では、最初の
open -a後もメインウィンドウがサムネイル状態のままでした(他のアプリケーションがフォアグラウンドを占有している場合)。2回目のopen -aで初めてフルサイズ (405, 517, 230×408) に拡大されました。対処:アクティブ化後はすぐにgui_list_windowsで検証し、表示されない場合は再度open -aを実行(最大2回)。それでも表示されない場合のみ、トラブルシューティングシーケンスに進む。 - 表示後に戻る可能性がある:フォアグラウンドが他のアプリケーションに奪還されると、約5秒以内にウィンドウが再びサムネイル状態に縮小される可能性があります(実測で再現)。推論:スクリーンショットによる検収には時間枠が存在します。
create_taskの実行中にフォアグラウンドが奪われた場合、タスク自体は影響を受けませんが、gui_screenshotが縮小後に撮影された場合、対象ウィンドウは画面に表示されません。対処:スクリーンショット撮影直前にフォアグラウンドの切り替えが発生した場合は、先にopen -aを実行してから撮影します。 - CGWindowListチャネルは影響を受けない:
optionOnScreenOnlyと全量リストの両方でウィンドウを列挙できます(タイトルのみ画面録画権限が必要)。ただし、onScreenOnlyリストに表示されるのはサムネイルウィンドウであり、メインウィンドウではないことに注意してください。ウィンドウ座標に依存してクリック位置を特定するツールは、間違った位置をクリックする可能性があります(実際のボタンではなくサムネイルをクリック)。 - AXツリーは論理ジオメトリを読み取り、サムネイルによる移動の影響を受けないが、ブラインドスポットがある(権限付与後の27.0.1実測):AXが返すウィンドウフレームはフルサイズの論理座標です(例:(405,517,230×408))。同時刻のCGWindowListレンダリング状態は39×100のサムネイルウィンドウです。台前調達によるジオメトリの移動はAXを騙せません。ただしブラインドスポット:新しく起動され、一度もステージに上がったことのないウィンドウの場合、AXツリーは windows=0 を報告します。ステージに上がった後にバックグラウンド起動すると、AXは継続して表示されます。推論:AX認識も無条件に影響を受けないわけではなく、初回起動のアプリケーションは先にアクティブ化してステージに上げる必要があります。また:AX論理座標に従ってスクリーンに合成マウスイベントを送信すると、間違ったアプリケーションをクリックする可能性があります(論理位置 ≠ 現在のレンダリング位置)。AX系ツールでアクションを実行する場合は、AXPressなどのアクセシビリティアクションAPI(axctlなど)を使用する必要があり、座標クリックは使用できません。
判断順序(対象アプリケーションがウィンドウリストにない場合):
- まずプロセスが生きているか確認(
pgrep):生きている → 可視性の問題である可能性が高く、アプリケーションの障害ではない - ユーザーが台前調達を有効にしているか確認(macOS 15+、
defaults read com.apple.WindowManager GloballyEnabled、1=有効):有効 → ステップ3に進む。無効 → ウィンドウが突然存在しなくなったか、他の理由の可能性がある - アプリケーションをアクティブ化して表示:
open -a <アプリケーション名>(一瞬フォーカスが奪われるため、事前にユーザーに伝える)。27では初回アクティブ化で定着しない可能性があるため、アクティブ化後すぐに検証し、表示されない場合はもう一度アクティブ化する(上限2回) - 再度
gui_list_windowsを実行すると、通常はwindow_idを取得できる
追加のシグナル:台前調達が有効な場合、open_app は通常window_idを取得できません(hintを返して2回目の列挙を促します)。無効な場合は正常にwindow_idを返します。
重要な推論:
見えるウィンドウがないという報告は、ウィンドウが存在しないことを意味するのではなく、ましてや以前の操作が失敗したことを意味しません。以前「失敗」したタスクが実際には成功している可能性があります(ウィンドウは作成されているが、見えないだけ)。- ダイアログタイプのウィンドウ(「開く」ファイルダイアログなど)がタスク自体によって閉じられた後、そのwindow_idは無効になり、後続のスクリーンショットでエラーが発生する可能性があります。これは正常な動作であり、再度列挙して新しいIDを取得してください。
- 一部のアプリケーション(テキストエディットなど)は、ドキュメントなしで起動した場合、デフォルトでウィンドウがありません。これは正常な動作であり、ファイルを指定して開く必要があります。
タスク記述の三段階法(成否の鍵)
task パラメータは以下の3つの部分を含む必要があります:
目標:何を完了するかを段階的に説明
境界:触れてはいけないものを明確に指定(例:「履歴リスト内のエントリをクリックしないでください」)
失敗処理:操作が応答しない場合、何が起こったかを正確に記録し、次のステップに進む。再試行したり方法を変更したりしない
失敗処理ルールは省略不可です。省略すると、単一の失敗が繰り返し再試行を引き起こし、全体のステップ数を消費します。
記述にはピクセル座標や数値位置を含めないでください。対象は画面に表示されるテキストとコントロール名で指定します。
例
ユーザーリクエスト:「XXアプリを開いて、エクスポート形式をCSVに変更して」
目標:1. メニューバーまたはツールバーにある「設定」または「Preferences」エントリを見つけてクリック
2. 設定パネルで「エクスポート形式」または「Export Format」オプションを見つける
3. その値をCSVに変更する
4. 設定を保存してパネルを閉じる
境界:他の設定項目は一切変更しないこと。「リセット」ボタンをクリックしないこと
失敗処理:上記のコントロールが見つからない場合、実際に見えるコントロール名を記録してタスクを終了する。推測でクリックしないこと
AX代替層(axctl)
内蔵のcomputer useが利用できない場合(有効でない、gui_*ツールがない、タスクが小さすぎてディスパッチする価値がない)、または意味レベルの要素操作が必要な場合、このスキルに内蔵されたAX代替ツール tools/axctl を使用します。純粋なAccessibility API実装であり、マウスに触れず、フォーカスを奪わず、AppleEventsサンドボックスの制限を受けません(WorkBuddyサンドボックスはSystem Eventsへの制御イベント送信を禁止しています。osascriptルートは廃止されたため、再試行しないでください)。
場所とインストール:バイナリ tools/axctl、ソースコード tools/axctl.swift(Swift単一ファイル)。どちらもスキルと共に配布されます。初回使用前に sh tools/install.sh を実行します:swiftcが検出された場合はその場でコンパイル(推奨、ソースコードを監査可能、マシンアーキテクチャに最適化)。それ以外の場合は、パッケージに同梱されたプリコンパイル済みバイナリを使用します(Apple Siliconのみ)。ソースコードを変更した後、toolsディレクトリ内で swiftc -O -o axctl axctl.swift を実行して再コンパイルします。
前提条件:ホストは「アクセシビリティ」TCC権限を保持している必要があります(システム設定 → プライバシーとセキュリティ → アクセシビリティでホストをチェックし、ホストを再起動すると有効になります)。AX呼び出しがAXError=0を返すことを準備完了のフラグとします。
サブコマンド
axctl list <bundle-id|pid> 列ウィンドウ:タイトル + 論理ジオメトリフレーム
axctl tree <target> [depth] 読UIツリー:ロール/タイトル/説明/値/フレーム(デフォルト depth=2)
axctl actions <target> <タイトル> 一致する要素の利用可能なアクションリストを表示
axctl press <target> <タイトル> AXPressを実行(意味クリック、要素レベル、座標不要)
axctl activate <target> アプリケーションをアクティブ化(NSRunningApplication.activate)
<target> は、バンドルID(推奨、例:com.apple.calculator)、数値PID、またはローカライズされたアプリケーション名(小文字で一致。日本語システムでは「Calculator」ではなく「計算機」。名前の一致は間違いやすいため、バンドルIDを優先)をサポートします。
使用ルール
- 要素検索:まず
treeを実行するか、既知のボタンタイトルで直接actionsを実行してAXPressの存在を確認してからpressを実行します。pressはAXPressアクションを持つ要素にのみ有効です。メニュー項目はAXPickです。タイプごとに判断します。 - アクションの検証:pressが
PRESSEDを返した後、treeを使用して対象要素または関連表示領域の新しい値を読み取り、証拠とします(電卓の実測例:press "3" 後、StaticText値が3になる)。computer useのスクリーンショット検収と同様、テキストによる自己申告は証拠として十分ではありません。 - 台前調達シナリオ:AXツリーは論理ジオメトリを読み取るため、サムネイル状態のウィンドウも読み取りおよび操作が可能です(実測済み)。ただし、新しく起動されステージに上がっていないアプリケーションのAXツリーは空です。先に
axctl activateまたはopen -aでステージに上げてから操作します。 - 適用範囲:axctlは要素レベルの読み書き(ボタン/メニュー/テキストフィールド)に適しています。アプリケーション間のメニューバークリック、システムレベルのキーボード/マウスシミュレーション、または複雑なマルチステップGUIフローが必要な場合は、内蔵のcomputer useディスパッチを使用します。
- 既知の制限:UI変更のリスニングはありません(axmcpのobserve_changes機能。上流がSwift 6.4に適応した後に再評価)。単一要素の単一操作のみで、バッチトランザクションはありません。
実測記録(macOS 27.0.1、台前調達有効)
axctl press com.apple.calculator "3" → PRESSED path=w/0/0/0/1/0/15 → tree で読み取ったAXStaticText値が 3。ツリー読み取り、位置特定、意味クリック、効果検証の4サイクルすべてが成功。
結果検証
GUIエージェントのテキストによる自己申告は完了の証拠として十分ではありません。古いインターフェース状態が残っている場合、成功と誤認される可能性があります。以下の手順を実行する必要があります:
- タスクが
done=trueを返したら、gui_screenshot(window_id)を呼び出して最終スクリーンショットを取得する - スクリーンショットの内容で目標が達成されたかどうかを判断する
- ユーザーに報告する際、結論の根拠がスクリーンショットであることを明記する
各ラウンド間では、デフォルトでスクリーンショットを撮影しないでください(continue_task の戻り値には実行履歴が含まれています)。エージェントが連続して数ラウンドにわたってreasoning/action_descに変化がない場合にのみ、補完的に1回撮影してスタックしていないかどうかを判断します。
トラブルシューティングクイックリファレンス
| 症状 | 対処 |
|---|---|
permission_denied | references/authorization-macos.md を参照 |
| 連続して複数ラウンド同じステップで停止 | continue_task に hint パラメータを指定し、コントロールの正確な表示テキストを提供 |
| 画面に変化がないが成功を報告 | gui_screenshot に依存。window_idが正しいことを確認 |
conflict | そのウィンドウには既にタスクがあるため、先に delete_task を実行 |
window_not_found | ウィンドウが閉じられたかIDが期限切れ。再度 gui_list_windows を実行 |
見えるウィンドウがない(プロセスが生きている場合) | 台前調達がアクティブでウィンドウをキャプチャできない:open -a でアクティブ化 → すぐに再列挙。表示されない場合はもう一度アクティブ化(27では初回アクティブ化で定着しない可能性があるため、上限2回)。「不可視ウィンドウの落とし穴」を参照(15と27.0.1の両方で実験的に確認済み) |
| スクリーンショットに写ったウィンドウが異常に小さい/画面端に貼り付いている | 対象ウィンドウが台前調達のサムネイル状態にある(27再検証で発見):先に open -a でアクティブ化してフルサイズに戻してから撮影。「不可視ウィンドウの落とし穴」の27再検証セクション第1、3条を参照 |
ステータスが call_user | 人間の介入が必要。reasoning をユーザーに伝え、continue_task は呼び出さない |
プラットフォームサポート
- macOS:完全サポート。認証フローについては references/authorization-macos.md を参照
- Windows:未検証。現在のバージョンではサポートを保証しません。Windows環境に遭遇した場合は、この制限をユーザーに正直に伝え、macOSの権限モデルを適用しようとしないでください
リソース
references/authorization-macos.md— macOS認証の全フロー。実測による注意点(チェック後も有効にならない、Quit & Reopenダイアログなど)を含むtools/axctl— AX代替ツール(ソースコードtools/axctl.swiftは同じディレクトリ。初回使用時はsh tools/install.shを実行)。使用方法は「AX代替層」の章を参照