CLOUSD
Mở tài khoản
AI agent

AI agent điều khiển điện thoại Android như thế nào

Agent điều khiển điện thoại bằng một vòng lặp: nhìn màn hình, quyết định, thao tác, kiểm tra. Từng bước chạy thế nào, MCP thêm được gì, và những lỗi mà ai xây agent cũng gặp.

Một mô hình ngôn ngữ không thể chạm vào màn hình. Để điều khiển điện thoại Android, nó cần một lớp harness biến màn hình thành thứ mô hình đọc được, và biến quyết định của mô hình thành sự kiện chạm và phím. Harness nghiên cứu, công cụ test và các sản phẩm đặt chỗ hay đặt hàng thay người dùng đều dùng một biến thể nào đó của cùng một vòng lặp.

Bài viết này đi qua vòng lặp đó từng bước, kèm các lệnh ADB bên dưới, rồi nói về chỗ đứng của MCP và những lỗi xuất hiện trong mọi dự án thật: popup, quyền, ngày giờ, danh sách dài và những màn hình agent đơn giản là không đọc được.

Vòng lặp

Mỗi bước của agent trên điện thoại gồm bốn phần:

  1. Observe (quan sát). Chụp lại màn hình hiện tại: ảnh chụp màn hình, cây UI, hoặc cả hai.
  2. Decide (quyết định). Gửi mục tiêu, lịch sử ngắn của các bước trước và quan sát hiện tại cho mô hình. Mô hình trả lời bằng một hành động có cấu trúc: chạm phần tử này, gõ đoạn văn bản này, vuốt, bấm Back, mở một ứng dụng, chờ, hoặc kết thúc kèm câu trả lời.
  3. Act (thao tác). Harness biến hành động đó thành sự kiện nhập liệu trên điện thoại.
  4. Check (kiểm tra). Quan sát lại và xác nhận màn hình đã đổi đúng như hành động định làm.

Trong code, bộ khung khá ngắn:

steps = 0
while steps < max_steps:
    obs = phone.observe()              # screenshot + elements with text and bounds
    action = model.next_action(goal, history, obs)
    if action.kind == "done":
        return action.answer
    phone.act(action, seq=obs.seq)     # refuse if the screen changed since obs
    history.append((obs.summary, action))
    steps += 1

Phần việc khó nằm bên trong observe và act, và ở chỗ bạn đưa gì vào history. Hãy giữ lịch sử gọn: mỗi bước một dòng gồm hành động và những gì đã thay đổi là đủ. Ảnh chụp đầy đủ của mọi bước trước chỉ đốt context mà không giúp mô hình quyết định tốt hơn.

Nhìn màn hình: điểm ảnh và cây UI

Có hai cách cho mô hình thấy màn hình, và phần lớn agent chạy được việc đều kết hợp cả hai.

NguồnCho được gìHỏng ở đâu
Ảnh chụp màn hìnhMọi thứ đang hiển thị, kể cả icon và hình ảnh; cần mô hình có thị giácMục tiêu nhỏ, icon na ná nhau, tọa độ chính xác
Cây UIVăn bản, resource id, tên class, bounds, cờ clickable; chính xác và rẻGame và đồ họa vẽ trên canvas, một số WebView, view tự viết không có nhãn accessibility
Ảnh chụp có đánh số phần tửMột bức ảnh để nắm bối cảnh cộng id chính xác cho từng mục tiêuMàn hình chật chội với các phần tử chồng lên nhau

Với ADB thuần, nguyên liệu thô trông như sau:

adb exec-out screencap -p > screen.png
adb shell uiautomator dump /sdcard/ui.xml && adb pull /sdcard/ui.xml

Bản dump liệt kê mọi node với text, resource-id, content-desc và bounds. Chạm vào tâm bounds của một node đáng tin hơn nhiều so với việc hỏi mô hình thị giác tọa độ thô. Có một điểm cần lưu ý: dump UI phải chờ màn hình đứng yên, nên những màn hình không bao giờ ngừng chuyển động, như video đang phát hay đồng hồ đang đếm, có thể làm nó thất bại. Khi đó harness nên quay về dùng ảnh chụp màn hình.

Thao tác: chạm, văn bản và thời điểm

Các lệnh nhập liệu cơ bản:

adb shell input tap 540 1650
adb shell input swipe 540 1600 540 600 300
adb shell input text "hello%sworld"
adb shell input keyevent KEYCODE_BACK

Để ý %s trong input text: nó thay cho dấu cách, và lệnh này không xử lý được phần lớn ký tự ngoài ASCII. Harness nào cần bảng chữ cái khác sẽ đưa văn bản vào clipboard rồi dán.

Ba chi tiết phân biệt một agent đáng tin với một agent chập chờn:

  • Focus trước khi gõ. Chạm vào ô nhập trước, rồi mới gõ. Lúc đó bàn phím che khoảng nửa dưới màn hình, nên hãy quan sát lại trước lần chạm tiếp theo.
  • Chờ ổn định, đừng sleep. Sau mỗi thao tác, chờ đến khi màn hình ngừng thay đổi, giới hạn trong vài giây. Sleep cố định hoặc phí thời gian, hoặc thao tác khi trang chưa tải xong.
  • Từ chối hành động lỗi thời. Nếu màn hình đã đổi sau lần quan sát mà mô hình dựa vào, hành động có thể trúng nhầm phần tử. Harness tốt gắn số thứ tự cho mỗi lần quan sát và từ chối hành động tính từ quan sát cũ hơn, buộc agent nhìn lại thay vì đoán.

Chỗ đứng của MCP

Model Context Protocol là cách chuẩn để trao công cụ cho mô hình. Một MCP server cho điện thoại cung cấp các công cụ như liệt kê thiết bị, quan sát màn hình và thao tác trên đó, nên mọi MCP client (Claude Code, Codex, Cursor và các công cụ khác) đều điều khiển được điện thoại mà không cần code nối riêng. Vòng lặp không đổi; MCP chỉ chuẩn hóa các lệnh gọi.

Có hai mức điều khiển. Ở mức thấp, agent của bạn gọi observe và act và tự quyết định từng bước. Ở mức cao, nó giao một mục tiêu cho agent nằm ngay cạnh điện thoại: "mở app, thêm túi gạo 2 kg vào giỏ hàng, báo lại tổng tiền". Clousd hỗ trợ cả hai mức: observe và act qua REST API và MCP server, và Tác vụ, nơi bạn giao cho điện thoại một mục tiêu bằng lời thường, agent của Clousd tự làm các bước và trả về câu trả lời. Trang dành cho agent đặt hai cách này cạnh nhau.

Những gì làm agent hỏng

Hộp thoại xin quyền, lời nhắc "đánh giá ứng dụng", thông báo cập nhật, tooltip, banner cookie trong WebView và hộp thoại "ứng dụng không phản hồi" đều xuất hiện vào những lúc ngẫu nhiên. Agent làm theo kế hoạch một cách mù quáng sẽ chạm nhầm. Hãy đặt một quy tắc trong prompt: trước khi tiếp tục kế hoạch, đóng mọi hộp thoại không thuộc về tác vụ. Trong môi trường test, cấp quyền trước bằng adb shell pm grant com.example.app android.permission.POST_NOTIFICATIONS.

Quyền khác nhau theo phiên bản Android

Android 13 thêm quyền runtime cho thông báo. Android 14 thêm quyền truy cập ảnh một phần, khi người dùng chọn "Chọn ảnh" thay vì cho phép tất cả. Vị trí có "Trong khi dùng ứng dụng" và "Chỉ lần này". Cùng một tác vụ sinh ra các hộp thoại khác nhau trên các phiên bản khác nhau, nên hãy test agent trên nhiều hơn một phiên bản.

Ngày và giờ

"Thêm cuộc họp vào thứ Ba tuần sau" phụ thuộc vào đồng hồ và múi giờ của điện thoại, trong khi khái niệm "hôm nay" của mô hình lại đến từ dữ liệu huấn luyện. Hãy đưa ngày, giờ và múi giờ của thiết bị vào mọi lần quan sát. Bộ test kiểm tra kết quả có ngày tháng cần đồng hồ điện thoại được đặt đúng như tác vụ mong đợi.

Văn bản dài và danh sách dài

Gõ vài đoạn văn ngốn hết ngân sách bước. Đếm phần tử trong một danh sách cần cuộn năm lần, hay tìm mục trùng trong đó, đòi hỏi agent nhớ những gì đã thấy. Đây là những tác vụ agent thất bại nhiều nhất hiện nay, và kết quả AndroidWorld trên trang benchmark phân loại các thất bại theo từng kiểu.

Màn hình agent không đọc được

Ứng dụng đặt cờ secure trên cửa sổ, thường gặp ở app ngân hàng và màn hình mật khẩu, cho ra ảnh chụp đen kịt. Game vẽ trên canvas không có cây UI. Hãy thiết kế tác vụ quanh những giới hạn này thay vì để agent lặp vô tận trên một màn hình trống.

Trạng thái rò rỉ giữa các lần chạy

Phiên đăng nhập, dữ liệu cache và thông báo từ lần chạy trước làm thay đổi những gì agent thấy ở lần sau. Khi đánh giá, hãy đặt lại điện thoại về trạng thái mới giữa các lần chạy để mọi lượt đều bắt đầu như nhau.

Xây một bài đánh giá có ý nghĩa

  • Một bộ tác vụ cố định, mỗi tác vụ có trạng thái kết thúc kiểm tra được từ bên ngoài: một dòng trong cơ sở dữ liệu, một tệp, activity trên cùng (adb shell dumpsys activity top).
  • Một lần thử cho mỗi tác vụ với ngân sách bước cố định. Chạy lại sẽ che giấu tỉ lệ thất bại thật.
  • Một ảnh chụp màn hình và hành động cho mỗi bước, để bạn đọc được vì sao tác vụ thất bại.
  • Hai hoặc ba mẫu điện thoại và phiên bản Android. Agent chạy được trên một kích thước màn hình thường hỏng ở kích thước khác.

Với những kiểm tra cần nhiều hơn màn hình, cùng chiếc điện thoại đó có thể truy cập qua ADB thông qua relay bảo mật.

Sẵn sàng khởi chạy
chiếc điện thoại đám mây đầu tiên?

Dùng thử miễn phí 30 phút

Không cần thẻ