Mục tiêu
Guide của cua.ai dựng một Windows sandbox, cài Minecraft Java Edition và cho computer-use agent điều khiển game qua MCP server của cua-driver. Minecraft là bài stress test đủ khó: cần internet, Java, OpenGL và một GUI gần như chỉ thao tác được bằng click.
Yêu cầu tối thiểu gồm cua-sandbox 0.3.3, host có KVM hoặc HVF cho đường local, Microsoft account sở hữu Minecraft Java Edition và một model có vision. Trên Apple Silicon, guest x86_64 chạy qua TCG nên không dùng được -cpu host; guide khuyên chuyển sang Fleet.
Boot Windows sandbox local
Image mặc định cần ba bổ sung:
.expose(3000)để đưa MCP server trong guest ra host.- NIC thứ hai không bị
restrict=on, đặt ở subnet riêng để guest vào internet. -cpu hostvì CPU modelqemu64mặc định không đủ cho software OpenGL driver.
from cua import Image, QEMURuntime, Sandbox
EXTRA_ARGS = [
"-netdev", "user,id=net1,net=10.0.3.0/24,host=10.0.3.2,dns=10.0.3.3",
"-device", "virtio-net-pci,netdev=net1,mac=52:55:00:d1:55:02",
"-cpu", "host",
]
sb = await Sandbox.create(
Image.windows().expose(3000),
name="mc-win",
local=True,
runtime=QEMURuntime(
mode="bare-metal",
cpu_count=12,
memory_mb=16384,
extra_args=EXTRA_ARGS,
),
)
mcp_port = sb.exposed_ports[3000]
Ở local, đọc port từ sb.exposed_ports; sb.tunnel.forward(3000) không được HTTP transport hỗ trợ. Hai NIC cũng không được dùng cùng subnet mặc định 10.0.2.0/24, nếu không Windows có thể đẩy một interface sang địa chỉ link-local và mất DNS.
Cài launcher và software OpenGL
Windows Server 2022 chỉ có Microsoft Basic Display Adapter với OpenGL 1.1, trong khi Minecraft mới cần OpenGL 3.2. Guide dùng Prism Launcher bản MinGW và Mesa3D bản MinGW để tránh phụ thuộc Visual C++ Redistributable.
Sau khi Prism tải Java runtime, copy opengl32.dll và libgallium_wgl.dll cạnh mọi javaw.exe dưới thư mục cài đặt. Windows ưu tiên DLL cùng thư mục với executable, nhờ đó game dùng Mesa thay cho OpenGL hệ thống.
$dirs = Get-ChildItem C:\mc -Recurse -Filter javaw.exe -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty DirectoryName -Unique
foreach ($d in $dirs) {
Copy-Item C:\mc\mesamw\x64\opengl32.dll, C:\mc\mesamw\x64\libgallium_wgl.dll $d -Force
}
Đăng nhập Prism dùng Microsoft device authorization. Code tồn tại khoảng 15 phút và tự được cấp lại; luôn đọc code mới từ screenshot thay vì tái sử dụng code cũ.
Điều khiển qua MCP
Agent loop chỉ cần một nhóm tool nhỏ: xem desktop, liệt kê window/app, click, gõ text, bấm phím, đưa app ra trước và scroll. Có ba chi tiết dễ gây lỗi:
list_tools()có thể quảng cáo tool bị YAML policy chặn; một tool xuất hiện trong schema không có nghĩa là được phép chạy.clicknhắm đến process/window quapid, không phải tọa độ màn hình chung. Lấypidtừlist_windowsvà dùngdelivery_mode="foreground"nếu click nền không tới.- Không có tool wait. Agent cần gọi lại
get_desktop_stateđể chờ và quan sát thay đổi.
Guide giới hạn một tool call mỗi turn và chỉ giữ ba screenshot mới nhất để tránh context phình ra. Một run từ launcher đến khi đứng trong world mất 52 bước local và 51 bước trên Fleet, khoảng 20 phút; phần lớn thời gian dành cho software renderer.
Không publish disk đã từng đăng nhập
Đây là cảnh báo quan trọng nhất. Guide thử xoá accounts.json rồi zero-fill free space nhưng vẫn khôi phục được tên profile, UUID và Mojang access-token JWT từ image export. Dữ liệu còn nằm ở:
pagefile.sys, nơi JVM heap bị swap có thể giữ command line và HTTPS response;- phần slack của file log vẫn đang tồn tại;
- cluster đã giải phóng mà bước zero-fill không ghi đè hết.
Không có thao tác scrub nào biến một tìm kiếm âm tính thành bằng chứng credential đã biến mất. Hãy build containerDisk trước khi đăng nhập, tải instance và Java mà không gắn account, rồi để người dùng đăng nhập sau khi boot image riêng của họ.
Export containerDisk an toàn
Không gọi sb.stop() trước khi copy session disk: QEMU runtime coi overlay là ephemeral và có thể unlink file. Hãy shutdown từ trong guest rồi đợi QEMU thoát.
async with Sandbox.connect("mc-win", local=True) as sb:
await sb.shell.run("shutdown /s /t 0")
Sau đó flatten chain và nén overlay:
qemu-img convert -O qcow2 -c ~/.cua/cua-sandbox/images/sessions/mc-win.qcow2 disk.img
OCI image phải đặt file đúng đường dẫn /disk/disk.img:
FROM scratch
ADD disk.img /disk/disk.img
Khi boot image từ registry, khai báo rõ Windows và VM để runtime chọn UEFI:
IMAGE = Image.from_registry(
"ghcr.io/<you>/minecraft-workspace:1.20.1",
os_type="windows",
kind="vm",
).expose(3000)
Fleet pull package ẩn danh, nên package GHCR phải public. Chỉ publish image mà bạn sẵn sàng cho người lạ tải; đây cũng là lý do không bao giờ gắn account vào image build.
Khác biệt trên Fleet
Fleet dùng sb.tunnel.forward(3000) hoặc service proxy thay cho exposed_ports. Với Mesa, llvmpipe làm game crash trong lúc load resource; process khởi động Prism phải có biến sau để chuyển sang renderer chậm hơn nhưng ổn định:
$env:GALLIUM_DRIVER = "softpipe"
Start-Process -FilePath C:\mc\prismw\prismlauncher.exe -WorkingDirectory C:\mc\prismw
Dùng client credentials thay cho session token của cua auth login. Token client cũng hết hạn — guide quan sát expires_in là 900 giây — nên run dài phải mint token mới và dựng lại MCP client.
Dev nên quan tâm vì
Minecraft chỉ là workload minh hoạ. Các bài học tổng quát hơn là: tool schema phải phản ánh policy thực thi, GUI action cần process identity, VM image phải được coi như bản sao forensic của memory và disk, còn credential phải được đưa vào sau khi artifact phân phối đã đóng băng. Đây là checklist hữu ích cho mọi computer-use sandbox, kể cả khi ứng dụng thật không phải game.