DEV Community

Cover image for Hệ thống kiểm soát tác nhân AI: Cổng phê duyệt và Giới hạn phạm vi tác động
Sebastian Petrus
Sebastian Petrus

Posted on • Originally published at apidog.com

Hệ thống kiểm soát tác nhân AI: Cổng phê duyệt và Giới hạn phạm vi tác động

Đã 3 giờ sáng. Tác nhân của bạn đã xử lý một hàng dài yêu cầu hỗ trợ trong khi bạn ngủ. Một yêu cầu trông giống như leo thang, nên tác nhân viết tóm tắt và gửi email cho sếp. Bản tóm tắt chính xác, ngữ pháp tốt—nhưng không ai yêu cầu email đó, không ai duyệt trước và không có gì ngăn nó gửi đi sau khi mô hình đã quyết định. Tác nhân đã làm đúng những gì hướng dẫn cho phép. Đó mới là vấn đề.

Dùng thử Apidog ngay hôm nay

Những lỗi gây thiệt hại lớn nhất thường không phải là ảo giác hay workflow bị lỗi. Các lỗi đó dễ thấy. Rủi ro nguy hiểm hơn là tác nhân thực hiện đúng lệnh: gửi email, xóa hồ sơ hoặc tạo thanh toán mà không có lớp kiểm tra giữa quyết định của mô hình và tác dụng phụ thực tế.

Hàng rào bảo vệ (guardrails) là lớp kiểm tra một hành động trước khi hành động xảy ra. Lớp này phải quyết định rõ ràng: cho phép, chặn hoặc yêu cầu con người phê duyệt.

Bài viết này tập trung vào bốn guardrail có thể triển khai ngay:

  1. Danh sách hành động được phép (allowlist)
  2. Cổng phê duyệt (approval gate)
  3. Chế độ chạy thử (dry-run)
  4. Giới hạn phạm vi ảnh hưởng (blast radius)

Sau đó, phần quan trọng nhất: kiểm tra để chứng minh guardrail thực sự hoạt động. Để có bối cảnh rộng hơn, hãy xem bài viết về lý do các tác nhân AI gặp lỗi trong môi trường sản xuất, trong đó thiếu guardrail là một trong năm chế độ lỗi chính.

Sắp xếp hành động theo mức độ gây hại

Không phải hành động nào cũng cần cổng kiểm soát.

Một tác nhân đọc lịch, tra cứu dự báo thời tiết hoặc truy vấn báo cáo chỉ đọc có thể chạy tự động. Nếu bắt người dùng phê duyệt mọi lệnh đọc, họ sẽ hình thành thói quen nhấn “cho phép” mà không kiểm tra. Khi đó, phê duyệt trở nên vô nghĩa ở những thời điểm thực sự quan trọng.

Bắt đầu bằng cách chia tool/API mà tác nhân gọi thành hai nhóm:

Nhóm Ví dụ Cách xử lý
Allowlist Đọc dữ liệu, tìm kiếm, tra cứu idempotent, tạo bản nháp có thể hoàn tác Cho phép chạy tự động
Cần kiểm soát Gửi email, xóa dữ liệu, thanh toán, cập nhật hệ thống hồ sơ Chặn hoặc yêu cầu phê duyệt

Đừng phân loại chỉ dựa trên HTTP verb. Một POST tạo bản nháp có thể an toàn; một POST tạo bản nháp rồi gửi email thì không.

Hãy phân loại theo hậu quả. Dùng câu hỏi này cho từng hành động:

Nếu tác nhân thực hiện hành động này 100 lần do nhầm lẫn, hậu quả có nghiêm trọng không?

Nếu câu trả lời không phải là “không đáng kể”, hành động đó không nên nằm trong allowlist.

Ví dụ policy đơn giản:

type ToolName =
  | "search_knowledge_base"
  | "get_customer_ticket"
  | "create_email_draft"
  | "send_email"
  | "delete_customer_record"
  | "create_payment";

const AUTO_APPROVED_TOOLS = new Set<ToolName>([
  "search_knowledge_base",
  "get_customer_ticket",
  "create_email_draft",
]);

function requiresApproval(toolName: ToolName): boolean {
  return !AUTO_APPROVED_TOOLS.has(toolName);
}
Enter fullscreen mode Exit fullscreen mode

Mặc định an toàn nên là: tool mới chưa được phân loại thì không tự động chạy.

Đưa con người vào quy trình cho hành động phá hoại

Sau khi xác định các hành động nguy hiểm, thêm cổng phê duyệt. Tác nhân phải tạm dừng, hiển thị yêu cầu thực tế và chờ người có quyền xác nhận.

Đây là mô hình human-in-the-loop. Nó biến một sai lầm không thể hoàn tác thành một yêu cầu có thể bị từ chối.

Một cổng phê duyệt tốt không chỉ hiển thị:

“Tác nhân muốn gửi email.”

Nó phải hiển thị đầy đủ thông tin mà người duyệt cần:

  • Người nhận
  • Tiêu đề
  • Nội dung email
  • Lý do tác nhân đề xuất hành động
  • Tool/API sẽ được gọi
  • Payload thực tế
  • Tác dụng phụ dự kiến

Ví dụ dữ liệu yêu cầu phê duyệt:

{
  "action": "send_email",
  "reason": "Yêu cầu hỗ trợ có dấu hiệu cần leo thang",
  "request": {
    "method": "POST",
    "url": "/emails/send",
    "body": {
      "to": ["manager@example.com"],
      "subject": "Tóm tắt yêu cầu hỗ trợ #4821",
      "content": "..."
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Người duyệt không nên phải tin vào phần tóm tắt của tác nhân. Họ cần thấy payload mà hệ thống sắp gửi.

Triển khai theo hai bước:

async function executeToolCall(toolName: ToolName, args: unknown) {
  if (requiresApproval(toolName)) {
    return createApprovalRequest({
      toolName,
      args,
      status: "pending",
    });
  }

  return runTool(toolName, args);
}
Enter fullscreen mode Exit fullscreen mode

Chỉ chạy tool sau khi nhận được phê duyệt rõ ràng:

async function approveAction(approvalId: string, reviewerId: string) {
  const approval = await getApproval(approvalId);

  if (approval.status !== "pending") {
    throw new Error("Yêu cầu không còn ở trạng thái chờ duyệt");
  }

  await recordApproval({
    approvalId,
    reviewerId,
    decision: "approved",
  });

  return runTool(approval.toolName, approval.args);
}
Enter fullscreen mode Exit fullscreen mode

Việc từ chối cũng phải đơn giản, rõ ràng và được ghi log. Nếu quy trình từ chối chậm hoặc khó hiểu, người dùng sẽ phê duyệt theo phản xạ.

Cuộc thảo luận trong SDK của Anthropic về việc thêm bước phê duyệt của con người trước khi tác nhân hành động cũng nhấn mạnh cùng một điểm: người đánh giá không thể đưa ra quyết định thực sự nếu không nhìn thấy payload cụ thể.

Ghi lại mọi quyết định:

{
  "approval_id": "apr_123",
  "tool": "delete_customer_record",
  "decision": "rejected",
  "reviewer_id": "user_456",
  "timestamp": "2025-03-08T03:00:00Z",
  "reason": "Bản ghi không khớp với yêu cầu"
}
Enter fullscreen mode Exit fullscreen mode

Nhật ký này là dữ liệu điều tra khi một guardrail bị bỏ qua hoặc bị cấu hình sai.

Cung cấp chế độ chạy thử (dry-run)

Cổng phê duyệt bảo vệ production. Chế độ chạy thử bảo vệ bạn trong giai đoạn phát triển và staging.

Trong dry-run, tác nhân vẫn thực hiện toàn bộ quá trình suy luận:

  1. Chọn tool
  2. Xây dựng request
  3. Chọn arguments
  4. Lập kế hoạch gọi API

Nhưng hệ thống dừng trước khi tạo tác dụng phụ. Thay vì gửi request thật, nó trả về request mà nó sẽ gửi.

type ExecutionMode = "live" | "dry-run";

async function runTool(
  toolName: ToolName,
  args: unknown,
  mode: ExecutionMode = "live"
) {
  const request = buildToolRequest(toolName, args);

  if (mode === "dry-run") {
    return {
      mode: "dry-run",
      executed: false,
      toolName,
      plannedRequest: request,
    };
  }

  return callExternalApi(request);
}
Enter fullscreen mode Exit fullscreen mode

Ví dụ output của một lần chạy thử:

{
  "mode": "dry-run",
  "executed": false,
  "toolName": "delete_customer_record",
  "plannedRequest": {
    "method": "DELETE",
    "url": "/customers/cus_123"
  }
}
Enter fullscreen mode Exit fullscreen mode

Chế độ này hữu ích vì hai lý do:

  • Bạn có thể quan sát hành vi của tác nhân với dữ liệu gần thực tế mà không tạo tác dụng phụ.
  • Bạn có thể kiểm tra ý định của tác nhân qua chuỗi tool call và arguments.

Một công cụ gỡ lỗi tác nhân AI chuyên dụng giúp biến nhận xét mơ hồ như “tác nhân đã làm điều gì đó kỳ lạ” thành dữ liệu cụ thể, chẳng hạn:

Tác nhân đã cố gọi endpoint xóa ở bước thứ tư.

Đừng dùng dry-run thay cho approval gate:

  • dry-run phù hợp cho development và staging.
  • Approval gate phù hợp cho production, nơi hành động là thật.

Bạn cần cả hai.

Giới hạn phạm vi ảnh hưởng

Allowlist, approval gate và dry-run quyết định một hành động cụ thể có được thực hiện hay không.

Giới hạn phạm vi ảnh hưởng (blast radius limits) giải quyết câu hỏi khác:

Nếu nhiều thứ vẫn xảy ra sai, tác nhân có thể gây thiệt hại đến mức nào?

Ba giới hạn quan trọng nhất là:

1. Scopes: giới hạn quyền truy cập

Cấp thông tin xác thực với quyền tối thiểu cần thiết.

Một tác nhân quản lý issue của một dự án chỉ nên có token cho dự án đó, không phải khóa admin cho toàn bộ tổ chức.

{
  "token_scope": {
    "project_ids": ["project_support"],
    "permissions": ["issues:read", "issues:write"],
    "forbidden": ["org:admin", "billing:write", "customers:delete"]
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Quotas: giới hạn số lần thực hiện

Giới hạn số lần một hành động có thể chạy trong một khoảng thời gian. Điều này ngăn retry loop hoặc vòng lặp logic gửi hàng nghìn email.

const MAX_EMAILS_PER_HOUR = 10;

async function enforceQuota(agentId: string, action: string) {
  const count = await getActionCount(agentId, action, "1h");

  if (count >= MAX_EMAILS_PER_HOUR) {
    throw new Error(`Đã vượt quota cho ${action}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Spend caps: giới hạn chi phí

Đặt giới hạn cứng cho token và các hành động có chi phí, theo tác vụ hoặc theo ngày.

const MAX_TASK_COST_USD = 2;
const MAX_DAILY_COST_USD = 50;

async function enforceSpendCap(taskId: string, estimatedCost: number) {
  const taskSpend = await getTaskSpend(taskId);

  if (taskSpend + estimatedCost > MAX_TASK_COST_USD) {
    throw new Error("Tác vụ đã vượt giới hạn chi phí");
  }
}
Enter fullscreen mode Exit fullscreen mode

Các giới hạn này cũng là lớp phòng thủ dự phòng. Ngay cả khi một guardrail phức tạp bị bỏ sót, tác nhân vẫn không thể vượt quyền, vượt quota hoặc vượt ngân sách đã định.

Để biết các giới hạn có thực sự hoạt động, hãy theo dõi:

  • Số lần gọi theo tool/action
  • Chi phí theo tác vụ
  • Chi phí theo ngày
  • Tỷ lệ lỗi gần quota
  • Số yêu cầu bị từ chối vì scope
  • Số action bị chặn do spend cap

Theo dõi chúng giống như bạn theo dõi khả năng quan sát API cho một dịch vụ production.

OWASP gọi trực tiếp rủi ro này là “quyền hạn quá mức” (excessive agency) trong OWASP Top 10 cho các ứng dụng mô hình ngôn ngữ lớn (LLM). Scopes, quotas và spend caps đều làm giảm quyền hạn đó.

Cách kiểm tra guardrail

Mỗi guardrail là một nhánh mã chỉ chạy khi hệ thống sắp thực hiện hành động nguy hiểm. Đây thường là những nhánh ít được chạy nhất, vì vậy cũng dễ hỏng âm thầm nhất.

Một cổng không bao giờ kích hoạt và một cổng kích hoạt nhưng bị bỏ qua có thể trông giống nhau trong dashboard nếu bạn không kiểm tra chúng.

Bạn không nên kiểm tra bằng API trực tiếp. Nếu kiểm tra endpoint gửi email thật, bạn có thể tạo chính tác dụng phụ mà guardrail cần ngăn chặn.

Thay vào đó, hãy giả lập endpoint gây tác dụng phụ.

Vòng lặp kiểm tra

  1. Giả lập endpoint gửi, xóa hoặc thanh toán.
  2. Chạy tác nhân với tình huống phải kích hoạt guardrail.
  3. Xác nhận endpoint trực tiếp không nhận request.
  4. Xác nhận yêu cầu phê duyệt được tạo với payload đúng.
  5. Kiểm tra hành động an toàn đi qua mà không yêu cầu phê duyệt.

Ví dụ kiểm tra approval gate:

it("yêu cầu phê duyệt trước khi gửi email", async () => {
  const result = await agent.run({
    input: "Leo thang ticket #4821 tới quản lý",
    mode: "live",
  });

  expect(mockEmailApi.receivedRequests()).toHaveLength(0);

  expect(result.approvalRequest).toMatchObject({
    toolName: "send_email",
    status: "pending",
    args: expect.objectContaining({
      to: expect.any(Array),
      subject: expect.any(String),
    }),
  });
});
Enter fullscreen mode Exit fullscreen mode

Kiểm tra hướng ngược lại:

it("cho phép truy vấn dữ liệu chỉ đọc mà không cần duyệt", async () => {
  const result = await agent.run({
    input: "Tra cứu trạng thái ticket #4821",
    mode: "live",
  });

  expect(result.approvalRequest).toBeUndefined();
  expect(mockTicketApi.receivedRequests()).toHaveLength(1);
});
Enter fullscreen mode Exit fullscreen mode

Điều kiện đạt không phải là:

“Tác nhân đã gửi thành công.”

Điều kiện đạt là:

“Tác nhân đã hỏi trước khi gửi.”

Bạn cũng phải xác nhận rằng action an toàn không bị chặn vô nghĩa. Một cổng chặn mọi thứ cũng thất bại giống như cổng không chặn gì.

Hướng dẫn về cách kiểm tra các tác nhân AI gọi API của bạn trình bày thiết lập đầy đủ. Bài viết về kiểm thử tác nhân AI và API cung cấp thêm các mẫu xác nhận khi mô hình là thành phần không xác định.

Điểm chính: hãy kiểm tra rằng tác dụng phụ không xảy ra và approval flow đã xảy ra. Nếu test của bạn chỉ bao phủ happy path, nó vẫn có thể xanh vào ngày guardrail bị hỏng.

Apidog phù hợp ở đâu — và không phù hợp ở đâu

Cần xác định đúng vai trò của công cụ.

Apidog không phải là framework tác nhân, model server, thư viện guardrail hay nền tảng đánh giá. Nó không xây dựng hoặc chạy tác nhân của bạn, cũng không quyết định action nào là an toàn.

Code và lớp điều phối của bạn vẫn chịu trách nhiệm về:

  • Allowlist
  • Approval gate
  • Cờ dry-run
  • Scopes
  • Quotas
  • Spend caps

Apidog phù hợp ở lớp API mà các guardrail đang bảo vệ:

  • Giả lập endpoint có tác dụng phụ như gửi, xóa hoặc tính phí.
  • Lập trình phản hồi thành công và lỗi giống dịch vụ thực.
  • Chạy kiểm thử mà không chạm vào API production.
  • Kiểm tra request mà tác nhân dự định hoặc cố gắng gửi.
  • Chứng minh action nguy hiểm đi vào luồng phê duyệt thay vì gọi API trực tiếp.

Nói ngắn gọn: Apidog giúp kiểm thử các API mà tác nhân gọi và giả lập API phá hoại để bạn xác minh luồng guardrail.

Các câu hỏi thường gặp

Sự khác biệt giữa allowlist và approval gate là gì?

Allowlist xác định những action có thể chạy tự động mà không cần con người. Approval gate xử lý các action còn lại bằng cách tạm dừng và yêu cầu xác nhận trước khi tạo tác dụng phụ.

Allowlist để phân loại; approval gate để dừng và kiểm tra.

Guardrail có làm tác nhân chậm quá nhiều không?

Chỉ khi bạn kiểm soát sai action. Giữ các thao tác đọc và có thể hoàn tác trong allowlist để chúng chạy nhanh. Chỉ yêu cầu phê duyệt cho action đắt tiền, có phạm vi lớn hoặc khó hoàn tác.

Tôi có thể kiểm tra guardrail mà không gọi API thật không?

Có, và bạn nên làm vậy. Giả lập endpoint tạo tác dụng phụ, chạy tác nhân qua kịch bản nguy hiểm, sau đó xác nhận mock không nhận request trong khi approval flow được kích hoạt.

Tôi nên đặt action nào sau approval gate đầu tiên?

Bắt đầu với action khó hoàn tác nhất:

  • Thanh toán
  • Xóa dữ liệu
  • Gửi email hoặc tin nhắn ra bên ngoài
  • Cập nhật hệ thống hồ sơ
  • Hành động ảnh hưởng trực tiếp đến khách hàng hoặc đồng nghiệp

Nếu một lần lặp lại ngẫu nhiên có thể gây thiệt hại thực sự, action đó nên nằm sau approval gate.

Bắt đầu với hành động phá hoại nhất

Bạn không cần triển khai đủ cả bốn guardrail trong ngày đầu tiên.

Hãy chọn action khiến bạn lo nhất—action mà bạn không muốn phải giải thích trong buổi đánh giá sự cố—và đặt approval gate cho nó trong tuần này.

Sau đó, viết test:

  1. Giả lập endpoint.
  2. Chạy tác nhân qua tình huống nguy hiểm.
  3. Xác nhận tác nhân yêu cầu phê duyệt thay vì gọi API trực tiếp.

Khi test chuyển sang đỏ ngay lần đầu bạn cố tình phá gate, bạn có lý do thực tế để tin vào guardrail của mình.

Tải xuống Apidog để giả lập endpoint gây tác dụng phụ, lập trình phản hồi và xác nhận tác nhân đi theo luồng phê duyệt thay vì luồng trực tiếp.

Top comments (0)