Có một câu hỏi nhìn qua tưởng là chuyện cấu hình kỹ thuật nhỏ, nhưng thật ra lại chạm đúng một trong những ranh giới sống còn nếu anh em muốn đưa OpenClaw vào môi trường nhiều người dùng: làm sao để agent không chỉ “cư xử như có phân quyền”, mà thật sự bị chặn ở đúng lớp hạ tầng khi đụng tới dữ liệu không được phép xem.
Bài đang được bàn trên r/OpenClawUseCases hỏi khá thẳng về một tình huống rất thật: một OpenClaw agent dùng chung trong Slack, nhưng User A chỉ được thấy dữ liệu của A, User B chỉ được thấy phần của B, còn admin mới có quyền xem toàn bộ. Tác giả còn nói rõ một điểm mà mình rất đồng ý: không muốn dựa vào prompt, mà muốn hard RBAC ở layer tool hoặc API.
Đây là cách đặt vấn đề đúng. Vì trong hệ nhiều người dùng, prompt chỉ là lời dặn. Còn quyền thật phải nằm ở chỗ agent có gọi được tool hay đọc được dữ liệu đó hay không.
Vì sao RBAC cho agent không thể chỉ giải bằng prompt
Rất nhiều anh em khi mới dựng multi-user agent hay đi theo lối tắt này:
- nhét vào system prompt rằng mỗi người chỉ được xem dữ liệu của mình
- dặn agent đừng trả lời vượt quyền
- hy vọng model sẽ luôn cư xử đúng
Cách này có thể đủ cho demo hoặc môi trường ít rủi ro. Nhưng với dữ liệu thật, đây là nền rất yếu.
Lý do đơn giản:
- prompt không phải cơ chế bảo mật cứng
- model có thể hiểu sai ngữ cảnh hoặc suy luận lỏng tay
- một tool call sai là dữ liệu đã bị lộ trước khi anh em kịp sửa câu trả lời
- khi số lượng tool và nguồn dữ liệu tăng lên, việc trông chờ model tự giữ ranh giới sẽ ngày càng mong manh
Nói ngắn gọn, nếu OpenClaw vẫn có quyền chạm vào toàn bộ mọi sheet, mọi API hoặc mọi bảng dữ liệu, thì chuyện “đừng trả lộ ra” chỉ là guardrail mềm. RBAC đúng nghĩa phải chặn từ phía sau, không phải chỉ dặn ở phía trước.
Cách nhìn đúng: phân quyền ở tool boundary, không phải ở lời văn
Điểm hay nhất của câu hỏi Reddit là tác giả đã chốt luôn mục tiêu đúng: enforcement phải ở layer tool/API.
Theo mình, đây là nguyên tắc số một cho multi-user agent:
Agent không nên trở thành nơi quyết định cuối cùng ai được xem gì.
Hệ thống phía sau phải quyết định chuyện đó trước.
Khi nhìn như vậy, bài toán tách ra thành ba lớp rõ ràng.
1. Xác định người gọi là ai
Trước khi nói tới phân quyền, hệ thống phải biết request hiện tại đến từ ai.
Với Slack hoặc nền chat tương tự, thông tin này thường có sẵn ở event inbound:
- user id
- channel id hoặc thread id
- workspace hoặc team id
- đôi khi có thêm role nội bộ nếu anh em map sẵn
Tức là bước đầu tiên không phải prompt engineering, mà là identity propagation. Nếu tool layer không nhận được identity của người gọi, mọi RBAC phía sau đều chỉ là giả lập.
2. Ánh xạ identity sang policy
Sau khi biết user là ai, cần có một lớp policy rõ ràng trả lời được mấy câu hỏi này:
- user này thuộc tenant nào
- được truy cập nguồn dữ liệu nào
- được gọi tool nào
- được gọi tool đó với tham số nào
- có quyền xem dữ liệu raw hay chỉ summary
- có quyền write hay chỉ read
Lớp này có thể rất đơn giản lúc đầu, ví dụ một bảng mapping:
user_id -> rolerole -> allowed_resourcesrole -> allowed_actions
Nhưng nó phải là dữ liệu có thể kiểm tra được, không phải chỉ là lời mô tả trong prompt.
3. Chặn thật ở execution path
Đây là phần nhiều hệ thiếu nhất.
Kể cả khi agent đã biết người dùng là ai và policy nói họ không được xem sheet X, thì tool execution vẫn phải từ chối nếu request cố chạm vào X. Nếu không, toàn bộ lớp policy chỉ là tư liệu tham khảo.
Đây mới là chỗ RBAC trở thành bảo mật thật thay vì etiquette.
Một kiến trúc thực chiến đủ gọn cho anh em bắt đầu
Nếu đang dựng OpenClaw cho nhiều người dùng, mình nghĩ anh em có thể hình dung một kiến trúc 4 lớp như sau.
Lớp 1: Chat identity
Slack gửi event vào kèm user_id, channel_id, team_id.
Lớp adapter hoặc middleware nên chuẩn hóa các thông tin này thành context nội bộ, ví dụ:
- requester_id
- requester_role
- tenant_id
- session_scope
Đừng để mỗi tool phải tự mò lại identity từ raw event. Nên chuẩn hóa một lần rồi truyền xuống dưới.
Lớp 2: Authorization service hoặc policy table
Tại đây anh em lưu rule kiểu:
- User A -> chỉ được sheet khách hàng miền Nam
- User B -> chỉ được sheet khách hàng miền Bắc
- Admin -> được toàn bộ
- Nhóm support -> chỉ được đọc summary, không được sửa
Giai đoạn đầu, lớp này có thể chỉ là:
- một bảng Postgres
- một Google Sheet nội bộ
- một file config có version control
Miễn là nó rõ, kiểm tra được, và không bị chôn trong prompt.
Lớp 3: Guarded tools
Đây là lớp quan trọng nhất.
Thay vì cho OpenClaw gọi trực tiếp mọi tool với credential rộng, anh em nên đặt wrapper hoặc proxy tool có kiểm tra quyền trước khi chạm dữ liệu thật.
Ví dụ:
read_customer_sheet(user_context, target_sheet)query_orders(user_context, customer_id)update_ticket(user_context, ticket_id)
Trong mỗi wrapper này, bước đầu tiên là check policy. Không đủ quyền thì fail ngay. Đủ quyền mới cho đi tiếp.
Lớp 4: Resource scoping
Nếu làm bài bản hơn nữa, đừng chỉ kiểm tra “có được gọi tool này không”, mà kiểm tra luôn “tool này được gọi trên phạm vi nào”.
Ví dụ cùng là tool đọc Google Sheets, nhưng:
- người A chỉ đọc được sheet A
- người B chỉ đọc được sheet B
- admin đọc được tất cả
Tức là quyền không chỉ gắn với tool name, mà còn gắn với resource instance hoặc filter condition.
Đây là điểm phân biệt giữa RBAC sơ khai và RBAC đủ dùng ngoài đời.
Với Google Sheets, nên chặn kiểu nào cho đỡ nguy hiểm?
Bài Reddit dùng ví dụ rất đúng: mỗi người có thể liên quan tới một sheet khác nhau. Đây là trường hợp phổ biến và cũng là chỗ nhiều anh em dễ làm ẩu nhất.
Cách yếu là:
- agent cầm một credential đọc được mọi sheet
- prompt tự dặn chỉ lấy đúng sheet của user hiện tại
Cách mạnh hơn là:
- tool wrapper nhận
requester_id - policy table map
requester_id -> allowed_sheet_ids - wrapper chỉ cho đọc sheet nằm trong danh sách được phép
- nếu cần, trả về lỗi rõ ràng khi vượt quyền
Nếu muốn chặt hơn nữa, anh em có thể tách credential theo nhóm tài nguyên hoặc theo tenant thay vì dùng một credential toàn cục. Làm vậy công hơi cao hơn nhưng blast radius nhỏ hơn hẳn nếu có lỗi logic.
RBAC cho agent nên theo role hay theo user?
Câu trả lời thực tế là: bắt đầu bằng role, nhưng đừng chỉ dừng ở role.
Role-based đủ tốt khi:
- số nhóm người dùng không nhiều
- quyền truy cập khá đồng nhất trong từng nhóm
- hệ thống còn nhỏ
Ví dụ:
sales_repsupportmanageradmin
Cần thêm resource-level mapping khi:
- mỗi người dù cùng role nhưng phụ trách tập dữ liệu khác nhau
- dữ liệu chia theo khách hàng, vùng, team, tenant hoặc account owner
- cùng là
sales_repnhưng A không được xem lead của B
Khi đó RBAC thuần role-based chưa đủ. Anh em cần một lớp ABAC hoặc row/resource-level filtering nhẹ, ít nhất là:
- role quyết định loại hành động
- resource mapping quyết định phạm vi cụ thể
Mình nghĩ với bài toán trong Reddit, câu trả lời tốt nhất là role + resource scope chứ không chỉ role đơn thuần.
Những lỗi thiết kế rất dễ gặp khi làm multi-user agent
Từ góc nhìn vận hành, mình thấy có vài bẫy rất hay làm hệ RBAC trông có vẻ đúng nhưng thực ra vẫn hở.
1. Cho agent dùng credential quá rộng
Nếu credential phía sau đọc được hết, anh em đang đặt quá nhiều niềm tin vào lớp logic ở trên. Càng rộng quyền, hậu quả của một bug càng lớn.
2. Check quyền ở chat layer nhưng không check lại ở tool layer
Đây là lỗi phổ biến. UI hoặc middleware có thể đã chặn, nhưng tool trực tiếp vẫn gọi được nếu ai đó đi đường vòng hoặc nếu agent sinh ra tool call bất ngờ.
3. Không log quyết định phân quyền
Nếu sau này có tranh chấp hoặc lỗi lộ dữ liệu, anh em cần biết:
- ai gọi
- đã yêu cầu gì
- tool nào bị gọi
- policy nào cho phép hoặc từ chối
Không có audit log, rất khó mổ xẻ sự cố.
4. Không tách read và write
Nhiều người gom chung quyền đọc và sửa. Trong thực tế, write thường nên khắt khe hơn read rất nhiều.
5. Tin rằng session isolation là đủ cho data isolation
Tách thread, tách channel hay tách session là tốt cho context. Nhưng nó không tự động là bảo mật dữ liệu. Data isolation phải được chặn ở tool path và data path.
Nếu anh em muốn làm đúng ngay từ phiên bản đầu
Mình sẽ đi theo checklist này.
Bước 1: chuẩn hóa user identity từ Slack inbound
- luôn có requester id rõ ràng
- nếu được, map sang role nội bộ ngay từ đầu
Bước 2: tạo bảng policy đơn giản
- ai thuộc role nào
- role nào gọi được tool nào
- mỗi user hoặc role được đụng resource nào
Bước 3: bọc các tool nhạy cảm bằng guard wrapper
- Google Sheets
- CRM
- internal APIs
- database query
Bước 4: mọi tool nhạy cảm đều phải check quyền trước khi chạy
- không check ở prompt
- không check chỉ ở UI
- check ngay tại execution boundary
Bước 5: log mọi lần allow và deny
- để audit
- để debug
- để thấy policy nào đang quá chặt hoặc quá lỏng
Góc nhìn cuối: agent dùng chung chỉ an toàn khi “dốt quyền” hơn backend
Mình nghĩ đây là nguyên tắc đáng nhớ nhất.
Một multi-user OpenClaw an toàn không nên là hệ nơi model hiểu rất sâu về policy rồi tự cố làm đúng. Nó nên là hệ nơi model dù có muốn vượt quyền cũng không vượt được, vì backend, wrapper và resource scope đã khóa cửa trước rồi.
Tức là:
- prompt vẫn hữu ích để hướng dẫn hành vi
- session isolation vẫn hữu ích để giữ context sạch
- nhưng quyền thật phải do hạ tầng cưỡng chế
Đó mới là cách biến một agent nhiều người dùng từ đồ chơi thông minh thành hệ có thể chạm vào dữ liệu thật mà không quá liều.
Kết luận
Câu hỏi RBAC trên r/OpenClawUseCases đáng giá ở chỗ nó nhắc anh em một điều rất quan trọng: khi đưa OpenClaw vào Slack hoặc bất kỳ môi trường nhiều người dùng nào, đừng hỏi trước tiên “prompt nào để agent biết giữ quyền”, mà hãy hỏi “tool nào, API nào và resource nào phải bị chặn cứng ở đâu”.
Nếu mình phải tóm gọn thành một lời khuyên thực chiến, thì là thế này:
- truyền identity thật xuống tool layer
- giữ policy ngoài prompt
- enforce ở execution boundary
- scope tới từng resource nếu cần
- audit lại mọi quyết định allow/deny
Làm được vậy, anh em mới bắt đầu có một nền RBAC đủ nghiêm túc để dùng OpenClaw cho hệ nhiều người dùng ngoài đời thật.
Top comments (0)