Minh bạch tiến trình với Trace
Khi hệ thống làm việc thay người dùng — agent AI, pipeline, tác vụ nền — hãy cho họ thấy từng bước: đang làm gì, mất bao lâu, sai ở đâu và có thể làm gì tiếp.
Vì sao cần minh bạch
Một spinner “Đang xử lý…” kéo dài 20 giây khiến người dùng nghi ngờ, bấm lại, hoặc bỏ đi. Một danh sách bước đang tiến triển thì không.
- Niềm tin — người dùng thấy AI đã đọc tài liệu nào, gọi công cụ nào trước khi tin vào câu trả lời.
- Quyền kiểm soát — biết đang ở bước nào thì mới quyết định chờ, dừng hay thử lại.
- Gỡ lỗi — khi sai, bước lỗi và log nằm ngay đó, không phải mở tab khác.
Sáu trạng thái
Mỗi trạng thái có icon riêng, màu token riêng và nhãn chữ (đọc được bởi trình đọc màn hình) — màu không bao giờ là tín hiệu duy nhất.
| Trạng thái | Nhãn | Khi nào | Màu |
|---|---|---|---|
pending | Đang chờ | Đã lên kế hoạch, chưa bắt đầu. | text-foreground-3 |
running | Đang chạy | Đang thực hiện — đồng hồ chạy trực tiếp. | text-brand-foreground-1 |
success | Hoàn tất | Xong, có thời lượng. | text-success-foreground-1 |
error | Lỗi | Thất bại — tự mở chi tiết, nói nguyên nhân. | text-danger-foreground-1 |
skipped | Bỏ qua | Không cần chạy (điều kiện không thoả, cache trúng). | text-foreground-3 |
cancelled | Đã huỷ | Bị dừng bởi người dùng hoặc vì bước trước lỗi. | text-warning-foreground-1 |
Chọn độ chi tiết
Một bước = một việc người dùng hiểu được. Chi tiết kỹ thuật nằm trong phần mở rộng, không nằm trên dòng tiêu đề.
Tạo báo cáo tháng 10
Đang chờ
- 2.1ssales_db12 480 dòng
- Truy vấn đơn hàng, Hoàn tất1.2s
- Truy vấn hoàn tiền, Bỏ qua
Không có hoàn tiền trong kỳ.
- 3.4s
{ "revenue": 1284000000, "orders": 3120, "aov": 411538} - Viết nhận xét, Hoàn tất4.1ssakura-12.1k token
- Tiêu đề bước là động từ + đối tượng (“Lấy dữ liệu bán hàng”); tên hàm / công cụ để trong metadata hoặc details.
- Lồng tối đa 2 cấp. Agent gọi 30 lệnh nhỏ → gộp thành một bước cha “Đọc 30 tệp” với bước con thu gọn.
- metadata cho thông tin quét nhanh: công cụ, model, số token, số dòng, nhánh git.
- details (log, JSON, CodeBlock) mặc định thu gọn; bước lỗi và bước đang chạy tự mở.
Cập nhật trực tiếp
Trace là component hiển thị thuần: bạn giữ danh sách bước trong state và cập nhật theo sự kiện từ agent.
// Sự kiện từ agent (SSE / WebSocket) → props của TraceStep
type AgentEvent =
| { type: "step_started"; id: string; title: string; at: number }
| { type: "step_finished"; id: string; at: number; tokens?: number }
| { type: "step_failed"; id: string; at: number; error: string };
function reduce(steps: Step[], e: AgentEvent): Step[] {
switch (e.type) {
case "step_started":
return [...steps, { id: e.id, title: e.title, status: "running", startedAt: e.at }];
case "step_finished":
return steps.map((s) => s.id === e.id ? { ...s, status: "success", duration: e.at - s.startedAt } : s);
case "step_failed":
return steps.map((s) => s.id === e.id ? { ...s, status: "error", error: e.error } : s);
}
}
<Trace title="Agent" startedAt={runStartedAt}>
{steps.map((s) => (
<TraceStep
key={s.id}
title={s.title}
status={s.status}
startedAt={s.startedAt}
duration={s.duration}
details={s.error && <TraceLog intent="error">{s.error}</TraceLog>}
/>
))}
</Trace>| Prop · Kiểu | Mặc định | Mô tả |
|---|---|---|
| statusTraceStatus | Mặc định: "pending" | Đổi status là đủ — icon, màu, đồng hồ, thông báo tự theo. |
| startedAtnumber | Mặc định: — | Mốc bắt đầu từ server để đồng hồ chính xác; bỏ trống thì tính từ lúc chuyển sang running. |
| durationnumber (ms) | Mặc định: — | Thời lượng thật khi xong. |
| Trace | Mặc định: — | Đồng hồ tổng khi đang chạy; tổng thời lượng khi xong. |
| Trace | Mặc định: true | Gộp các thay đổi cùng nhịp thành một thông báo polite. |
Khi có lỗi
Bấm Chạy: bước get_order sẽ hết thời gian chờ ở lần đầu. Các bước sau chuyển sang Đã huỷ, và phần đầu đưa ra hành động tiếp theo.
Trợ lý: kiểm tra đơn hàng #A1023
Đang chờ
- Phân tích câu hỏi, Đang chờ
- search_docs("đổi trả"), Đang chờ
- get_order("#A1023"), Đang chờ
- Soạn câu trả lời, Đang chờ
- Mô tả lỗi bằng ngôn ngữ người dùng (“không phản hồi sau 5 giây”); log kỹ thuật nằm trong details.
- Đánh dấu các bước phụ thuộc là cancelled — đừng để chúng ở pending như thể vẫn sẽ chạy.
- Cho thử lại từ bước lỗi thay vì chạy lại tất cả khi có thể.
Khả năng tiếp cận
| Khía cạnh | Cách Trace xử lý |
|---|---|
| Ngữ nghĩa | Vùng <section> có tên (tiêu đề); các bước là role=list / listitem, bước con là danh sách lồng. |
| Trạng thái | Mỗi bước có chữ ẩn “, Hoàn tất” / “, Lỗi”… ngay trong tên — không chỉ dựa vào icon hay màu. |
| Mở rộng | Tiêu đề bước có details / bước con là nút disclosure với aria-expanded + aria-controls; Enter / Space để mở. |
| Thông báo | Một vùng role=status polite đọc “Tên bước: trạng thái”; thay đổi cùng nhịp được gộp làm một. |
| Chuyển động | Spinner đứng yên và bước mới không mờ dần khi người dùng bật giảm chuyển động. |
| Log | TraceLog luôn dir="ltr", focus được bằng Tab để cuộn bằng bàn phím. |
Đặt title của TraceStep là chuỗi (hoặc truyền announceLabel) để thông báo trạng thái có nội dung.
Nên & không nên
- Hiện bước ngay khi agent bắt đầu nó, không đợi xong mới in ra.
- Ghi thời lượng cho từng bước để người dùng biết chậm ở đâu.
- Mở sẵn bước lỗi, kèm nguyên nhân và hành động thử lại.
- Dùng Trace size small, thu gọn, trong tin nhắn của trợ lý AI.
- Không giả lập tiến độ bằng các bước bịa — chỉ hiện việc thật sự xảy ra.
- Không để bước phụ thuộc ở pending khi pipeline đã dừng.
- Không đưa dữ liệu nhạy cảm (token, mật khẩu) vào metadata hay log hiển thị.