Idea In 30 Seconds
RBAC (Role-Based Access Control) for an AI agent defines who can execute which actions through tools in runtime.
When you need it: when an agent works with multiple roles, multiple tenants, or has access to write actions in real systems.
Problem
Without RBAC, an agent is often launched with "wide" access: one role, many tools, minimal boundaries. In demos this looks convenient. In production it quickly becomes an incident source.
A single planning mistake by the agent can trigger an unnecessary action: wrong tool, wrong tenant, wrong access level. After that, it is hard to answer even a basic question: who got access and why. To prevent this from becoming an incident, access checks must live not in prompt but in policy layer before every tool call.
Analogy: it is like a universal pass card in a business center. While everything is calm, the difference is invisible. During a failure, that card opens too many doors.
Solution
The solution is to move access control into policy layer in runtime.
Each tool call is checked by user context (role, permissions, and tenant scope) before execution.
Start with a baseline rule: default deny and explicit allows only for required roles.
RBAC != Just Allowlist
Allowlist defines which tools exist in the system.
RBAC defines who can call them and when.
One without the other does not work:
- without RBAC, access boundaries between roles blur
- without allowlist, the tool set grows uncontrolled
Example:
- allowlist: tool
refund.createexists and is available in system - RBAC: only role
billing_managercan callrefund.createin its own tenant
Access Control Levels (RBAC layers)
These checks work together at every agent step.
| Layer | What it controls | Key mechanics | Why |
|---|---|---|---|
| Roles (role mapping) | Who executes the action | role assignment service account policy | Prevents "one role for all" |
| Permissions | What exactly is allowed for the role | action-based permissions default deny allowlist | Creates explicit boundaries for tools and actions |
| Tenant isolation (scope) | Which data space can be affected (tenant is an isolated client data boundary) | tenant_id check resource scoping | Prevents access to another tenant |
| Write-action control | Risky or irreversible actions | separate write permissions human approval | Reduces expensive failure risk |
How It Looks In Architecture
Policy layer (tool gateway) sits between runtime and tools and checks every call.
Every decision (allow, deny, approval_required) is recorded in audit log.
Flow: from request to decision
Every tool call passes through this flow before execution: runtime does not execute actions directly and delegates decision to policy layer.
Flow summary:
- Runtime forms tool request
- RBAC policy layer checks role and tenant scope
allow-> tool call executesdeny-> stop reason + audit log recordapproval_required-> stop reason + audit log record
Policy decisions
Every tool call ends with one of these decisions:
allowβ action is executeddenyβ action is blockedapproval_requiredβ confirmation is required
This is a centralized decision point through which all actions pass before execution. These decisions are used as stop reasons and logged in audit log.
Example
A support agent (role = support_agent) receives a refund request.
Tool refund.create is allowed only for role billing_manager in its own tenant.
Result:
support_agent->refund.create->deny("permission_denied")role mismatchortenant scope mismatch->deny("permission_denied")- event is written to audit log with denial reason
RBAC stops the mistake at execution level by checking access before each action.
In Code It Looks Like This
decision = rbac.check(user_context, tool, tenant_id, args)
if not decision.allowed:
audit.log(user_context, tool, tenant_id, decision.outcome, reason=decision.reason)
return deny(decision.reason)
if decision.requires_approval and not approval.ok():
audit.log(user_context, tool, tenant_id, "approval_required", reason="approval_required")
return stop("approval_required")
result = tool.execute(args)
audit.log(user_context, tool, tenant_id, decision.outcome, reason=decision.reason, result=result)
return result
How It Looks During Execution
Scenario 1: access denied (deny)
Request: user asks for refund
Runtime: tool call formed -> refund.create
Policy: role + tenant scope + permissions check
Decision: deny (permission_denied)
Audit: decision=deny, role=support_agent, action=refund.create, reason=permission_denied
Stop: action not executed
---
Scenario 2: access allowed (allow)
Request: same case for billing_manager in own tenant
Runtime: tool call formed -> refund.create
Policy: role + tenant scope + permissions check
Decision: allow
Tool: refund.create executed
Audit: decision=allow, role=billing_manager, action=refund.create, result=ok
Return: result returned to client
Common Mistakes
- one "service" role for all agents and users
- missing default-deny allowlist
- checking only role without tenant scope
- missing centralized policy layer
- same permissions for
readandwriteactions - RBAC logic only in UI or prompt
- missing audit trail: role, action, tenant, policy decision reason
As a result, the system looks controlled but access boundaries degrade over time.
Self-Check
Quick RBAC check before production launch:
Progress: 0/8
β Baseline governance controls are missing
Before production, you need at least access control, limits, audit logs, and an emergency stop.
FAQ
Q: How should we handle tools that call GitHub, Jira, or other external APIs?
A: Do not give agent one shared key for everything. Prefer user-scoped credentials, OAuth tokens, or separate service-account policy with explicit boundaries.
Q: What is the difference between role and tenant scope?
A: Role defines what can be done. Tenant scope defines where it can be done.
Q: How do we add a new tool to RBAC safely?
A: Add it through explicit permission model: default deny, separate read/write permissions, and tenant scope checks.
Q: What should be implemented first: RBAC or approval?
A: Start with RBAC using default deny and tenant scope. Then add approval for risky write actions.
Q: Is RBAC alone enough for production?
A: No. You also need execution limits, budgets, audit logs, and kill switch.
Where RBAC Fits In The Whole System
RBAC is one of Agent Governance layers.
Together with budgets, limits, approval, and audit, it forms a unified execution-control system.
Related Pages
Next on this topic:
- Agent Governance Overview β overall production control model for agents.
- Allowlist vs Blocklist β why default-deny scales better.
- Human Approval β how to add manual confirmation for risky actions.
- Audit Logs For Agents β how to reconstruct decision chains in incidents.
- Kill Switch β how to emergency-stop an agent without release.