Product Management
Đăng nhập
ESC

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

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

Bài 3 — Thiết lập approval gate: chèn điểm dừng vào luồng agent

Đã đọc 0/7 mục · còn khoảng 3 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.

Giờ ta biến policy thành cơ chế thật: một approval gate chặn hành động rủi ro cao lại, tạo yêu cầu phê duyệt, và chỉ cho hành động chạy tiếp khi được người duyệt chấp thuận.

Mẫu kiến trúc: interrupt & resume

Điểm mấu chốt là agent phải tạm dừng được và tiếp tục lại (interrupt/resume). Nghĩa là khi gặp hành động cần duyệt, agent không block-chờ đồng bộ (sẽ chết timeout), mà:

  • Lưu lại toàn bộ trạng thái cần thiết để sau chạy tiếp.
  • Tạo một approval request với đầy đủ ngữ cảnh.
  • Trả quyền điều khiển về, chờ sự kiện "đã duyệt/từ chối".
  • Khi có quyết định, khôi phục trạng thái và thực thi (hoặc hủy).
Đây là lý do các framework agent hiện đại (LangGraph, v.v.) có khái niệm checkpoint/interrupt — nhưng bạn tự làm cũng được với một hàng đợi và bảng DB.

Ví dụ cụ thể: wrapper cổng phê duyệt

def gated_execute(action, ctx):
    risk = assess_risk(action, ctx)          # từ Bài 2
    level = policy.level_for(risk)

    if level in ('L0', 'L1', 'L2'):
        result = action.run()                # chạy ngay
        audit_log.write(action, ctx, result, auto=True)
        return result

    # L3/L4: tạo yêu cầu phê duyệt và DỪNG
    req = ApprovalRequest.create(
        action=action.serialize(),           # đủ để chạy lại sau
        context=ctx.summary(),
        risk=risk,
        approvers_needed=2 if level == 'L4' else 1,
        expires_at=now() + timedelta(hours=4)
    )
    notify_approvers(req)
    raise Interrupt(req.id)                   # thoát khỏi luồng, chờ resume

Và phía resume khi có người duyệt:

def on_approved(req_id):
    req = ApprovalRequest.get(req_id)
    if req.approvals_count < req.approvers_needed:
        return                               # chưa đủ chữ ký
    action = deserialize(req.action)
    result = action.run()
    audit_log.write(action, req.context, result,
                    approved_by=req.approvers)

Yêu cầu phê duyệt phải chứa gì?

Một approval request tồi chỉ ghi "Agent muốn hoàn tiền — Duyệt/Từ chối?". Người duyệt không đủ thông tin nên sẽ bấm bừa. Một request tốt gồm:

  • Hành động cụ thể: "Hoàn 3.000.000đ cho đơn #4821".
  • Lý do agent đưa ra: "Khách báo giao thiếu 2 sản phẩm, đã xác nhận qua ảnh.".
  • Bằng chứng/ngữ cảnh: link hội thoại, ảnh, dữ liệu đơn.
  • Điểm rủi ro và mức tự chủ đã tính.
  • Hệ quả nếu duyệt / nếu từ chối.
  • Thời hạn của yêu cầu.

Các bước triển khai approval gate

  • Bọc mọi lời gọi tool write qua một hàm gated_execute duy nhất — không cho tool nào chạy tắt ngoài cổng.
  • Tạo bảng approval_requests với trạng thái: pending / approved / rejected / expired.
  • Serialize hành động đủ chi tiết để chạy lại y hệt sau khi duyệt (idempotency key kèm theo — xem Bài 4).
  • Xây kênh thông báo cho người duyệt (email, Slack, Telegram) kèm link tới màn duyệt.
  • Xây màn duyệt hiển thị đủ ngữ cảnh, nút Duyệt/Từ chối, ô ghi lý do.
  • Xử lý hết hạn: request quá thời hạn tự chuyển expired và thông báo lại cho agent.

Checklist một approval gate đạt chuẩn

  • [ ] Không có đường nào để hành động write chạy mà bỏ qua cổng?
  • [ ] Trạng thái agent được lưu để resume chính xác?
  • [ ] Request chứa đủ ngữ cảnh để người duyệt quyết định trong 30 giây?
  • [ ] Có thời hạn và xử lý khi hết hạn?
  • [ ] Có phân biệt cần 1 hay nhiều người duyệt?

Sai lầm thường gặp

  • Chặn đồng bộ (block synchronously). Giữ luồng agent chờ người bấm nút khiến timeout, tốn tài nguyên, và mất trạng thái khi service restart. Luôn dùng interrupt/resume.
  • Request thiếu ngữ cảnh. Người duyệt không đủ dữ kiện sẽ bấm Duyệt cho xong — gate mất tác dụng.
  • Có cửa hậu (bypass path). Một tool nào đó gọi API trực tiếp không qua cổng là lỗ hổng chí mạng. Mọi write phải đi qua một cửa.
  • Không có hết hạn. Request treo mãi khiến hàng đợi phình to và khách chờ vô thời hạn.
  • Serialize thiếu. Nếu không lưu đủ để chạy lại, sau khi duyệt agent thực thi sai so với lúc đề xuất.
Bài sau ta lo phần hậu quả: làm sao undo một hành động và đảm bảo thực thi lại không bị nhân đôi.

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