데스크톱 인수 (Desktop Takeover)
개요
AI 에이전트가 데스크톱을 인수하여 GUI 작업을 완료하는 전체 과정을 통합적으로 오케스트레이션합니다. 먼저 최적 경로를 라우팅 판단하고, computer use 권한이 준비되었는지 확인한 후, 작업을 전달하고 검증합니다. computer use는 최후의 수단(폴백) 경로이며 기본 경로가 아닙니다. 작업이 반드시 GUI를 통해서만 완료되어야 할 때만 사용합니다.
워크플로 의사 결정 트리
데스크톱 조작 유형의 요청을 받으면 다음 순서로 경로를 판단하며, 해당 조건에 맞으면 즉시 중단합니다.
1. 연결기/MCP로 직접 접근 가능?
대상 앱에 이미 연결된 연결기(GitHub, WPS 지식 베이스, WeCom 등)가 있음
→ 연결기 사용, GUI 건드리지 않음
예: GitHub PR 확인 → gh 연결기; WPS 라이브러리 문서 읽기 → wps-knowledgebase
2. 순수 브라우저 작업?
작업이 웹페이지에서 발생 (양식 작성, 웹 클릭, 스크린샷 비교)
→ browser-use 스킬 사용, 시스템 GUI 움직이지 않음
예: 특정 웹사이트 로그인하여 설정 변경 → 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 앱의 인터페이스 요소(버튼, 메뉴, 웹이 아닌 창)를 조작해야 함
예: GUI 진입점만 있는 특수 소프트웨어의 설정 항목 변경
판단 원칙: 한 단계 아래로 갈수록 신뢰성과 속도가 떨어지고 불확실성이 증가합니다. GUI 조작은 요소 위치 파악, 창 포커스, 인터페이스 언어 등 여러 불확실성을 수반하므로 최후의 수단입니다.
참고: 5단계의 가시성 의존성(창 열거 + 스크린샷)은 Stage Manager(무대 관리자)가 켜져 있을 때 구조적 약점입니다(Pre-flight 2항 및 '보이지 않는 창 함정' 참조). AX 계열 도구(접근성 트리 인식)는 논리적 지오메트리를 읽으므로 Stage Manager의 축소/이동 속임수에 영향을 받지 않아 대체/보완 경로가 됩니다. 27.0.1 재검증에서 부분적으로 확인됨(자세한 함정 하위 절 발견 5 참조). 제한 조건: 완전히 새로 시작되어 무대에 한 번도 올라간 적 없는 창은 AX 트리에서도 볼 수 없습니다. 이 스킬에 내장된 AX 폴백 도구:
tools/axctl(사용법은 'AX 폴백 계층' 장 참조).
라우팅 시 대상 앱에 연결기가 있는지 불확실하면 먼저 list_installed_plugins를 확인하고, 기억에 의존하여 단정하지 마십시오.
사전 점검: 권한 및 환경 이중 점검
computer use로 넘어가기 전에 두 가지 사전 점검을 완료해야 하며, 하나라도 빠뜨리면 안 됩니다.
1. 권한 확인
gui_permission_status 호출:
all_granted: true→ 두 번째 사전 점검으로 진행- 권한 부족 → references/authorization-macos.md의 절차에 따라 사용자에게 권한 부여 안내(macOS)
- Windows → 현재 버전은 macOS만 지원하므로 사용자에게 명확히 안내
2. Stage Manager 사전 점검 (필수, 사용자가 Stage Manager를 켜 둔 경우가 많음)
defaults read com.apple.WindowManager GloballyEnabled 실행:
1반환(켜짐) → 전달 전에 먼저open -a <앱 이름>으로 대상 앱을 활성화하여 현재 무대로 가져옴(잠시 포커스를 뺏으므로 사용자에게 미리 알림). 그런 다음gui_list_windows로 대상 창이 보이는지 확인한 후에야create_task실행. 활성화 후에도 창이 목록에 없으면 바로 아래 '보이지 않는 창 함정' 진단 시퀀스로 진입 —create_task를 재시도하지 말고, 앱이 고장 났다고 단정하지 마십시오.0반환(꺼짐) → 정상 전달 프로세스 진행
이 사전 점검은 Stage Manager 함정을 '사후 진단'에서 '사전 회피'로 업그레이드합니다. Stage Manager는 macOS 15+ 사용자에게 드물지 않으며, 켜져 있는 사용자에게 이 절차는 매 전달의 기본 경로이지 특별한 경우가 아닙니다. 활성화-가시화 메커니즘은 같은 날 macOS 27.0.1에서 재검증되었으나, '첫 활성화 후 유지 안 됨'과 '가시화 후 다시 축소'라는 두 가지 새로운 세부 사항이 발견되었습니다. 자세한 내용은 '보이지 않는 창 함정'의 27 재검증 하위 절을 참조하십시오.
작업 전달
권한이 준비되면 내장된 computer use 스킬의 표준 워크플로를 따릅니다.
gui_list_windows로 대상 앱 창 찾기; 찾지 못하면open_app으로 실행- 실행 후 가시성 확인:
open_app후 반드시 다시gui_list_windows를 호출하여 창이 실제로 목록에 나타나는지 확인. 나타나지 않으면 성급하게 '앱이 고장 났다'고 결론 내리지 말고 아래 '보이지 않는 창 함정'을 먼저 확인 - Stage Manager가 켜져 있는 경우(사전 점검에서 확인됨): 먼저
open -a로 대상 앱을 활성화한 후 전달 — Pre-flight 2항 참조, 여기서 다시 판단하지 않음 create_task(window_id, task)로 작업 전달
보이지 않는 창 함정 (Stage Manager 시나리오)
결론 적용 범위: 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후 메인 창이 여전히 축소 상태(전경이 다른 앱에 의해 점유됨)였고, 두 번째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가 반환하는 window frame은 전체 크기 논리적 좌표(예: (405,517,230×408))인 반면, 동시에 CGWindowList 렌더링 상태는 39×100 축소 창 — Stage Manager의 기하학적 이동은 AX를 속일 수 없음. 하지만 사각지대: 완전히 새로 시작되어 무대에 한 번도 올라간 적 없는 창의 AX 트리는 windows=0을 보고함; 무대에 한 번 올라갔다가 백그라운드에서 다시 실행되면 AX는 계속 볼 수 있음. 추론: AX 인식도 무조건적인 면역은 아니며, 처음 실행되는 앱은 먼저 무대에 올리기 위해 활성화해야 함. 또한: AX 논리적 좌표를 사용하여 화면에 합성 마우스 이벤트를 보내면 잘못된 앱을 클릭하게 됨(논리적 위치 ≠ 현재 렌더링 위치) — AX 계열 도구로 작업을 수행하려면 AXPress와 같은 접근성 작업 API(예: axctl)를 사용해야 하며 좌표 클릭을 사용하면 안 됨
판단 순서(대상 앱이 창 목록에 없을 때):
- 먼저 프로세스가 살아 있는지 확인(
pgrep): 살아 있음 → 가시성 문제일 가능성이 높고 앱 고장이 아님 - 사용자가 Stage Manager를 켰는지 확인(macOS 15+,
defaults read com.apple.WindowManager GloballyEnabled, 1=켜짐): 켜짐 → 3단계로 진행; 꺼짐 → 갑자기 창이 없어졌거나 다른 이유일 수 있음 - 앱을 활성화하여 가시화:
open -a <앱 이름>(잠시 포커스를 뺏으므로 사용자에게 미리 알림); 27에서는 첫 활성화 후 유지되지 않을 수 있으므로, 활성화 후 즉시 확인하고 가시화되지 않으면 다시 활성화(최대 2회) - 다시
gui_list_windows실행, 일반적으로 window_id를 얻을 수 있음
추가 신호: Stage Manager가 켜져 있을 때 open_app은 일반적으로 window_id를 얻을 수 없음(hint를 반환하여 두 번째 열거를 유도함); 꺼져 있을 때는 정상적으로 window_id 반환.
중요 추론:
보이는 창 없음보고 ≠ 창이 존재하지 않음, 더욱이 이전 작업이 실패했음을 의미하지 않음 — 이전 '실패'한 작업이 실제로는 성공했을 수 있음(창이 생성되었지만 보이지 않는 것뿐)- 대화 상자 창(예: '열기' 파일 대화 상자)이 작업에 의해 닫히면 해당 window_id는 무효화되고 이후 스크린샷은 오류를 보고함 — 이는 정상적인 현상이며, 다시 열거하여 새 ID를 얻으면 됨
- 일부 앱(예: 텍스트 편집기)은 문서 없이 실행될 때 원래 창이 없는 것이 정상적인 동작이므로 파일을 열어서 함께 사용해야 함
작업 설명 3단 구성 (성패의 핵심)
task 매개변수는 다음 세 부분을 포함해야 합니다.
목표: 수행할 작업을 단계별로 설명
경계: 건드리면 안 되는 것을 명확히 함 (예: "히스토리 목록의 어떤 항목도 클릭하지 마십시오")
오류 처리: 특정 작업이 응답하지 않으면 발생한 상황을 정확히 기록하고 다음 단계로 진행하며, 재시도하거나 방법을 변경하지 않음
오류 처리 규칙은 생략할 수 없음 — 생략하면 단일 실패가 반복적인 재시도를 유발하여 전체 단계 할당량을 소진시킵니다.
설명에 픽셀 좌표나 숫자 위치를 포함하지 말고 인터페이스에서 볼 수 있는 텍스트와 컨트롤 이름을 사용하여 대상을 지정하십시오.
예시
사용자 요청: "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> 창 나열: 제목 + 논리적 지오메트리 frame
axctl tree <target> [depth] UI 트리 읽기: 역할/제목/설명/값/frame(기본 depth=2)
axctl actions <target> <제목> 일치하는 요소의 사용 가능한 액션 목록 확인
axctl press <target> <제목> AXPress 실행(의미적 클릭, 요소 수준, 좌표 불필요)
axctl activate <target> 앱 활성화(NSRunningApplication.activate)
<target>은 bundle id(권장, 예: com.apple.calculator), 숫자 PID, 또는 지역화된 앱 이름(소문자 일치 — 한국어 시스템에서는 '계산기'가 아닌 'Calculator' — 이름 일치는 오류가 발생하기 쉬우므로 bundle id 우선)을 지원합니다.
사용 규칙
- 요소 찾기: 먼저
tree를 사용하거나 알려진 버튼 제목으로actions를 사용하여AXPress가 존재하는지 확인한 후press실행. press는 AXPress 액션이 있는 요소에만 작동하며, 메뉴 항목은 AXPick이므로 유형별로 판단 - 액션 검증: press가
PRESSED를 반환하면tree를 사용하여 대상 요소 또는 관련 표시 영역의 새 값을 읽어 증거로 삼음(계산기 실제 측정 참조: '3'을 누른 후 StaticText 값이 3으로 변경됨) — computer use의 스크린샷 검증과 동일하게, 텍스트 자체 진술은 증거로 충분하지 않음 - Stage Manager 시나리오: AX 트리는 논리적 지오메트리를 읽으므로 축소 상태의 창도 읽고 조작할 수 있음(실제 측정됨); 하지만 완전히 새로 시작되어 무대에 오른 적 없는 앱의 AX 트리는 비어 있음 — 먼저
axctl activate또는open -a로 무대에 올린 후 조작 - 적용 범위: axctl은 요소 수준 읽기/쓰기(버튼/메뉴/텍스트 필드)에 적합; 앱 간 메뉴바 클릭, 시스템 수준 키보드/마우스 시뮬레이션, 또는 복잡한 다단계 GUI 흐름이 필요하면 여전히 내장된 computer use 전달 사용
- 알려진 제한 사항: UI 변경 모니터링 없음(axmcp의 observe_changes 기능 — 업스트림이 Swift 6.4를 채택한 후 재평가); 단일 요소 작업만 가능, 배치 트랜잭션 없음
실제 측정 기록 (macOS 27.0.1, Stage Manager 켜짐)
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에 변화가 없을 때만 추가로 한 번 촬영하여 멈췄는지 여부를 판단합니다.
문제 해결 빠른 참조
| 증상 | 처리 |
|---|---|
permission_denied | references/authorization-macos.md 참조 |
| 여러 라운드 연속으로 같은 단계에서 멈춤 | continue_task에 hint 매개변수로 컨트롤의 정확한 표시 텍스트 제공 |
| 인터페이스 변화 없지만 성공 보고 | gui_screenshot에 의존; window_id가 올바른지 확인 |
conflict | 해당 창에 이미 작업이 있음, 먼저 delete_task 실행 |
window_not_found | 창이 닫혔거나 ID가 만료됨, 다시 gui_list_windows 실행 |
보이는 창 없음(프로세스가 살아 있을 때) | Stage Manager 활성화로 창 캡처 불가: open -a 활성화 → 즉시 다시 열거; 가시화되지 않으면 다시 한 번 활성화(27에서 첫 활성화 후 유지되지 않을 수 있음, 최대 2회), '보이지 않는 창 함정' 참조(15 및 27.0.1 모두 실험으로 확인됨) |
| 스크린샷에 찍힌 창이 비정상적으로 작거나 화면 가장자리에 붙어 있음 | 대상 창이 Stage Manager 축소 상태임(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 폴백 계층' 장 참조