AI Platform Role Hierarchy: Multi-Tenant RBAC for Enterprise

TL;DR — AI platform role hierarchy implements multi-tenant RBAC for AI SaaS. WorkOS: "In 2025, SaaS buyers walk straight through the front door, asking about RBAC before they even try the demo. Mature, tenant-aware authorization isn't a luxury anymore — it's a checkpoint on the road to enterprise deals, SOC2 audits, and frictionless user experiences." Three-tier hierarchy: Platform Admin (all tenants), Tenant Admin (their org), User (scoped access). Scalekit covers "channel-owned auth, explicit scope translation, org-level isolation" for multi-tenant AI agents. WorkOS 2026: "Hierarchical resource model: Define resource types (organizations, workspaces, projects, apps) with parent-child relationships, enabling automatic permission inheritance." EnterpriseReady: roles bundle permissions as resource:action pairs. AI-specific: Agent Operator, Knowledge Curator, Agent Identity (service accounts). Integrate with multi-tenant architecture, zero-trust, tenant suspension, and audit logging.

WorkOS notes the shift: "In 2025, SaaS buyers walk straight through the front door, asking about RBAC before they even try the demo. Mature, tenant-aware authorization isn't a luxury anymore for B2B SaaS. It's a checkpoint on the road to enterprise deals, SOC2 audits, and frictionless user experiences."

Scalekit describes the AI-specific challenge: "Multi-tenant AI agents are becoming standard infrastructure for B2B SaaS platforms, triage agents, workflow agents, and notification agents, all of which act continuously across dozens of customer orgs."

Role Hierarchy Architecture

flowchart TD subgraph Platform["Platform Tier"] PA["Platform Admin
Full platform access"] PS["Platform Support
Read-only all tenants"] end subgraph Tenant["Tenant Tier"] TA["Tenant Admin
Manage org users, agents, billing"] TE["Tenant Editor
Create/edit agents, knowledge"] TV["Tenant Viewer
Read-only access"] TB["Billing Admin
Manage invoices, usage"] end subgraph User["User Tier"] AO["Agent Operator
Start/stop/monitor agents"] KC["Knowledge Curator
Manage knowledge content"] AD["API Developer
Manage API keys, webhooks"] end subgraph Agent["Agent Identity"] SA["Service Account
(agent credentials)"] AR["Agent Role
(scoped permissions)"] end subgraph Resources["Hierarchical Resources"] Org["Organization"] WS["Workspace"] Proj["Project"] Agt["Agent"] KB["Knowledge Base"] end PA --> TA PS --> TA TA --> TE TA --> TV TA --> TB TE --> AO TE --> KC TE --> AD Org --> WS WS --> Proj Proj --> Agt Proj --> KB SA --> AR AR --> Agt

Role Permission Matrix

Role Manage Users Manage Agents Knowledge Base Billing View Analytics API Keys Audit Logs
Platform Admin All tenants All tenants All tenants All All All All
Platform Support Read-only Read-only Read-only No All No Read-only
Tenant Admin Own tenant Own tenant Own tenant Own Own Own Own
Tenant Editor No Create/Edit Create/Edit No Own No No
Tenant Viewer No Read-only Read-only No No No No
Billing Admin No No No Own Own No No
Agent Operator No Start/Stop No No Agent metrics No No
Knowledge Curator No No Edit/Approve No No No No
API Developer No No No No No Manage No

Hierarchical Resource Scoping

Level Resource Type Parent Permissions Inherit From
1 Organization None Platform Admin grants
2 Workspace Organization Organization permissions
3 Project Workspace Workspace permissions
4 Agent Project Project permissions
4 Knowledge Base Project Project permissions
5 Document Knowledge Base KB permissions

Implementation

from enum import Enum
from dataclasses import dataclass

class Role(Enum):
    PLATFORM_ADMIN = "platform_admin"
    PLATFORM_SUPPORT = "platform_support"
    TENANT_ADMIN = "tenant_admin"
    TENANT_EDITOR = "tenant_editor"
    TENANT_VIEWER = "tenant_viewer"
    BILLING_ADMIN = "billing_admin"
    AGENT_OPERATOR = "agent_operator"
    KNOWLEDGE_CURATOR = "knowledge_curator"
    API_DEVELOPER = "api_developer"

class Permission(Enum):
    # User management
    USERS_READ = "users:read"
    USERS_WRITE = "users:write"
    USERS_DELETE = "users:delete"
    # Agent management
    AGENTS_READ = "agents:read"
    AGENTS_WRITE = "agents:write"
    AGENTS_DELETE = "agents:delete"
    AGENTS_OPERATE = "agents:operate"
    # Knowledge base
    KNOWLEDGE_READ = "knowledge:read"
    KNOWLEDGE_WRITE = "knowledge:write"
    KNOWLEDGE_DELETE = "knowledge:delete"
    KNOWLEDGE_APPROVE = "knowledge:approve"
    # Billing
    BILLING_READ = "billing:read"
    BILLING_WRITE = "billing:write"
    # Analytics
    ANALYTICS_READ = "analytics:read"
    # API
    API_KEYS_MANAGE = "api_keys:manage"
    # Audit
    AUDIT_READ = "audit:read"

ROLE_PERMISSIONS = {
    Role.PLATFORM_ADMIN: set(Permission),  # All permissions
    Role.PLATFORM_SUPPORT: {
        Permission.USERS_READ, Permission.AGENTS_READ,
        Permission.KNOWLEDGE_READ, Permission.ANALYTICS_READ,
        Permission.AUDIT_READ,
    },
    Role.TENANT_ADMIN: {
        Permission.USERS_READ, Permission.USERS_WRITE, Permission.USERS_DELETE,
        Permission.AGENTS_READ, Permission.AGENTS_WRITE, Permission.AGENTS_DELETE,
        Permission.KNOWLEDGE_READ, Permission.KNOWLEDGE_WRITE, Permission.KNOWLEDGE_DELETE,
        Permission.BILLING_READ, Permission.BILLING_WRITE,
        Permission.ANALYTICS_READ, Permission.API_KEYS_MANAGE,
        Permission.AUDIT_READ,
    },
    Role.TENANT_EDITOR: {
        Permission.AGENTS_READ, Permission.AGENTS_WRITE,
        Permission.KNOWLEDGE_READ, Permission.KNOWLEDGE_WRITE,
        Permission.ANALYTICS_READ,
    },
    Role.TENANT_VIEWER: {
        Permission.AGENTS_READ, Permission.KNOWLEDGE_READ,
    },
    Role.BILLING_ADMIN: {
        Permission.BILLING_READ, Permission.BILLING_WRITE,
        Permission.ANALYTICS_READ,
    },
    Role.AGENT_OPERATOR: {
        Permission.AGENTS_READ, Permission.AGENTS_OPERATE,
        Permission.ANALYTICS_READ,
    },
    Role.KNOWLEDGE_CURATOR: {
        Permission.KNOWLEDGE_READ, Permission.KNOWLEDGE_WRITE,
        Permission.KNOWLEDGE_APPROVE,
    },
    Role.API_DEVELOPER: {
        Permission.API_KEYS_MANAGE,
    },
}


class RBACEngine:
    """Multi-tenant RBAC with hierarchical resource scoping."""

    def __init__(self, db, redis):
        self.db = db
        self.redis = redis

    async def check_permission(
        self,
        user_id: str,
        tenant_id: str,
        permission: Permission,
        resource_type: str = None,
        resource_id: str = None,
    ) -> bool:
        """Check if user has permission within tenant context."""

        # 1. Get user's role in this tenant
        user_role = await self._get_user_role(user_id, tenant_id)
        if not user_role:
            return False  # User not in this tenant

        # 2. Check if role has the permission
        role_perms = ROLE_PERMISSIONS.get(Role(user_role), set())
        if permission not in role_perms:
            return False

        # 3. If resource-scoped, check hierarchical inheritance
        if resource_type and resource_id:
            has_access = await self._check_resource_scope(
                user_id, tenant_id, permission, resource_type, resource_id
            )
            if not has_access:
                return False

        return True

    async def _check_resource_scope(
        self, user_id, tenant_id, permission, resource_type, resource_id
    ) -> bool:
        """Check hierarchical resource scoping with permission inheritance."""

        # Check direct grant on this resource
        direct = await self.db.find_one("resource_grants", {
            "user_id": user_id,
            "tenant_id": tenant_id,
            "resource_id": resource_id,
            "permission": permission.value,
        })
        if direct:
            return direct["allowed"]

        # Traverse up the hierarchy for inherited permissions
        current_id = resource_id
        current_type = resource_type

        while current_id:
            parent = await self.db.find_one("resources", {
                "id": current_id,
                "tenant_id": tenant_id,
            })
            if not parent:
                break

            # Check grant on parent
            parent_grant = await self.db.find_one("resource_grants", {
                "user_id": user_id,
                "tenant_id": tenant_id,
                "resource_id": parent["parent_id"],
                "permission": permission.value,
            })

            if parent_grant:
                return parent_grant["allowed"]

            current_id = parent.get("parent_id")

        # No explicit grant found — default deny
        return False

    async def assign_role(self, user_id: str, tenant_id: str, role: Role,
                          assigned_by: str):
        """Assign a role to a user within a tenant."""
        await self.db.insert("user_roles", {
            "user_id": user_id,
            "tenant_id": tenant_id,
            "role": role.value,
            "assigned_by": assigned_by,
            "assigned_at": datetime.utcnow(),
        })

        await self.audit.log(
            tenant_id=tenant_id,
            user_id=assigned_by,
            action="role_assigned",
            details={"target_user": user_id, "role": role.value},
        )

    async def create_agent_identity(
        self, tenant_id: str, agent_name: str, role: Role, created_by: str
    ) -> dict:
        """Create a service account identity for an AI agent."""
        agent_id = str(uuid4())
        api_key = self._generate_api_key()

        await self.db.insert("agent_identities", {
            "agent_id": agent_id,
            "tenant_id": tenant_id,
            "name": agent_name,
            "role": role.value,
            "api_key_hash": self._hash_key(api_key),
            "created_by": created_by,
            "active": True,
            "created_at": datetime.utcnow(),
        })

        await self.audit.log(
            tenant_id=tenant_id,
            user_id=created_by,
            action="agent_identity_created",
            details={"agent_id": agent_id, "name": agent_name, "role": role.value},
        )

        return {"agent_id": agent_id, "api_key": api_key}  # Return key once

AI Platform Role Hierarchy Checklist

  • [ ] Define three-tier hierarchy: Platform Admin, Tenant Admin, User
  • [ ] Define AI-specific roles: Agent Operator, Knowledge Curator, API Developer
  • [ ] Define permissions as resource:action pairs (agents:read, knowledge:write)
  • [ ] Map roles to permission bundles (ROLE_PERMISSIONS mapping)
  • [ ] Implement tenant-scoped access: every permission check includes tenant_id
  • [ ] Use JWT with tenant_id and role claims
  • [ ] Verify tenant_id at every API layer — never trust client-side claims
  • [ ] Implement hierarchical resource scoping (Org → Workspace → Project → Agent)
  • [ ] Store resource hierarchy in database (resource_id, parent_id, type)
  • [ ] Implement permission inheritance: parent grants cascade to children
  • [ ] Allow child-level override (deny inheritance for specific children)
  • [ ] Use recursive CTEs in PostgreSQL for hierarchy resolution
  • [ ] Implement role assignment with audit logging
  • [ ] Support custom roles per tenant (tenant admin creates role bundles)
  • [ ] Set up SSO integration (SAML, OIDC) for enterprise identity mapping
  • [ ] Map enterprise directory groups to platform roles
  • [ ] Create agent identities as service accounts (not human credentials)
  • [ ] Assign scoped roles to agents (Agent Operator, not Tenant Admin)
  • [ ] Log every agent action with agent_id (separate from user_id)
  • [ ] Implement agent revocation: tenant admin can revoke agent access
  • [ ] Require human approval for high-risk agent actions (role-gated)
  • [ ] Implement Platform Support role (read-only across tenants for support)
  • [ ] Implement Billing Admin role (separate from Tenant Admin)
  • [ ] Enforce least-privilege: default deny, explicit allow
  • [ ] Implement permission cache (Redis) for fast checks
  • [ ] Invalidate permission cache on role changes
  • [ ] Set up role-based feature flags (features visible by role)
  • [ ] Implement model access restrictions per role (Viewer = mini models only)
  • [ ] Integrate with multi-tenant architecture isolation
  • [ ] Apply zero-trust architecture principles
  • [ ] Set up audit logging for all permission changes
  • [ ] Apply OWASP LLM Top 10 access control (ASI03)
  • [ ] Integrate with tenant suspension for access revocation
  • [ ] Set up platform monitoring for access control health
  • [ ] Consider self-hosted AI for identity sovereignty
  • [ ] Test cross-tenant access: verify Tenant A admin cannot access Tenant B
  • [ ] Test permission inheritance: verify parent grant cascades to children
  • [ ] Test agent identity: verify agents use service accounts, not user creds
  • [ ] Document role hierarchy and permissions for compliance audits
  • [ ] Quarterly access review: audit role assignments, remove stale access
  • [ ] Consider AI incident response for access control breaches

FAQ

What is AI platform role hierarchy?

AI platform role hierarchy is a multi-tier RBAC system for AI SaaS platforms. The hierarchy has three levels: (1) Platform Admin — manages the entire platform (all tenants, models, infrastructure, billing). (2) Tenant Admin — manages their organization (users, agents, knowledge bases, billing within their tenant). (3) User — uses AI features within their assigned permissions. Each tier inherits permissions from the level above. Within each tenant, sub-roles can be defined: Editor (create/edit agents and knowledge), Viewer (read-only access), and custom roles. The hierarchy ensures: platform staff can manage infrastructure, tenant admins can self-manage their org, and users only access what they're authorized for. AI-specific roles include Agent Operator (manage running agents) and Knowledge Curator (manage knowledge base content).

How does RBAC work in multi-tenant AI platforms?

RBAC in multi-tenant AI platforms combines role-based permissions with tenant-scoped resource access. Every permission check evaluates two dimensions: (1) Role — what actions can this user perform (read, write, delete, admin). (2) Tenant scope — which tenant's resources can they access. A Tenant Admin for Tenant A has full admin rights but ONLY for Tenant A's resources — they cannot see Tenant B's data. Implementation: JWT carries tenant_id and role, every API request verifies both, database queries filter by tenant_id (RLS), and vector searches include tenant_id filter. Permissions are defined as resource:action pairs (e.g., agent:read, knowledge:write, billing:admin). Roles bundle permissions. Users are assigned roles within a tenant context. SSO (SAML, OIDC) maps enterprise identity to platform roles.

What roles should an AI SaaS platform define?

Essential roles for AI SaaS: (1) Platform Admin — full platform access, manage all tenants, models, infrastructure. (2) Platform Support — read-only access to all tenants for support. (3) Tenant Admin — manage users, agents, knowledge, billing within their tenant. (4) Tenant Editor — create and modify agents, knowledge bases, workflows. (5) Tenant Viewer — read-only access to agents and knowledge. (6) Agent Operator — start/stop/monitor running agents. (7) Knowledge Curator — manage knowledge base content, approve wiki edits. (8) Billing Admin — view invoices, manage payment methods, see usage. (9) API Developer — manage API keys, webhooks, integrations. (10) Custom roles — tenant admin can create custom roles with specific permission bundles.

How do you implement hierarchical resource scoping?

Hierarchical resource scoping defines parent-child relationships between resources: Organization → Workspace → Project → Agent → Knowledge Base. Permissions inherit downward: a user with 'read' on a Workspace automatically has 'read' on all Projects and Agents within that Workspace. Implementation: (1) Define resource types with parent-child relationships. (2) Store resource hierarchy in database (resource_id, parent_id, type). (3) On permission check, traverse up the hierarchy to find the highest applicable permission. (4) Child permissions can override parent (deny inheritance for specific children). (5) Use recursive CTEs in PostgreSQL to resolve hierarchy efficiently. This pattern enables: 'User has Editor access to Engineering workspace' → automatically has Editor access to all projects and agents in Engineering, without explicit per-resource grants.

How do AI agents get their own identity and permissions?

AI agents need their own identity separate from human users. Implementation: (1) Agent identity — each agent gets a service account with its own credentials (API key or OAuth token). (2) Agent roles — agents are assigned roles like 'Agent Operator' with scoped permissions (can call LLM, can search knowledge base, cannot delete resources). (3) Agent scope — agents are scoped to a specific tenant and workspace, preventing cross-tenant access. (4) Agent audit — every agent action is logged with agent_id, not just tenant_id. (5) Agent approval — high-risk agent actions require human approval from a user with appropriate role. (6) Agent revocation — tenant admin can revoke an agent's access at any time. Microsoft Entra now offers 'Agent Registry Administrator' role for managing agent identities. Agents should never use human user credentials — always their own service account.


Want a self-hosted AI company brain that does all of this out of the box?
Book a demo →