Thực Hành Tốt Nhất Khi Dùng Computer Và Browser Use Với Claude
Điểm chính
- Độ chính xác click phụ thuộc rất mạnh vào cách bạn resize ảnh chụp màn hình trước khi gửi cho API.
- Prompt injection là rủi ro mặc định của mọi agent thao tác trên web và UI không đáng tin cậy; phải có lớp phòng thủ nhiều tầng.
- Quản lý context tốt thường ảnh hưởng đến chi phí và độ trễ nhiều hơn gần như mọi tối ưu hóa khác.
- Với tác vụ cơ học, Sonnet 4.6 thường là điểm cân bằng tốt; Opus 4.7 phù hợp hơn khi cần suy luận mạnh và giữ chất lượng click ở độ phân giải cao.
Anthropic vừa chia sẻ một bộ nguyên tắc khá thực dụng cho những ai đang xây tích hợp computer use và browser use với Claude. Nếu bạn đang làm agent có khả năng nhìn màn hình, bấm nút, nhập liệu và điều hướng web, đây là những chi tiết rất đáng đọc kỹ. Phần lớn lỗi “agent bấm sai” không đến từ mô hình ngu, mà đến từ ảnh đầu vào, tỷ lệ co giãn, thứ tự message, hoặc cách bạn giữ context qua nhiều lượt.
Bài này gom lại những điểm quan trọng nhất theo hướng dễ áp dụng hơn cho triển khai thực tế.
Bắt đầu đúng: độ phân giải và scaling
Độ chính xác của click là nền móng của mọi tích hợp computer use. Nếu click không rơi đúng chỗ, mọi thứ phía sau đều đổ vỡ: form không điền được, nút không bấm được, và workflow coi như hỏng.
Đảm bảo scaling đúng
Khi bạn gửi ảnh chụp màn hình cho Claude’s Computer Use API, mô hình sẽ đọc ảnh và trả về tọa độ click theo không gian display_width_px / display_height_px mà bạn khai báo. Nhưng có một giới hạn quan trọng: API có ngưỡng xử lý nội bộ cho kích thước ảnh. Ảnh vượt quá giới hạn này sẽ bị downscale trước khi mô hình nhìn thấy.
Với họ model Claude 4.6, giới hạn là:
- Cạnh dài tối đa: 1568 pixel
- Tổng số pixel tối đa: 1.15 megapixel
- Ảnh vượt một trong hai giới hạn sẽ bị downscale nội bộ
Với Opus 4.7, ngưỡng cao hơn:
- Cạnh dài tối đa: 2576 pixel
- Tổng số pixel tối đa: 3.75 megapixel
- Ảnh vượt giới hạn cũng sẽ bị downscale nội bộ
Khi không gian tọa độ và hình ảnh mô hình nhìn thấy không khớp nhau, click mà mô hình dự đoán sẽ lệch so với ảnh gốc. Đây là nguyên nhân chính khiến click kém chính xác ở độ phân giải cao. Cách sửa đơn giản nhất là luôn downscale screenshot về mức phù hợp trước khi gửi lên API.
Độ phân giải khuyến nghị
Điểm khởi đầu tốt nhất là 1280x720. Đây là mặc định an toàn cho đa số trường hợp: dùng khoảng 80% budget pixel, nằm gọn trong giới hạn cạnh dài lẫn tổng pixel, và là độ phân giải quen thuộc với mô hình.
Nếu bạn dùng Opus 4.7, Anthropic khuyên bắt đầu ở 1080p, vì mức này cho chất lượng tốt hơn 720p mà vẫn giữ được cân bằng hợp lý giữa token và hiệu năng.
Nếu bạn muốn tận dụng tối đa thông tin hình ảnh mà không méo tỷ lệ khung hình, có thể dùng cách tính “max API fit” để chọn độ phân giải tối ưu cho từng ảnh dựa trên aspect ratio gốc:
import math
from PIL import Image
import base64
import io
# 1568 for 4.6 family, 2576 for Opus 4.7
MAX_LONG_EDGE = 1568
# 1.15MP for 4.6 family, 3.75MP for Opus 4.7
MAX_PIXELS = 1_150_000
def compute_max_api_fit(native_w, native_h):
"""Compute the largest resolution that fits API limits while preserving aspect ratio."""
aspect = native_w / native_h
# Compute max dimensions from pixel budget
h_from_pixels = math.sqrt(MAX_PIXELS / aspect)
w_from_pixels = h_from_pixels * aspect
# Apply long edge constraint
if native_w >= native_h:
w = min(w_from_pixels, MAX_LONG_EDGE)
h = w / aspect
else:
h = min(h_from_pixels, MAX_LONG_EDGE)
w = h * aspect
# Never upscale beyond native
w = min(w, native_w)
h = min(h, native_h)
return int(w), int(h)
Cách này hơi phức tạp hơn, nhưng tránh méo tỷ lệ và tận dụng tốt phần pixel budget có sẵn cho từng ảnh. Cải thiện độ chính xác so với cố định 1280x720 là vừa phải, nhưng đây là một cách triển khai gọn và ổn định.
Những cấu hình nên tránh:
- Độ phân giải gốc chưa scale: nếu ảnh nguồn vượt giới hạn, đây là nguyên nhân phổ biến nhất khiến click sai.
- Độ phân giải quá thấp, dưới
960x540: quá ít chi tiết để mô hình nhận ra UI nhỏ. - Trên macOS: ảnh chụp màn hình thường có device pixel ratio là 2, nên ảnh có thể cao gấp đôi tọa độ màn hình.
- Với họ 4.6, tránh
1920x1080trở lên vì sẽ vượt pixel limit và bị downscale âm thầm. Với Opus 4.7, ngưỡng cao hơn nên 1080p và 1440p đều ổn, nhưng vẫn nên tránh 4K gốc nếu không resize.
Scale lại tọa độ
Khi bạn resize screenshot trước khi gửi, mô hình sẽ trả tọa độ theo đúng độ phân giải hiển thị mà bạn đã khai báo. Bạn phải scale ngược về độ phân giải thật của màn hình trước khi thực thi click:
# Your screen is screen_w x screen_h
# You sent a screenshot resized to display_w x display_h
scale_x = screen_w / display_w
scale_y = screen_h / display_h
screen_x = int(api_returned_x * scale_x)
screen_y = int(api_returned_y * scale_y)
Đây là bước rất nhỏ nhưng cực kỳ quan trọng. Chỉ cần quên scale hoặc khai báo sai display_width_px / display_height_px so với ảnh đã gửi, click sẽ lệch đều theo một hướng.
Thứ tự nội dung trong messages array
Khi xây messages.content, hãy đặt instruction dạng text trước ảnh. Cách này giúp mô hình biết mình đang nhìn gì ngay từ lúc xử lý screenshot, và thường cải thiện độ chính xác click:
# RECOMMENDED — text instruction first, then screenshot:
content = [
{"type": "text", "text": "Click on the Submit button"},
{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": screenshot_b64}},
]
# NOT RECOMMENDED — image first, then text:
content = [
{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": screenshot_b64}},
{"type": "text", "text": "Click on the Submit button"},
]
Chẩn đoán lỗi click
Nếu click bị miss target, thường nguyên nhân nằm ở một trong các nhóm sau:
| Triệu chứng | Nguyên nhân có thể | Cách thử |
|---|---|---|
| Click luôn lệch về cùng một hướng | display_width_px / display_height_px không khớp với kích thước ảnh thật đã gửi |
Đảm bảo kích thước display khớp chính xác với ảnh đã resize, không phải độ phân giải gốc |
| Click rơi vào vùng gần đúng nhưng vẫn trượt | Target quá nhỏ; ảnh nguồn quá nét rồi bị mất chi tiết khi downscale; hoặc méo tỷ lệ do ép aspect ratio không tự nhiên | Bật enable_zoom: True cho UI dày đặc; chụp ở DPI thấp hơn hoặc crop vùng liên quan; giữ nguyên aspect ratio khi resize |
| Model bấm nhầm element khác | Instruction mơ hồ; có nhiều element trông giống nhau; UI quá phức tạp cho một bước | Viết prompt cụ thể hơn với ngữ cảnh vị trí; chia interaction thành bước nhỏ; bổ sung mô tả bố cục trang |
| Độ chính xác kém trên toàn bộ luồng | Ảnh gửi vượt giới hạn API; ảnh nguồn từ màn hình rất cao rồi bị nén mạnh; độ phân giải quá thấp | Downscale tất cả screenshot về mức an toàn trước; với nguồn 4K+ trên họ 4.6, Sonnet thường bền hơn Opus 4.6 khi bị downscale nặng |
Chọn model cho tác vụ click
Theo thử nghiệm nội bộ của Anthropic, Claude Sonnet 4.6 thường chính xác về mặt cơ học hơn khi click, còn Claude Opus 4.6 mạnh hơn về suy luận. Sonnet 4.6 cũng bền hơn khi nguồn ảnh phải downscale mạnh.
Opus 4.7 thu hẹp khoảng cách này đáng kể: độ chính xác click gần với Sonnet 4.6, trong khi ngân sách độ phân giải cao hơn giúp giảm bớt việc phải downscale ngay từ đầu. Nếu bạn muốn vừa reasoning mạnh vừa click tốt, đây là lựa chọn đáng cân nhắc.
Khuyến nghị thực tế:
- Dùng Sonnet 4.6 cho đa số tác vụ: cân bằng tốt giữa độ chính xác click, suy luận và chi phí.
- Dùng Opus 4.7 khi cần reasoning mạnh hơn, đặc biệt nếu ảnh nguồn có độ phân giải cao.
- Dùng Haiku 4.5 khi độ trễ là ưu tiên số một.
- Với workflow lớn, vẫn có thể tách thành orchestrator + sub-agent: một model lo lập kế hoạch, model khác lo các bước click cơ học.
Xử lý target nhỏ
Độ chính xác click giảm nhanh khi target càng nhỏ. Nút lớn và vừa như button, input field hay menu item tiêu chuẩn thường ổn ở mọi độ phân giải trong vùng an toàn. Vấn đề nằm ở các target nhỏ và rất nhỏ như checkbox, icon ở system tray, mũi tên dropdown, toggle nhỏ, hay nút mở rộng/collapse trong tree view.
Nếu ứng dụng của bạn thường xuyên phải click target nhỏ, Anthropic gợi ý vài cách sau:
Dùng zoom cho UI dày đặc
Claude 4.6 và 4.7 hỗ trợ zoom để inspect vùng màn hình cụ thể ở độ phân giải cao hơn trước khi click. Có thể bật trong cấu hình tool:
{ "type": "computer_20251124", "name": "computer", "display_width_px": 1280, "display_height_px": 720, "enable_zoom": True }
Làm target lớn hơn
Nếu bạn kiểm soát được UI đang được tự động hóa, hãy tăng kích thước target click dù chỉ một chút. Tác động đến độ ổn định thường rất lớn. Có thể là giảm DPI hệ thống, zoom browser lên, hoặc chỉnh scaling của giao diện.
Ưu tiên keyboard thay vì click
Với phần tử rất nhỏ như icon ở system tray hoặc checkbox bé, keyboard shortcut hay điều hướng bằng tab thường ổn hơn click. Nếu workflow cho phép, hãy prompt mô hình dùng keyboard cho những bước đó.
Cân nhắc độ phân giải ảnh nguồn
Ảnh từ màn hình 4K+ khi nén xuống 720p sẽ mất rất nhiều chi tiết. Ví dụ, một checkbox 16px ở độ phân giải gốc 3840x2160 có thể chỉ còn khoảng 5px ở display resolution 1280x720, khiến nó khó bấm hơn nhiều.
Nếu làm việc với màn hình rất cao độ phân giải, hãy cân nhắc dùng Opus 4.7 vì ngưỡng cao hơn các model trước. Nếu vẫn dùng họ 4.6, có thể chụp ở DPI thấp hơn, dùng scaling để làm UI to hơn, hoặc crop đúng vùng cần thao tác thay vì lấy toàn màn hình.
Những cách thử nhưng không hiệu quả rõ ràng
Anthropic đã thử một số tối ưu phổ biến trong internal evaluations nhưng không thấy uplift ổn định trên nhiều tình huống:
- Chia ảnh thành nhiều tile nhỏ rồi gửi riêng từng phần.
- Chèn lưới tọa độ lên ảnh để mô hình tự định vị.
- Thay đổi thuật toán resize như PIL LANCZOS, sips hay các lựa chọn phổ biến khác.
Điểm chung là bạn có thể dùng cái gì tiện trong stack của mình; phần lớn lợi ích nằm ở cách resize đúng và giữ tỷ lệ nhất quán, không phải ở thuật toán resize cụ thể.
Khi click lỗi, hãy soi failure thay vì đoán mò
Nếu mô hình vẫn hành xử khó đoán sau các bước trên, hãy log toàn bộ transcript và overlay các click dự đoán lên ảnh nguồn để xem thực ra mô hình đang nhìn thấy gì và quyết định ra sao.
Một số lỗi nhìn giống như click sai nhưng thật ra không phải. Ví dụ, một số menu dropdown có thể gọi UI cấp hệ điều hành mà browser viewport không capture được. Khi đó mô hình không hề “fail logic”; đơn giản là nó không nhìn thấy menu cần tương tác. Trong những case này, hãy chuyển sang JavaScript execution, điều hướng bằng keyboard, hoặc thao tác trực tiếp qua DOM thay vì cố click.
Quản lý context cho computer use
Khi xây agent computer use, screenshot sẽ tích tụ rất nhanh. Mỗi hành động sinh ra một ảnh mới, và mỗi ảnh có thể tiêu tốn khoảng 1,000–1,800 token tùy độ phân giải. Sau system prompt, tool definitions và text content, một context window 200k token có thể đầy trong chưa tới 100 screenshot.
Mục tiêu của quản lý context có hai phần: giữ tổng token có kiểm soát và giữ prompt caching hoạt động tốt để bạn không phải trả full price cho cùng một prefix ở mỗi lượt. Theo Anthropic, đây là một trong những tối ưu quan trọng nhất cho agent chạy dài.
Đặt cache breakpoint
Prompt caching chỉ có ích nếu breakpoint nằm trên phần nội dung sẽ lặp lại giữa các turn. API hỗ trợ tối đa bốn cache breakpoint. Gắn cả bốn vào stable prefix như system prompt và tool definitions là lãng phí, vì prefix này đã hit một lần rồi không đổi nữa.
Cách Anthropic khuyên:
- Một breakpoint ở system prompt hoặc phần tool definitions cuối cùng.
- Tối đa ba breakpoint nữa ở các tool result gần nhất, cập nhật theo từng turn và xóa breakpoint cũ của vòng trước để không vượt quá giới hạn bốn breakpoint.
Dàn breakpoint như vậy giúp degrade mềm. Nếu breakpoint gần nhất bị invalidated, ví dụ vì prune image, compaction, hoặc đổi tool definitions, breakpoint cũ hơn vẫn còn có thể hit.
Ví dụ đặt cache control cho các tool result gần nhất:
def set_trailing_cache_control(messages, max_breakpoints=3):
"""Place up to `max_breakpoints` ephemeral cache_control markers on the most recent tool_result blocks, after clearing any existing markers."""
for msg in messages:
for block in msg.get("content", []):
if isinstance(block, dict):
block.pop("cache_control", None)
placed = 0
for msg in reversed(messages):
for block in reversed(msg.get("content", [])):
if placed >= max_breakpoints:
return
if isinstance(block, dict) and block.get("type") == "tool_result":
block["cache_control"] = {"type": "ephemeral"}
placed += 1
Cách 1: Rolling buffer có ý thức về cache
Cách đơn giản nhất để giới hạn token là giữ lại N screenshot gần nhất và bỏ phần còn lại. Trước mỗi API call, đi qua mảng message và thay các image block cũ bằng placeholder ngắn như "[Image omitted]".
Vấn đề của cách naïve là bạn prune từng ảnh một khi chúng già đi, khiến prefix thay đổi ở mỗi turn và cache bị invalidated liên tục. Đây là lý do nhiều người nghĩ rolling buffer “phá cache”. Cách sửa là prune theo batch: giữ prefix byte-identical trong vài turn, rồi đổi một lần, rồi ổn định trở lại.
Một pattern thực dụng đã được test là:
- Giữ nguyên
keep_nscreenshot gần nhất ở full resolution. - Khi tổng số screenshot vượt
keep_n + interval, thay lôintervalảnh cũ nhất bằng placeholder trong một lần. - Giữa hai lần prune, message array giữ nguyên byte, nên cache breakpoint vẫn hit.
Giá trị khởi đầu hợp lý là keep_n = 3 và interval = 25. interval cao hơn sẽ giảm số lần prune, tốt cho cache, nhưng giữ nhiều screenshot full-res hơn trong context.
Ví dụ prune screenshot cũ mà vẫn giữ cache breakpoint:
def prune_old_screenshots(messages, keep_n=3, interval=25):
"""Replace older screenshots with text placeholders in batches. Only prunes when the total count exceeds keep_n + interval, so the message prefix stays byte-stable for `interval` turns between prunes."""
image_positions = [
(msg_idx, block_idx)
for msg_idx, msg in enumerate(messages)
for block_idx, block in enumerate(msg.get("content", []))
if isinstance(block, dict) and block.get("type") == "image"
]
if len(image_positions) <= keep_n + interval:
return messages
to_prune = image_positions[:-keep_n][-interval:]
for msg_idx, block_idx in to_prune:
messages[msg_idx]["content"][block_idx] = {
"type": "text",
"text": "[Image omitted]",
}
return messages
Rolling buffer vẫn có một hạn chế thật: thứ nằm ngoài buffer là mất. Instruction gốc, những gì agent đã thử, và trạng thái hiện tại của task sẽ biến mất cùng các screenshot cũ. Với task ngắn dưới khoảng 50 actions thì ổn; với task dài hơn, nên kết hợp với compaction.
Cách 2: Compaction bằng LLM
Thay vì xóa lặng lẽ ảnh cũ, hãy tóm tắt toàn bộ hội thoại trước khi bỏ nó đi. Bản tóm tắt giữ lại chuyện gì đã xảy ra, người dùng muốn gì, đã làm được gì, và nên resume ở đâu. Vài screenshot gần nhất vẫn được giữ kèm theo để agent nhìn thấy trạng thái hiện tại.
Compaction và rolling buffer bổ trợ cho nhau: rolling buffer giúp giữ token tăng trưởng chậm theo từng turn; compaction định kỳ giúp lấy lại phần lớn window mà không mất bối cảnh quan trọng.
Prompt tóm tắt
Mẫu prompt dưới đây là khung để tránh các lỗi thường gặp. Prompt phải giữ được mọi thứ agent cần để tiếp tục task mà không phải đọc lại hội thoại gốc:
COMPACT_PROMPT = """Your task is to create a detailed summary of this conversation that will REPLACE the conversation history. The agent will continue working with only this summary and a few recent screenshots as context. CRITICAL: Preserve ALL user instructions verbatim. User instructions are the most critical element. If they are lost, the agent will deviate from the task. Before providing your summary, analyze the conversation in tags: 1. Extract every user instruction, requirement, and constraint 2. Identify if this is a repeatable workflow (e.g., processing N items) 3. Chronologically trace what actions were taken and what happened Your summary MUST include these sections: 1. USER INSTRUCTIONS: - Complete initial task definition (verbatim when possible) - ALL specific requirements and criteria - Every "DO NOT", "ALWAYS", "MUST" instruction - Any corrections or feedback that changed the approach 2. TASK TEMPLATE (if this is a repeatable workflow): - The pattern being repeated - Decision criteria for each iteration - Standard workflow steps - Example of one completed iteration 3. CONSTRAINTS AND RULES: - All user-specified rules and restrictions - Edge cases and exceptions discovered 4. ACTIONS TAKEN: - Pages visited and elements interacted with - Forms filled and buttons clicked 5. ERRORS AND FIXES: - What went wrong and how it was resolved - Approaches that failed (so they aren't retried) 6. PROGRESS TRACKING: - Items completed vs. remaining - Current position in the workflow 7. CURRENT STATE: - Current application, URL and domain (optional) - Important page state (logged in, form progress, etc.) 8. NEXT STEP: - Exactly what should be done next to continue """
Mỗi mục ở trên đều có lý do riêng: User Instructions chống task drift; Task Template giúp agent tiếp tục lặp workflow mà không phải suy luận lại; Constraints và Rules giữ nguyên các giới hạn đã phát hiện; Actions Taken ghi lại lịch sử; Errors and Fixes ngăn retry lại đường cũ; Progress Tracking tránh khởi động lại; Current State và Next Step cho entry point rõ ràng.
Server-side compaction beta
Cách đơn giản nhất là để API tự compaction bằng server-side compaction (beta). Bạn truyền prompt tóm tắt vào instructions trong context_management, và API sẽ tự tóm tắt khi input token vượt ngưỡng kích hoạt. Trường instructions này thay thế hoàn toàn prompt tóm tắt mặc định. Thêm pause_after_compaction để gắn các message mới nhất, bao gồm screenshot, qua các lần compaction.
# Minimal — turn on autocompaction with API defaults
response = client.beta.messages.create(
model="claude-opus-4-7",
max_tokens=16000,
betas=["compact-2026-01-12", "computer-use-2025-11-24"],
context_management={"edits": [{"type": "compact_20260112"}]},
messages=[...],
tools=[...],
)
# Customized — set your own trigger threshold and summarization prompt
response = client.beta.messages.create(
model="claude-opus-4-7",
max_tokens=16000,
betas=["compact-2026-01-12", "computer-use-2025-11-24"],
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 150_000},
"instructions": COMPACT_PROMPT,
}
]
},
messages=[...],
tools=[...],
)
Cắt ở client để khớp server
Khi API compact ở server, nó thay thế nội dung trước đó ở phía nó, nhưng local messages array của bạn vẫn giữ toàn bộ history. Nếu bạn cứ gửi nguyên đống history đó ở turn tiếp theo, bạn sẽ trả tiền cho những token server không còn cần nữa, và rolling buffer của bạn cũng sẽ trông vào một slice khác với server.
Cách sửa là mirror việc cắt của server ngay ở client. Khi response báo đã compaction, hãy bỏ phần trước marker compaction khỏi local messages array trước turn tiếp theo.
def truncate_to_last_compaction(messages, response):
"""If the server compacted on this turn, drop pre-compaction messages locally so the next turn's cache prefix matches what the server sees."""
context_mgmt = getattr(response, "context_management", None)
if not context_mgmt or not context_mgmt.get("applied_edits"):
return messages
compaction = next(
(e for e in context_mgmt["applied_edits"] if e["type"] == "compact"),
None,
)
if compaction is None:
return messages
keep_from = compaction["message_index_after_compaction"]
return messages[keep_from:]
Compaction ở client
Nếu model bạn dùng không hỗ trợ server-side compaction, hoặc bạn muốn kiểm soát hoàn toàn, có thể làm compaction ở client với cùng prompt. Sau mỗi API call, kiểm tra tổng input token trong usage. Khi số này chạm ngưỡng, gửi hội thoại cho một summarizer model với COMPACT_PROMPT làm system prompt, rồi thay history bằng bản tóm tắt cộng vài screenshot gần nhất.
Ghép các lớp lại
Một default tốt cho agent computer use chạy dài thường là:
- Một cache breakpoint trên stable prefix, ba breakpoint trên trailing tool results, được xóa và đặt lại mỗi turn.
- Rolling buffer có hiểu cache với
keep_n = 3vàinterval = 25, thay ảnh cũ bằng placeholder theo batch. - Server-side compaction quanh mốc 150k input token, cộng thêm bước cắt phía client để hai bên khớp nhau.
Ba lớp này kết hợp với nhau sẽ giúp session dài vẫn hit prompt cache ở đa số turn, giữ tổng input token nằm dưới context window, và vẫn đủ lịch sử để agent không bị mất phương hướng.
Một số thiết lập thử nghiệm để cải thiện computer và browser use
Các pattern dưới đây là kỹ thuật Anthropic đang thử trong implementation của họ. Chúng có thể giúp ở một số workload cụ thể, nhưng chưa phải khuyến nghị áp dụng đại trà.
Batch tools
Trong bản reference implementation mới, Anthropic có thêm computer_batch và browser_batch bên cạnh tool chuẩn. Mỗi tool nhận một danh sách sub-action và thực thi trong một lần gọi tool. Ví dụ, thay vì click, type và press key ở ba lượt riêng, model có thể emit một computer_batch chứa cả ba thao tác.
Lợi ích là hiệu năng: workflow có N action cơ học sẽ chỉ còn một round trip thay vì N round trip, nên giảm wall-clock time và token spend đáng kể ở task dài. Rủi ro là lỗi dồn lỗi: nếu action 2 phụ thuộc vào trạng thái visual mà action 1 tạo ra, nhưng action 1 lại miss, cả batch phía sau sẽ chạy trên giả định sai.
Anthropic khuyên dùng batch tools khi các sub-action không phụ thuộc vào kết quả visual của nhau, ví dụ điền nhiều field trong form, nối nhiều phím tắt, hoặc scroll rồi click vào một target đã biết. Không nên dùng trong navigation thăm dò, chuỗi recover lỗi, hoặc workflow mà “nếu bước 1 fail thì phải lập kế hoạch lại”.
Advisor tool (beta)
Advisor tool ghép một executor model với một advisor model mạnh hơn, để executor có thể gọi advisor khi gặp tình huống cần reasoning sâu hơn. Executor chạy vòng lặp, và khi cần thì gọi advisor, nhận kế hoạch hoặc course correction, rồi tiếp tục. Tất cả diễn ra server-side trong một request, không tạo thêm round trip phía bạn.
Với computer use, pattern này hữu ích nhất ở task dài: phần lớn turn chỉ là click cơ học, nhưng đôi lúc cần planner mạnh hơn để chọn tab, xử lý modal bất ngờ, hoặc quyết định bỏ chiến lược cũ. Bạn nhận được chất lượng gần với advisor-solo, trong khi phần lớn token vẫn chạy ở mức executor.
Một vài control hữu ích:
max_uses: giới hạn số lần advisor được gọi trong một request.- Giới hạn ở harness: vì advisor tính phí theo giá Opus 4.7 cho mỗi lần consult, bạn có thể tắt advisor sau một số lượng dùng nhất định.
- Advisor-side caching: với hội thoại nhiều lần gọi, cache prefix của advisor thường có lợi sau khoảng ba lần consult.
Hai điểm ít người để ý: advisor chạy không có tools và không có context management, nên nó chỉ trả text advice chứ không click hay browse giúp bạn. Và executor đôi khi sẽ quên rằng advisor tồn tại nếu session quá dài, nên cần reminder nudges.
Dọn các block advisor bị orphan
Khi advisor được gọi, executor sẽ emit server_tool_use với name: "advisor", sau đó là advisor_tool_result. Hai block này nằm trong messages array cùng với mọi thứ khác.
Nếu về sau bạn bỏ advisor khỏi tools array — vì đã chạm giới hạn, đổi config, hay chuyển model — các block cũ đó sẽ thành orphan. Lần gọi API sau sẽ bị 400 vì tool được tham chiếu không còn được khai báo.
Cách xử lý là quét messages trước khi gửi và bỏ các block server_tool_use có name == "advisor" cùng advisor_tool_result.
def strip_orphaned_advisor_blocks(messages):
"""Remove advisor server_tool_use / tool_result blocks from history. Call this before any request that doesn't include the advisor tool."""
for msg in messages:
content = msg.get("content")
if not isinstance(content, list):
continue
msg["content"] = [
block for block in content
if not (
isinstance(block, dict)
and (
(block.get("type") == "server_tool_use" and block.get("name") == "advisor")
or block.get("type") == "advisor_tool_result"
)
)
]
return messages
Nhắc nhở định kỳ
Trong session dài, executor model có thể quên mất tool nào đang có hoặc tool nào nên ưu tiên. Hai mẫu nhắc ngắn đã cho kết quả tốt trong thử nghiệm:
- Nhắc batch: nếu bạn expose
computer_batchhoặcbrowser_batchmà model vẫn gọi từng action lẻ, hãy thêm một gợi ý ngắn ở cấp system sau tool result tiếp theo: “Bạn có thể dùng computer_batch để gộp các thao tác liên tiếp không phụ thuộc vào screenshot trung gian.” - Nhắc advisor: nếu session đã dài hơn khoảng 20 turn mà chưa gọi advisor, thêm một reminder ngắn rằng advisor có sẵn cho các moment cần planning hoặc course correction.
Đây là nhắc nhẹ, không phải rewrite system prompt. Chúng chỉ tốn vài chục token input mỗi lần chèn, nhưng nếu system prompt của bạn đã dài hoặc cache breakpoint đã được đặt rất sát, hãy cân nhắc xem mức cải thiện có đáng hay không.
Gỡ lỗi trong reference implementation
Khi thứ gì đó chạy sai mà bạn chưa chắc là do harness, ảnh chụp hay mô hình, có ba công cụ phụ trong reference implementation rất đáng thử trước khi thêm logging tràn lan:
- Trajectory viewer (
streamlit run viewer/app.py): tải một trajectory đã ghi, xem từng turn kèm screenshot, thinking, tool call và usage. Rất hữu ích khi bạn muốn biết mô hình thực sự nhìn thấy gì và đã quyết định gì. - Tool debug panel (
uvicorn debug.server:app --reload): web UI nhỏ để test từng tool riêng lẻ, như chụp screenshot, lấy tọa độ click, type, scroll, zoom. Hợp để xác nhận pipeline capture và coordinate scaling có đúng không. - Localization playground (
uvicorn localize.server:app --reload --port 8001): upload ảnh bất kỳ và yêu cầu mô hình chỉ vào target. Đây là cách nhanh nhất để chẩn đoán miss click là do resize bug, coordinate-scaling bug hay lỗi thật của model.
Dạy Claude bằng dữ liệu mẫu
Thay vì cứ chỉnh prompt text mãi cho đến khi workflow chạy đúng, bạn có thể cho Claude xem luôn hành vi đúng. Hãy record chính bạn thực hiện task, chụp screenshot, hành động, và nếu cần cả voice narration ở mỗi bước; sau đó phát lại demo đó như context khi Claude chạy workflow tương tự.
Cách này hữu ích theo hai hướng: tăng độ ổn định cho workflow mà Claude gần như làm được nhưng đôi lúc vẫn sai, và mở ra cả những workflow mà chỉ dùng text prompt thì chưa đủ.
Ý tưởng cốt lõi: show, don't tell
Prompt engineering kiểu cũ yêu cầu người dùng mô tả bằng lời rồi sửa dần khi AI hiểu nhầm. Cách này đảo ngược thứ tự: người dùng tự làm task trong lúc hệ thống ghi lại actions, screenshots, và có thể cả voice narration. Khi playback, Claude nhận toàn bộ demo làm context và đi theo cùng chuỗi bước, nhưng vẫn có thể điều chỉnh theo state thực tế của UI.
Điểm mấu chốt là playback không phải replay cứng. Claude dùng demo như một bản hướng dẫn, rồi reason trên environment đang sống. Nếu button đã đổi chỗ hoặc menu đã được sắp xếp lại, Claude có thể tìm element tương đương thay vì bấm mù theo tọa độ cũ.
Mô hình dữ liệu
Đơn vị cơ bản là một “workflow step”, tức một hành động đơn lẻ được ghi lại trong lúc record. Mỗi step gộp lại việc đã làm, vị trí thực hiện, và trạng thái màn hình lúc đó:
from dataclasses import dataclass, field
from typing import Literal, Optional
@dataclass
class WorkflowStep:
action: Literal["click", "type", "navigate", "scroll", "select"]
description: str # Human-readable, e.g. "Click the Submit button"
timestamp: float
selector: Optional[str] = None # CSS selector or XPath
coordinates: Optional[dict] = None # {"x": int, "y": int}
url: Optional[str] = None
screenshot: Optional[str] = None # Base64-encoded screenshot
viewport_dimensions: Optional[dict] = None # {"width": int, "height": int}
speech_transcript: Optional[str] = None # Voice narration, if captured
value: Optional[str] = None # For type actions
@dataclass
class SavedWorkflow:
id: str
name: str # e.g. "Submit expense report"
steps: list[WorkflowStep] = field(default_factory=list)
description: Optional[str] = None # AI-generated summary of the workflow
start_url: Optional[str] = None
created_at: float = 0.0
usage_count: int = 0
Giữ cả selector lẫn coordinates là chủ đích: selector bền hơn khi layout đổi, còn coordinates là fallback trực quan để Claude dùng khi selector hỏng. Viewport dimensions được lưu lại để scale tọa độ nếu môi trường playback khác môi trường record.
Record: cần capture gì
Tối thiểu nên capture click, keyboard input, thay đổi điều hướng, và screenshot ở mỗi action. Với mỗi click, tạo một description dễ đọc bằng text từ aria-label, text content, hoặc qua một Claude call nhanh, rồi annotate screenshot bằng một marker tại vị trí click:
def on_click(event):
step = WorkflowStep(
action="click",
selector=generate_selector(event.target),
coordinates={"x": event.client_x, "y": event.client_y},
url=current_url(),
description=generate_description(event.target),
timestamp=now(),
viewport_dimensions=get_viewport_size(),
)
# Annotate screenshot with a circle at the click position
screenshot = capture_screenshot()
step.screenshot = annotate_with_circle(screenshot, event.client_x, event.client_y)
workflow_steps.append(step)
Marker hình tròn màu xanh ở vị trí click có hai tác dụng: giúp người dùng kiểm tra record có đúng element không, và khi playback cho Claude biết chính xác chỗ nào đã được bấm. Prompt playback nên nói rõ rằng các marker này là artifact của quá trình record, không phải phần của UI thật.
Playback: xây prompt như thế nào
Đây là phần quan trọng nhất. Khi người dùng chạy một workflow đã lưu, bạn cần tạo message gửi cho Claude gồm ba phần: ý định của người dùng, block context giải thích format demo, và các screenshot đã ghi.
Block context phải cho Claude biết cách đọc screenshot đã annotate và cách thích nghi nếu UI thật khác demo:
def generate_playback_context(steps: list[WorkflowStep]) -> str:
steps_description = "\n".join(
f"Step {i+1}: {step.description}"
for i, step in enumerate(steps)
)
return f"""<demonstration_context>
The user has recorded a demonstration showing how to perform this task.
RECORDED STEPS:
{steps_description}
ABOUT THE SCREENSHOTS:
- Each screenshot shows the screen state when an action was taken
- BLUE CIRCLES mark where the user clicked — these are recording annotations
- The blue highlighting is NOT part of the actual interface
- Your own screenshots will NOT have these markers
HOW TO USE THIS DEMONSTRATION:
1. Review all steps and screenshots to understand the complete workflow
2. Take your own screenshot to see the CURRENT page state
3. The blue highlights show which element to interact with — find it in your current view
4. Follow the same sequence of actions, adapting to any differences
5. If the UI has changed significantly, use judgment to find equivalent elements
</demonstration_context>"""
Sau đó ghép message đầy đủ với prompt của người dùng, context block, và screenshot của từng step:
import anthropic
client = anthropic.Anthropic()
content = [
{"type": "text", "text": user_prompt},
{"type": "text", "text": generate_playback_context(workflow.steps)},
]
for i, step in enumerate(workflow.steps):
if step.screenshot:
content.append({"type": "text", "text": f"[Step {i+1}: {step.description}]"})
content.append({
"type": "image",
"source": {"type": "base64", "media_type": "image/jpeg", "data": step.screenshot},
})
response = client.beta.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
betas=["computer-use-2025-11-24"],
messages=[{"role": "user", "content": content}],
tools=[{
"type": "computer_20251124",
"name": "computer",
"display_width_px": 1280,
"display_height_px": 720,
}],
)
Chế độ playback
Không phải workflow nào cũng cần mức bám sát demo giống nhau. Một số workflow quá dài, tiêu tốn rất nhiều input token và làm tăng latency lẫn chi phí. Có thể hỗ trợ một tham số strictness và chèn nó vào prompt:
Strict: đi đúng từng bước; dừng và báo nếu UI thay đổi quá nhiều. Hợp cho workflow nhạy cảm về compliance.Adaptive: dùng demo như guide nhưng vẫn thích nghi với thay đổi UI. Đây thường là default tốt nhất.Goal-oriented: tập trung vào kết quả cuối; coi các bước record chỉ là gợi ý. Hợp khi UI đổi thường xuyên nhưng mục tiêu không đổi.
Ví dụ workflow end-to-end cho expense report
Một workflow đã lưu có thể gồm năm bước: mở form chi phí, chọn loại expense, chọn “Travel” từ dropdown, nhập số tiền, rồi bấm Submit.
expense_workflow = SavedWorkflow(
id="wf_abc123",
name="Submit Expense Report",
start_url="https://expenses.company.com/new",
steps=[
WorkflowStep(
action="navigate",
url="https://expenses.company.com/new",
description="Navigate to new expense form",
timestamp=1700000000,
),
WorkflowStep(
action="click",
selector="#expense-type-dropdown",
coordinates={"x": 400, "y": 200},
description="Click on expense type dropdown",
timestamp=1700000001,
),
WorkflowStep(
action="click",
selector="[data-value='travel']",
coordinates={"x": 400, "y": 280},
description='Select "Travel" expense type',
timestamp=1700000002,
),
WorkflowStep(
action="type",
selector="#amount-input",
value="150.00",
description="Enter expense amount",
timestamp=1700000003,
),
WorkflowStep(
action="click",
selector="#submit-expense-btn",
coordinates={"x": 1150, "y": 420},
description="Click the Submit button",
speech_transcript="Now I'll click submit to send the report for approval",
timestamp=1700000004,
),
],
)
Khi người dùng sau đó nói “Submit my expense report for the team lunch ($85.50)”, playback service sẽ ghép demo context, năm screenshot đã annotate, và giá trị mới từ request. Claude sẽ thấy rõ cần click ở đâu, đi theo sequence nào, và điều chỉnh số tiền cùng mô tả theo task mới.
Nếu workflow quá dài đến mức không thực tế khi nhét toàn bộ làm ví dụ, hãy compact workflow trước rồi mới dùng làm demonstration.
Kết luận
Những nguyên tắc này phản ánh hiểu biết hiện tại của Anthropic về điều gì làm cho tích hợp computer use ổn định trong production. Chúng áp dụng cho họ model Claude 4.6 và Opus 4.7, và chắc chắn sẽ còn thay đổi khi model và kỹ thuật tiếp tục tiến hóa.
Điểm chung lớn nhất là rất thực dụng: resize ảnh đúng, scale tọa độ đúng, sắp xếp message đúng, giữ context có kỷ luật, và đừng bao giờ coi web content là nguồn đáng tin tuyệt đối. Nếu làm tốt mấy phần này, agent của bạn sẽ bền hơn rất nhiều so với việc chỉ tăng prompt dài hơn.
Nếu muốn đi sâu hơn, bạn có thể xem thêm tài liệu computer use, demo implementation mới của Anthropic, hoặc bài research gốc về computer use để hiểu nền tảng hình thành các capability này.
Bình luận