Unknown là lỗi hay là một kết quả?
Khi bạn bắt đầu phân loại các tương tác thành Human, Human + AI, Agent hoặc Unknown, nhóm Unknown thường lớn hơn mọi người dự đoán. Rất dễ muốn xem đó là một khoảng trống cần che đi, bằng cách gộp Unknown vào Human hoặc coi nó là đáng ngờ. Cả hai cách đều gây ra vấn đề.
Unknown có nghĩa là evidence hiện có không đủ để đưa ra một xác định đáng tin cậy. Một request từ client không chạy JavaScript, một lời gọi đến endpoint nơi bạn không thu được tín hiệu nào, một phiên kết thúc sau một trang: tất cả đều có thể hoàn toàn hợp lệ, và không điều nào trong số đó cho bạn đủ dữ liệu để biết ai hoặc cái gì đang hành động.
Báo cáo Unknown một cách trung thực là điều giúp các lớp khác đáng tin cậy. Nếu hệ thống của bạn không bao giờ nói Unknown, thì mọi kết quả Human đều ít nhiều là một phỏng đoán, và bạn không thể biết phần nào là phỏng đoán. Bài viết của chúng tôi về vì sao Unknown là một kết quả hợp lệ khi phân loại lưu lượng AI giải thích sâu hơn về lý do này.
Hướng dẫn này trình bày cách xử lý Unknown trong thực tế: fallback rõ ràng theo từng route, các quy tắc ngăn nó rò rỉ sang lớp khác, cách theo dõi, và cách giảm nó ở nơi quan trọng.
Bước 1: Không bao giờ mặc định thành Human
Sai lầm phổ biến nhất là một hàm phân loại trả về Human bất cứ khi nào nó không tìm thấy tín hiệu tự động hóa nào. Nhìn thì có vẻ hợp lý, nhưng là sai. Việc không có tín hiệu bot không có nghĩa là có tín hiệu người.
// Wrong: silence becomes Human
function classifyWrong(e: Evidence) {
if (e.signatureValid) return { actor: "agent", basis: "verified" };
if (e.declaredAgent) return { actor: "agent", basis: "declared" };
return { actor: "human", basis: "inferred" };
}
// Right: Human requires positive evidence, otherwise Unknown
function classify(e: Evidence) {
if (e.signatureValid) return { actor: "agent", basis: "verified" };
if (e.declaredAgent) return { actor: "agent", basis: "declared" };
if (e.interactiveSession) return { actor: "human", basis: "inferred" };
return { actor: "unknown", basis: "unknown" };
}Áp dụng cùng một quy tắc ở mọi nơi kết quả được tạo ra: timeout, lỗi, cache cũ và telemetry bị thiếu đều phải cho ra Unknown. Viết một test cho từng đường đi này để hành vi không thể âm thầm thoái lui. Ví dụ dưới đây dùng Node.js test runner có sẵn.
import { test } from "node:test";
import assert from "node:assert/strict";
test("missing evidence is unknown, not human", () => {
const r = classify({ signatureValid: false, declaredAgent: false, interactiveSession: false });
assert.equal(r.actor, "unknown");
});Bước 2: Đặt một fallback rõ ràng cho từng route
Unknown cần một hành vi được xác định, và hành vi đúng phụ thuộc vào route. Hãy quyết định theo từng route, ghi lại và giữ nó trong cấu hình. Để hiểu các fallback này phù hợp với một mô hình policy rộng hơn như thế nào, xem thiết kế policy ở cấp ứng dụng cho người và agent AI.
| Loại route | Ví dụ | Fallback hợp lý cho Unknown |
|---|---|---|
| Nội dung công khai | Trang marketing, tài liệu | Cho phép, phản hồi tiêu chuẩn |
| Dữ liệu chỉ đọc | Catalog, API tìm kiếm | Cho phép với giới hạn tốc độ tiêu chuẩn |
| Tạo tài khoản | Đăng ký | Giữ nguyên các kiểm tra hiện có, hàng đợi review tùy chọn |
| Thay đổi nhạy cảm | Mật khẩu, email, chi tiết thanh toán | Xác thực lại hiện có, không nới lỏng |
| Hành động giá trị cao | Xuất hàng loạt, thao tác quản trị | Ủy quyền mạnh hiện có |
Mẫu này rất đơn giản. Với các route ít rủi ro, Unknown hoạt động như lưu lượng bình thường. Với các route rủi ro cao, Unknown nhận cùng mức bảo vệ mà route đó vốn đã có. Trong cả hai trường hợp, kết quả actor không làm cho một người dùng chưa được phân loại nhưng hợp lệ bị thiệt hơn.
type Fallback = "allow" | "standard_limit" | "existing_checks" | "review";
const unknownFallback: Record<string, Fallback> = {
"GET /docs/*": "allow",
"GET /api/catalog": "standard_limit",
"POST /signup": "existing_checks",
"POST /account/password": "existing_checks",
"POST /exports": "review",
};Bước 3: Xử lý timeout và lỗi theo cùng một cách
Đánh giá actor nằm trên đường đi của request, nên nó phải có giới hạn thời gian nghiêm ngặt. Khi vượt quá ngân sách thời gian đó, hãy tạo Unknown và áp dụng fallback của route. Không bao giờ chặn request chỉ vì việc đánh giá quá chậm.
async function withBudget<T>(work: Promise<T>, ms: number, onTimeout: T): Promise<T> {
let timer: NodeJS.Timeout;
const timeout = new Promise<T>((resolve) => {
timer = setTimeout(() => resolve(onTimeout), ms);
});
try {
return await Promise.race([work, timeout]);
} finally {
clearTimeout(timer!);
}
}
const result = await withBudget(evaluateActor(req), 150, { actor: "unknown", basis: "unknown" });Ghi lại lý do vì sao một kết quả là Unknown: không có evidence, timeout, lỗi đánh giá hoặc evidence cũ. Những lý do này cho bạn biết cần sửa gì.
Bước 4: Không coi Unknown là đáng ngờ
Unknown không phải là một điểm rủi ro. Nhiều client hợp lệ sẽ luôn là Unknown ở một số route: công cụ dòng lệnh, tích hợp phía server không có chữ ký, công cụ hỗ trợ truy cập, trình duyệt ưu tiên quyền riêng tư và các trình đọc feed đơn giản. Ngay cả các nhà vận hành AI lớn hiện nay cũng chủ yếu nhận diện trình thu thập của họ bằng user agent và các dải IP được công bố. Ví dụ, tài liệu crawler của OpenAI liệt kê một chuỗi user agent và một tệp địa chỉ IP được công bố cho từng bot của họ tính đến November 2026.
Nếu bạn muốn phản ứng trước hành vi đáng ngờ, hãy dựa trên hành vi mà bạn có thể mô tả, chẳng hạn như tốc độ request, mẫu đăng nhập thất bại hoặc báo cáo lạm dụng, cùng với evidence riêng của nó. Giữ logic đó tách biệt khỏi lớp actor để không làm méo lớp kia.
Bước 5: Bạn theo dõi tỷ lệ Unknown như thế nào?
Tỷ lệ Unknown là phần tương tác được phân loại là Unknown. Hãy theo dõi nó theo từng route, từng ngữ cảnh tích hợp và theo thời gian. Đây là một trong những chỉ số sức khỏe hữu ích nhất mà bạn có.
type Row = { route: string; actor: string };
export function unknownRate(rows: Row[]) {
const byRoute = new Map<string, { total: number; unknown: number }>();
for (const r of rows) {
const s = byRoute.get(r.route) ?? { total: 0, unknown: 0 };
s.total += 1;
if (r.actor === "unknown") s.unknown += 1;
byRoute.set(r.route, s);
}
return [...byRoute].map(([route, s]) => ({ route, rate: s.unknown / s.total, total: s.total }));
}Các con số cho bạn biết gì:
- Tỷ lệ cao và ổn định trên một route thường có nghĩa là bạn đang thiếu tín hiệu ở đó. Một trang không bao giờ tải tích hợp trình duyệt của bạn, hoặc một API không bao giờ thấy request đã ký, sẽ chủ yếu ở trạng thái Unknown.
- Một sự tăng đột ngột thường có nghĩa là có gì đó đã thay đổi trong stack của bạn, ví dụ một bản release làm rơi mất header, một quy tắc CDN xóa các header chữ ký, hoặc một thay đổi frontend khiến ứng dụng của bạn không còn gửi declarations nữa.
- Một sự giảm đột ngột cũng đáng kiểm tra. Nếu Unknown giảm trong khi Human tăng, hãy xác nhận rằng evidence mới đã xuất hiện thay vì một fallback nào đó âm thầm thay đổi.
Hãy cảnh báo khi có thay đổi mạnh, không phải theo mức tuyệt đối. Mỗi ứng dụng đều có ngưỡng bình thường riêng.
Bước 6: Làm thế nào để giảm Unknown ở nơi quan trọng?
Bạn không cần đưa Unknown về 0. Bạn cần đủ evidence trên những route mà quyết định là quan trọng. Hãy xử lý theo thứ tự mức tác động:
- Thêm evidence trước tiên vào các route có tác động lớn. Nếu thay đổi tài khoản phần lớn là Unknown, đó là nơi một tích hợp trình duyệt hoặc một kiểm tra phía server mang lại hiệu quả.
- Khuyến khích client tự nhận diện. Công bố tài liệu cho API của bạn giải thích cách các agent có thể ký request bằng HTTP Message Signatures và các quy ước IETF Web Bot Auth, đồng thời cung cấp cho client được xác minh một trải nghiệm tốt hơn, chẳng hạn như giới hạn cao hơn hoặc phản hồi có cấu trúc. Các client có thể xác minh sẽ bắt đầu làm như vậy.
- Dùng kiến thức của chính ứng dụng bạn. Nếu người dùng tương tác với trợ lý tích hợp sẵn của bạn, hãy ghi nhận điều đó như một declaration. Ứng dụng của bạn thường biết nhiều hơn mạng.
- Sửa phần kết nối. Đảm bảo proxy chuyển tiếp các header mà bạn phụ thuộc vào và việc đánh giá có đủ ngân sách thời gian để hoàn tất.
Để xem thực tế các tín hiệu nào làm lưu lượng rời khỏi Unknown, hãy đọc cách biết lưu lượng website có đến từ agent AI hay không.
Bước 7: Hiển thị Unknown một cách trung thực trong dashboard
Hiển thị Unknown như một chuỗi riêng với cùng trọng số trực quan như các lớp khác. Không giấu nó trong một nhóm "other", và cũng không tô màu nó như một cảnh báo. Khi các bên liên quan thấy phần Unknown lớn, phản ứng đúng là "chúng ta cần thêm evidence ở đâu", không phải "bot đang ở đâu".
Bước 8: Review Unknown bằng kết quả, không phải giả định
Cứ vài tuần một lần, hãy lấy mẫu các tương tác Unknown từ những route quan trọng nhất của bạn và xem thực tế đã xảy ra gì. Phiên đó đã hoàn tất mua hàng, tạo dự án, đọc ba bài viết, hay thất bại lặp đi lặp lại khi đăng nhập? Kết quả cho bạn biết loại lưu lượng nào đang nằm trong nhóm đó mà không cần áp một nhãn quá sớm lên nó.
Nhóm những gì bạn tìm thấy thành ba loại thực tế:
- Hợp lệ và rủi ro thấp. Trình đọc feed, bản xem trước liên kết, công cụ giám sát và những người dùng có cài đặt quyền riêng tư. Giữ fallback của route như hiện tại.
- Tự động hóa hợp lệ có thể tự nhận diện. Các tích hợp và agent sẽ sẵn sàng dùng một đường đi có cấu trúc hoặc ký request nếu bạn cung cấp một tùy chọn như vậy. Hãy công bố hướng dẫn và chủ động liên hệ khi có thể.
- Hành vi cần kiểm soát riêng. Mẫu stuffing thông tin xác thực hoặc scraping, cả hai đều được lập danh mục trong dự án OWASP Automated Threats to Web Applications. Hãy xử lý chúng bằng các kiểm soát dựa trên hành vi có evidence riêng, chẳng hạn như tỷ lệ đăng nhập thất bại, và giữ chúng tách khỏi lớp actor.
Việc review này giữ cho các fallback của bạn bám vào lưu lượng thực tế và cho bạn một danh sách rõ ràng về nơi cần bổ sung evidence tiếp theo.
Câu hỏi thường gặp
Unknown có nên tính vào rate limit không? Hãy dùng giới hạn tiêu chuẩn của bạn. Giới hạn theo lớp là phù hợp với verified agents, vì họ có thể đạt được giới hạn cao hơn, nhưng Unknown nên nhận mức giới hạn bình thường, không phải mức trừng phạt.
Chúng ta có thể challenge người dùng Unknown không? Chỉ ở nơi route đó vốn đã challenge mọi người trong tình huống đó. Việc thêm challenge chỉ vì kết quả là Unknown sẽ phạt những người dùng hợp lệ có client gửi ít tín hiệu hơn.
Unknown có giảm khi các tiêu chuẩn trưởng thành hơn không? Khi ngày càng nhiều client tự động ký request, nhiều lưu lượng agent sẽ chuyển từ Unknown hoặc declared sang verified. Việc theo dõi của bạn sẽ cho thấy sự chuyển dịch đó theo từng route.
Proof of Actor phù hợp ở đâu
Proof of Actor báo cáo Unknown như một kết quả hạng nhất, kèm theo lý do, và không bao giờ chuyển nó thành Human. Ứng dụng của bạn chọn fallback cho từng route, còn phần phân tích cho thấy coverage kết thúc ở đâu để bạn có thể bổ sung evidence ở nơi quan trọng.
Để thiết lập điều này trên một ứng dụng production cùng với nhóm của chúng tôi, hãy đăng ký quyền truy cập sớm. Để hiểu chính xác evidence có thể xác lập điều gì, hãy đọc Detection & Limitations.
Nguồn
- RFC 9421: HTTP Message Signatures: tiêu chuẩn mà các client tự động có thể dùng để ký request
- draft-ietf-webbotauth-httpsig-protocol: bản thảo IETF Web Bot Auth cho lưu lượng tự động đã ký (đang được phát triển tính đến November 2026)
- OpenAI: Overview of OpenAI Crawlers: chuỗi user agent và các tệp địa chỉ IP được công bố cho bot của OpenAI
- OWASP Automated Threats to Web Applications: phân loại các mối đe dọa tự động như credential stuffing và scraping
- Node.js test runner: module
node:testđược dùng trong ví dụ