agent-desktop-ffi について
agent-desktop-ffi は、C-ABI から PlatformAdapter の操作を呼び出すインターフェースです。デスクトップの観察と操作をネイティブライブラリ経由で統合する開発者向けで、参照ベースの操作、セッション、構造化された結果に対応します。
主な機能
- 01C-ABI によるアダプター操作
- 02スナップショットと参照ベースの操作実行
- 03セッション単位の参照保存
- 04厳密なターゲット指定とネイティブハンドル
- 05構造化エラー、トレース、待機
活用シーン
- 01C ホストからデスクトップ自動化を呼び出す
- 02限定参照による観察・操作ループの構築
- 03操作結果とエラー詳細の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vercel-labs/ agent-desktop --skill agent-desktop-ffiインストール後、Claude Code で/agent-desktop-ffiを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/build-and-link.mderror-handling.mdownership.mdthreading.md詳細
agent-desktop-ffi
PlatformAdapter の操作に C-ABI から直接アクセスできます。release-ffi プロファイルで cdylib をビルドします:
cargo build --profile release-ffi -p agent-desktop-ffi
出力されるのは target/release-ffi/libagent_desktop_ffi.dylib(Linux では .so、Windows では agent_desktop_ffi.dll)と、コミット済みの C ヘッダー crates/ffi/include/agent_desktop.h です。デフォルトの release プロファイルでは panic = "abort" が使用されます。extern "C" 関数内で Rust のパニックが発生すると、ホストプロセスに SIGABRT が送られます。release-ffi では、パニックトラップに必要な panic = "unwind" が維持されます。
必要に応じて読み込む、4 つの参照トピック:
- ownership.md:FFI が返す各ポインターについて、誰が確保し、誰が解放するかを説明します。
- error-handling.md:errno 形式の最終エラーに関する契約、エラーコード、列挙値の検証、パニック境界を説明します。
- threading.md:ホストスレッドの契約、スレッド間およびプロセス間の変更順序、アダプターにバインドされたネイティブハンドル、AXIsProcessTrusted の継承を説明します。
- build-and-link.md:ビルド済みアーカイブ、ABI ハンドシェイク、構造体サイズの検証、C と Python の例を説明します。
観察・操作のワークフロー(標準経路)
ad_init(AD_ABI_VERSION_MAJOR) // verify header ↔ dylib match
adapter = ad_adapter_create_with_session("s1") // or ad_adapter_create()
rc = ad_snapshot(adapter, "Finder", 0, 10, false, false, &json_out)
// parse json_out: locate snapshot-qualified refs in data.tree
ad_free_string(json_out)
// build action:
AdAction act = {0}; act.kind = AD_ACTION_KIND_CLICK;
rc = ad_execute_by_ref(adapter, "@s8f3k2p9:e5", &act, 0, &result_out)
ad_free_string(result_out)
ad_adapter_destroy(adapter)
ad_snapshot は CLI のエンベロープ {version, ok, command, data} を返します。data.tree には、インタラクティブ要素を参照するスナップショットに紐づいた参照が含まれます。ツリーを信頼する前に data.complete を確認してください。false は観察の予算が尽きてツリーが不完全であることを意味し、エラーではありません。ad_snapshot は常に app のフォーカスされたウィンドウを対象とします。ウィンドウの指定、スケルトンモード、--root による掘り下げは ABI では公開されません。単独の @eN 参照を渡すと AD_RESULT_ERR_INVALID_ARGS が返されます。
主な制約
-
ABI ハンドシェイク。 ライブラリをロードした後に
ad_init(AD_ABI_VERSION_MAJOR)を 1 回呼び出してください。不一致の場合はAD_RESULT_ERR_INVALID_ARGSが返されるため、処理を中止してください。ad_abi_version()は表示用にライブラリのメジャーバージョンを返します。シンボルの削除またはレイアウトの変更があるとメジャーバージョンが上がります。新しいad_*シンボルとエラーコードの追加は後方互換です。リンクするlibagent_desktop_ffiのバージョンは正確に固定してください。 -
セッションアダプター。
ad_adapter_create_with_session("session-id")は、CLI の--session <id>と同様に、参照マップの永続化範囲をセッションの名前空間に限定します。ID は ASCII の英数字、-、_のいずれかで構成される 1~64 文字です。ID が null の場合はad_adapter_create()と同じ動作になります。無効な ID の場合は null が返されます(ad_last_error_*を読み取ってください)。 -
参照によるアクション。
ad_execute_by_refは主要なアクションのエントリーポイントです。RefStore を読み込み、参照を厳密に解決します(スナップショットに該当する参照がない場合、または要素が変更されている場合はSTALE_REF、候補が複数ある場合はAMBIGUOUS_TARGET)。次に、実行時の操作可能性を事前確認します(表示状態、安定性、有効状態、サポート対象のアクション、ポリシー、編集可能性)。その後、アクションをディスパッチします。対象が無効または未サポートの場合、プラットフォームを呼び出す前に失敗します。AD_RESULT_ERR_ACTION_FAILEDの場合、確認レポートはad_last_error_details()に JSON 形式で格納されます。事前確認の前に 5000 ms 自動で待機します。ad_execute_by_ref_timeoutではtimeout_msを指定できます(-1= デフォルトの 5000 ms、0= 1 回のみ実行)。PressKeyのデフォルトはfocus_fallbackです。それ以外のすべてのアクション(TypeTextを含む)のデフォルトはheadlessです。カーソルを動かさずにフォーカスすることを許可するにはAD_POLICY_KIND_FOCUS_FALLBACK(1)を渡してください。物理的なカーソル操作とキーボード入力を許可するにはAD_POLICY_KIND_HEADED(2)を渡してください。ad_execute_ref_action_exact_with_policyはAdExactRefEntryに対して同じ事前確認を実行します。 -
世代安全な直接 API。 すべての直接ターゲット指定関数は、プロセス世代の証拠を受け取ります。
AdExactRefEntry、AdExactWindowInfo、ad_list_windows_exact、ad_launch_app_exact、およびその他の*_exactシンボルが該当します。AdRefEntry、AdWindowInfo、AdSurfaceInfoは、exact 構造体に埋め込まれたフィールドとしてのみ存在します。ad_list_surfaces_exactはサーフェスのidを保持します。AD_EXACT_SURFACE_INFO_VERSION2 以降では、AdExactSurfaceInfo.unclassifiedはプローブで読み取れなかったサーフェスの種類(例:sheet,menu)を示すか、null になります。リストにある種類の横にsheetまたはmenuがない場合、それは不在ではなく不明を意味します。これを設定するのは Windows アダプターのみです。macOS と Linux では null が返されます。 -
ネイティブハンドル。
ad_resolve_element_exactとad_find_exactはAdNativeHandleを返します。ad_execute_action(ヘッドレス、事前チェックなし)とad_execute_action_with_policyは、ref-action パイプラインを経由せず、ハンドルに直接作用します。すべてのプラットフォームで、ad_adapter_destroyの前に、同じアダプターとスレッド上で、すべてのハンドルをad_free_handle(adapter, &handle)で解放してください。これによりhandle.ptrがゼロになるため、2 回目の呼び出しは何もしません。 -
アクション結果。
AdActionResult.stepsは、アクティベーションチェーンアクションの CLIsteps配列を反映します。各AdActionStepには、labelとoutcomeの各文字列、mechanism(AD_STEP_MECHANISM_SEMANTIC_API= 1 またはAD_STEP_MECHANISM_PHYSICAL_SYNTHETIC= 2。has_mechanismが有効な場合のみ有効)、およびverified(has_verifiedが有効な場合のみ有効)があります。AdActionResult.dispositionは、ad_last_error_delivery_semanticsと同じ配信/再試行の組み合わせを保持します。結果はad_free_action_result(&out)で解放してください。 -
ディスプレイの検出。
AdScreenshotTarget.screen_indexを使用する前に、ad_list_displaysを呼び出してください。リストの順序はスクリーンショットのインデックス順です。各AdDisplayInfoには、安定したディスプレイ ID、境界、プライマリフラグ、スケールが含まれます。リストはad_display_list_freeで解放してください。 -
エラー。 呼び出しが失敗すると、スレッドローカルの最終エラー状態が設定されます。次に失敗する呼び出しの前に、
ad_last_error_*アクセサーで読み取ってください。ad_last_error_details()は構造化 JSON を返します(ACTION_FAILEDの場合は実行可能性レポート、AMBIGUOUS_TARGETの場合は候補の概要)。これにはユーザーの画面に表示された要素名、値、ウィンドウタイトルが含まれることがあるため、共有ログには含めないでください。ad_last_error_delivery_semanticsは、失敗したアクションが配信されたかどうか、および再試行が安全かどうかを報告します。無効な enum 判別値はAD_RESULT_ERR_INVALID_ARGSを返します。error-handling.md を参照してください。 -
スレッド処理。 エントリーポイントは、任意のホストスレッドから呼び出せます。ネイティブハンドルは、それを作成したアダプターとスレッド上に保持してください。スレッド間では、修飾済み ref を渡してください。デスクトップの変更操作は CLI と同じプロセス間インタラクションリースを取得します。読み取り操作はリースを取得せず、有限の期限を持ちます。読み取り/読み取り、読み取り/変更、変更/変更のマトリックスについては、threading.md を参照してください。
-
トレース。 ファイルトレース(CLI
--traceと同じ JSONL 契約。セグメントにはevent、ts_ms、seq、および秘匿化されたフィールドが含まれます)は、アダプターの作成前にsession startで作成された、またはディスク上に同等のマニフェストがある、trace: onを設定したマニフェストをセッションが持つ場合にのみ有効です。ad_adapter_create_with_sessionだけでは何も書き込みません。各 OS プロセスは単一のセグメント~/.agent-desktop/sessions/<id>/trace/<pid>-<procTs>.jsonlに追記し、長時間稼働するホストはそれを再利用します。ad_trace_show(JSON エンベロープ)とad_trace_export(自己完結型 HTML ファイル)は、アダプターセッションの統合タイムラインを読み取ります。limitの-1は CLI のデフォルトを意味します。 -
ログコールバック。
ad_set_log_callback(cb)は、セッションマニフェストに関係なく、プロセス全体で使用するコールバックを 1 つ登録します。後続のad_*呼び出し内で同じスレッドから出力されるtracingイベントを JSON として受け取ります。FFI がホストプロセスのグローバルな tracing サブスクライバーをインストールしたり、置き換えたりすることはありません。cbは、呼び出し中のみ有効なconst char *msgと、int32_t型のレベル(1=ERROR ~ 5=TRACE)を受け取ります。登録解除するにはNULLを渡します。機密性の高いフィールド値(password、token、text など)は{"redacted":true}に置き換えられます。コールバックから C ABI をまたいでアンワインドしてはいけません。違反するとホストが異常終了する可能性があるため、内部で C++ 例外と Rust パニックを捕捉してください。複数のホストスレッドから同時に呼び出されることがあり、NULLで登録解除した後もしばらく呼び出される場合があります。コールバックと、コールバックがキャプチャするデータは、プロセスのライフタイム全体にわたって有効な状態にしてください。 -
待機。
ad_wait(adapter, args, &out)は CLI のwaitコマンドを実行します。mode.pause(AdOptionalU64、ミリ秒)、mode.element、mode.window(そのタイトルのウィンドウを待機)、mode.text、またはmode.surfaces.menu、.menu_closed、.notificationのいずれかを設定します。predicateグループ(predicate、value、action、count)と、scope.timeout_ms/scope.appを追加します。CLI のイベント待機(--event、--window-id)は公開されていません。AdWaitArgsをゼロ初期化し、呼び出しの前に構造体サイズをAD_WAIT_ARGS_SIZE/ad_wait_args_size()と照合してください。出力は{version, ok, command, data}エンベロープで、ad_free_stringで解放します。ad_waitはscope.timeout_msミリ秒まで呼び出し元のスレッドをブロックします。呼び出し中の wait があっても、並行して実行されるad_adapter_destroyによって無効になることはありません。 -
テキスト入力のプライバシー。 macOS では、フォーカスフォールバックまたはヘッドありのテキスト挿入において、非 ASCII テキストにクリップボードが一時的に使用される場合があります。機密性の高いテキストについては、対象が値の設定に対応している場合、
AD_POLICY_KIND_HEADLESSとAD_ACTION_KIND_SET_VALUEの使用を推奨します。 -
ad_get_tree_exactとad_snapshotの違い。ad_get_tree_exactは、生のフラットな幅優先ツリーを返します。参照も参照マップの永続化もなく、JSON エンベロープもありません(ad_free_treeで解放します)。カスタムの走査や UI の調査に使用してください。ad_execute_by_refを通じてアクションを実行する観察・操作型のエージェントでは、ad_snapshotから始めてください。