Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 5 — Ngăn hành động nguy hiểm: validate, dry-run & Human-in-the-Loop

Đã đọc 0/7 mục · còn khoảng 4 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Đây là hàng rào cuối cùng và quan trọng nhất: cổng thực thi tool (tool gateway). Dù các lớp trước có thủng, cổng này phải đảm bảo không hành động phá hủy nào xảy ra ngoài kiểm soát. Bài này xây tool gateway với validation, confirmation và Human-in-the-Loop (HITL).

Vòng đời một lời gọi tool an toàn

Model đề xuất tool call
   │
[A] Xác thực schema (tham số đúng kiểu, đủ trường?)
   │
[B] Kiểm tra policy   (tool này agent được phép? tier mấy?)
   │
[C] Kiểm tra ngưỡng   (số tiền, số bản ghi, phạm vi có vượt limit?)
   │
[D] Dry-run/preview    (mô phỏng kết quả, không commit)
   │
[E] HITL nếu Tier ≥ 2  (chờ người duyệt)
   │
[F] Thực thi + audit log

Điểm mấu chốt: model chỉ đề xuất; backend mới quyết định và thực thi. Không bao giờ nối thẳng output model vào hành động phá hủy.

Ví dụ: tool gateway cho hoàn tiền

CONFIRM_TIERS = {"issue_refund": 2, "delete_account": 3, "get_order": 0}
LIMITS = {"issue_refund_max": 500_000}  # VND

def execute_tool(name, args, ctx):
    # [A] schema
    if not validate_schema(name, args):
        return err("Tham số không hợp lệ")

    # [B] policy
    if name not in tools_for(ctx.role, ALL_TOOLS):
        return err("Không có quyền dùng tool này")

    # [C] ngưỡng
    if name == "issue_refund" and args["amount"] > LIMITS["issue_refund_max"]:
        return err(f"Vượt hạn mức tự động ({LIMITS['issue_refund_max']}). Cần duyệt tay.")

    tier = CONFIRM_TIERS.get(name, 2)  # mặc định cần duyệt nếu chưa khai báo

    # [D] preview
    preview = simulate(name, args, ctx)

    # [E] HITL
    if tier >= 2:
        approval = request_human_approval(name, args, preview, ctx)
        if not approval.granted:
            audit("blocked_by_human", name, args, ctx)
            return err("Người duyệt đã từ chối.")

    # [F] thực thi + audit BẤT KỂ kết quả
    result = do_execute(name, args, ctx)
    audit("executed", name, args, ctx, result)
    return result

Chú ý CONFIRM_TIERS.get(name, 2): tool chưa được phân loại thì mặc định cần duyệt — fail safe, không fail open.

Human-in-the-Loop hiệu quả

HITL không phải "hỏi người dùng mọi thứ" (sẽ gây mệt mỏi và người ta bấm Yes như phản xạ). Thiết kế đúng:

  • Chỉ chặn Tier ≥ 2. Tier 0-1 chạy tự do/log để không làm phiền.
  • Hiển thị preview rõ ràng: "Sẽ hoàn 500.000đ cho đơn #123 của khách Nguyễn Văn A. Không thể hoàn tác." — người duyệt cần thấy hậu quả.
  • Mặc định là TỪ CHỐI: timeout không phản hồi = không thực thi.
  • Ghi ai duyệt, lúc nào cho audit.

Các bước dựng tool gateway

  • Bọc mọi tool call qua một hàm gateway duy nhất — không cho gọi tool trực tiếp.
  • Validate schema tham số trước tiên.
  • Kiểm tra policy quyền (từ Bài 4).
  • Áp ngưỡng số học: hạn mức tiền, số bản ghi tối đa mỗi lần, phạm vi.
  • Dry-run cho hành động ghi/xóa: cho model và người xem kết quả mô phỏng trước.
  • Gọi HITL cho Tier ≥ 2, mặc định từ chối khi timeout.
  • Idempotency key cho hành động không hoàn tác được để tránh double-execute khi retry.
  • Audit log bất biến mọi lần thực thi/từ chối.

Checklist trước khi bật một tool phá hủy

  • [ ] Có đi qua gateway tập trung không?
  • [ ] Có ngưỡng số học (tiền/số bản ghi) không?
  • [ ] Có HITL cho hành động không hoàn tác không?
  • [ ] Timeout duyệt = từ chối (fail safe) chứ?
  • [ ] Có idempotency chống double-execute không?
  • [ ] Mọi thực thi có vào audit log không?

Sai lầm thường gặp

  • Nối thẳng model → hành động. Để model tự gọi delete() không qua cổng là lỗi chí mạng.
  • Fail open khi chưa phân loại. Tool mới thêm mà mặc định "cho chạy" → lỗ hổng theo thời gian. Luôn mặc định cần duyệt.
  • HITL cho mọi thứ. Gây "mệt mỏi cảnh báo": người duyệt bấm Yes tự động, HITL thành hình thức. Chỉ chặn cái thực sự nguy hiểm.
  • Preview mơ hồ. "Xác nhận hành động?" không cho người duyệt biết hậu quả → duyệt mù.
  • Quên idempotency. Agent retry sau timeout → hoàn tiền/gửi email hai lần.
  • Ngưỡng đặt ở prompt. "Đừng hoàn quá 500k" trong prompt là vô dụng; ngưỡng phải nằm ở code gateway.
Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi