AI 에이전트가 데스크톱을 조작하는 방식은 두 가지로 나뉜다. 스크린샷을 보고 픽셀 좌표를 계산하는 방식, 그리고 OS 접근성 API를 통해 UI 요소의 구조를 읽어 의미 있는 단위로 작동하는 방식이다. Vercel Labs의 agent-desktop은 후자를 선택했다. 21,500개 이상의 star를 얻은 이 프로젝트는 macOS, Windows, Linux에서 접근성 트리를 JSON으로 추출하고, 요소별 참조 ID(ref)로 클릭·입력·검증을 수행하는 CLI다.

모델이 내장되어 있지 않다는 점이 중요하다. agent-desktop은 도구를 제공할 뿐, 관찰·실행·검증 루프를 구성하는 것은 호출하는 에이전트다. 이 글은 저장소와 문서를 검토한 결과다. CodeBridge는 macOS에서 직접 스냅샷을 재현하지 않았다.

스크린샷 대신 접근성 트리

기존 컴퓨터 사용 에이전트는 화면을 캡처하고, OCR이나 객체 탐지로 버튼을 찾아, 화면 좌표로 클릭한다. 이 방식은 해상도가 바뀌면 좌표가 깨지고, 동적 UI에서는 프레임마다 위치가 달라진다.

agent-desktop은 다르다. macOS에서는 AX API, Windows에서는 UI Automation, Linux에서는 AT-SPI를 통해 대상 앱의 접근성 트리를 읽는다. 각 요소는 역할(role), 이름(name), 액션 가능 여부(available_actions)와 함께 고유한 ref_id를 얻는다.

{
  "version": "2.6",
  "ok": true,
  "command": "snapshot",
  "data": {
    "app": "Finder",
    "snapshot_id": "s8f3k2p9",
    "ref_count": 59,
    "complete": true,
    "tree": {
      "role": "window",
      "name": "Downloads",
      "children": [
        { "role": "treeitem", "name": "Documents", "ref_id": "@s8f3k2p9:e8", "available_actions": ["Click"] }
      ]
    }
  }
}

스냅샷 ID(s8f3k2p9)와 요소 인덱스(e8)를 조합한 @s8f3k2p9:e8이 ref다. 이 ref는 해당 스냅샷에만 유효하고, UI가 변경되면 STALE_REF 에러를 반환한다. 새로운 스냅샷을 찍어 새로운 ref를 사용해야 한다.

명령어: 57개 operação, MCP 서버도 가능

agent-desktop은 snapshot, click, type, wait 등 57개 운영 명령과 4개 미완료 명령(key-down, key-up, mouse-down, mouse-up — 데몬이 키/버튼을 놓는 기능을 아직 구현하지 않음)을 제공한다. 관찰, 액션, 키보드·마우스, 앱·창 관리, 알림, 클립보드, 세션, 샌드박스, 시스템 명령으로 그룹화된다.

간단한 워크플로우는 다음과 같다.

agent-desktop snapshot --app Finder -i
agent-desktop click @s8f3k2p9:e8
agent-desktop snapshot --app Finder -i

첫 snapshot으로 현재 UI를 읽고, click으로 ref를 클릭한 뒤, 두 번째 snapshot으로 결과를 확인한다. 이 루프는 agent-desktop 내부에 없고, 호출하는 에이전트가 구성한다.

MCP 서버로 동작하는 것도 특징이다. agent-desktop mcp 명령으로 stdio 기반 MCP 도서를 제공하므로, MCP 호환 에이전트 러닝에 바로 통합할 수 있다.

{ "mcpServers": { "agent-desktop": { "command": "agent-desktop", "args": ["mcp"] } } }

headless 기본, 보안 정책, 플랫폼 지원

agent-desktop은 기본적으로 headless로 동작한다. ref 액션은 접근성 API를 통해 포인터를 이동하거나 포커스를 전환하지 않는다. 전역 --headed 플래그를 주어야만 물리적 입력이 허용된다.

보안 정책은 명시적이다. 스냅샷, 클립보드 읽기, 스크린샷, 명령 출력, 디버그 아티팩트는 개인 데스크톱 콘텐츠를 포함할 수 있으므로, 공개 로그나 업로드에서 제외해야 한다.

지원 플랫폼은 다음과 같다.

플랫폼 요구사항 접근성 API
macOS macOS 13+, Intel/Apple Silicon AX API
Windows Windows 10 1809+, x64/ARM64 UI Automation
Linux Ubuntu 24.04+, x86_64/aarch64, X11/Wayland AT-SPI

각 플랫폼별 headless 지원 범위와 --headed 필요 여부가 플랫폼 페이지에 명시되어 있다.

에이전트가 구성해야 할 루프

agent-desktop은 완성형 에이전트가 아니다. 호출하는 에이전트가 다음 루프를 구성해야 한다.

  1. 관찰: snapshot으로 현재 UI 상태를 JSON으로 읽는다. ref_id 목록을 확인한다.
  2. 행동: click, type, set-value 등으로 ref를 조작한다. 에러 코드에 따라 retry 가능 여부를 판단한다.
  3. 검증: 다시 snapshot을 찍어 변경이 의도한 대로 반영되었는지 확인한다.

에러 처리가 중요하다. INVALID_ARGS는 ref 형식이 잘못되었을 때, STALE_REF는 UI가 변경되어 이전 ref가 무효화되었을 때, AMBIGUOUS_TARGET는 여러 창이 겹쳤을 때 반환된다. error.disposition.retry가 safe일 때만 재시도한다.

실무 적용: 어디에 유용한가

agent-desktop이 특히 유용한 상황은 다음과 같다.

  • 설정 다이얼로그 자동화: macOS 시스템 설정이나 Windows 설정 앱을 에이전트가 탐색하게 할 때, 스크린샷 좌표는 해상도마다 다르지만 ref는 안정적이다.
  • 데스크톱 앱 테스트: GUI 테스트 자동화에서 픽셀 매칭 대신 요소 구조로 테스트를 작성할 수 있다.
  • 접근성 테스트: 접근성 트리를 통해 스크린 리더 사용자 경로를 시뮬레이션할 수 있다.

반면, 게임이나 그래픽 전문 앱, canvas 기반 UI, 일부 게임 엔진은 접근성 트리 정보를 제공하지 않아 작동하지 않을 수 있다. 플랫폼별로 지원 범위가 다르므로, 대상 앱의 플랫폼 페이지에서 확인해야 한다.

한계: 접근성 API의 경계

첫째, 모든 앱이 접근성 정보를 제공하지는 않는다. 접근성 권한을 수동으로 부여해야 하는 앱도 있고, 일부 앱은 아예 접근성 트리를 노출하지 않는다.

둘째, ref는 스냅샷에 종속된다. UI가 변경되면 ref가 무효화되므로, 매번 새로운 스냅샷을 찍어야 한다. 이 과정은 네트워크 호출보다 빠르지만, 빈번한 스냅샷은 에이전트의 컨텍스트를 차지한다.

셋째, 보안 아티팩트 관리다. 스냅샷과 클립보드 내용은 개인정보일 수 있다. 공개 로그에 accidentally 포함되면 문제가 된다.

인사이트: 좌표가 아닌 의미로 자동화한다

agent-desktop의 핵심은 “픽셀 좌표 대신 의미 있는 UI 요소”다. 스크린샷과 OCR, 객체 탐지는 해상도와 동적 UI에 취약하지만, 접근성 트리는 구조적 안정성을 제공한다. 단, 모든 앱이 접근성 정보를 제공하지는 않으며, ref는 스냅샷에 종속된다.

도입을 검토한다면 질문은 “agent-desktop이 스크린샷 방식보다 나은가”가 아니라 “대상 앱이 접근성 API를 제공하는가, ref 스코프 관리가 가능한가, 보안 아티팩트 처리가 가능한가”다. 세 질문에 답한 뒤, 간단한 앱(Finder 등)에서 snapshot → click → snapshot을 시험해 보는 것이 첫 단계다.

데스크톱 자동화 루프의 구조를 더 알고 싶다면 에이전트 흐름 강의에서 관찰·실행·검증 패턴을 이어서 볼 수 있다.