Skip to content

AI Chat Permissions Integration Guide

This guide explains how to integrate your existing role-based permission system with the AI chat tool to restrict access to specific AI actions and tools.

Overview of Your Current Permission System

Your permission system follows a 4-level hierarchy:

User → Role → Action → Permission
           (multiple permissions grouped into one action)

Key Components:

Component Location Purpose
Permission seed/permissions.json Individual API permission (e.g., "add_role", "edit_user")
Action seed/actions.json Groups 5-15 permissions into a workflow (e.g., "Create Role" action includes nav_role + add_role + fetch_role...)
Category seed/category.json Organizes actions by business domain (e.g., "Manage Roles" groups 9 actions)
Enforcement controller/auth.py @permission_required("permission_name") decorator on routes

How Permission Checking Works

At request time (check_permissions() in auth.py:1802):

  1. User makes request → RequestMiddleware authenticates user
  2. If endpoint has @permission_required("permission_name") dependency
  3. Decorator calls check_permissions() which:
  4. Gets user's roles via UserRole table
  5. For each role, gets all assigned actions via RoleAction
  6. For each action, gets all permissions via ActionPermission
  7. Extracts permission api field into a set
  8. Checks if required permission is in user's permission set
  9. Raises HTTP 403 if permission missing

Special case for agents: Permissions can come from either: - AgentCategoryRole (role-based) - AgentCategoryTransactions (direct transaction permissions)


Step 1: Add AI Permissions to Seed Data

File: backend/seed/permissions.json

Add these AI-specific permissions:

{
    "api": "access_ai_chat",
    "title": "Access AI Chat",
    "description": "Permission to access the AI chat assistant"
},
{
    "api": "use_ai_analysis",
    "title": "Use AI Analysis Tool",
    "description": "Permission to use AI analysis features (loan, customer, transaction analysis)"
},
{
    "api": "use_ai_loan_tool",
    "title": "Use AI Loan Analysis",
    "description": "Permission to use AI loan analysis and scoring tools"
},
{
    "api": "use_ai_fraud_detection",
    "title": "Use AI Fraud Detection",
    "description": "Permission to use AI fraud detection tools"
},
{
    "api": "use_ai_customer_insights",
    "title": "Use AI Customer Insights",
    "description": "Permission to use AI customer profiling and insights tools"
},
{
    "api": "use_ai_report_generation",
    "title": "Use AI Report Generation",
    "description": "Permission to use AI-powered report generation"
},
{
    "api": "use_ai_advanced_tools",
    "title": "Use Advanced AI Tools",
    "description": "Permission to use advanced AI tools (data transformation, complex queries)"
},
{
    "api": "manage_ai_tools",
    "title": "Manage AI Tools",
    "description": "Permission to configure and manage AI tool access"
}

Step 2: Create AI Actions Grouping Permissions

File: backend/seed/actions.json

Add these AI actions. Each action groups permissions for a specific workflow:

{
    "name": "Access AI Chat",
    "description": "Basic access to AI chat interface",
    "permissions": [
        "access_ai_chat",
        "fetch_conversation"
    ]
},
{
    "name": "Use Loan Analysis Tool",
    "description": "Use AI to analyze loans and generate scores",
    "permissions": [
        "access_ai_chat",
        "use_ai_analysis",
        "use_ai_loan_tool",
        "fetch_loan",
        "fetch_loan_product"
    ]
},
{
    "name": "Use Fraud Detection Tool",
    "description": "Use AI fraud detection on transactions and customers",
    "permissions": [
        "access_ai_chat",
        "use_ai_analysis",
        "use_ai_fraud_detection",
        "fetch_transaction",
        "fetch_customer"
    ]
},
{
    "name": "Use Customer Insights Tool",
    "description": "Use AI for customer profiling and insights",
    "permissions": [
        "access_ai_chat",
        "use_ai_analysis",
        "use_ai_customer_insights",
        "fetch_customer",
        "fetch_account"
    ]
},
{
    "name": "Use AI Report Generation",
    "description": "Generate AI-powered reports and exports",
    "permissions": [
        "access_ai_chat",
        "use_ai_analysis",
        "use_ai_report_generation",
        "fetch_report"
    ]
},
{
    "name": "Use Advanced AI Tools",
    "description": "Access advanced AI features for complex queries and data transformation",
    "permissions": [
        "access_ai_chat",
        "use_ai_analysis",
        "use_ai_advanced_tools",
        "fetch_account",
        "fetch_transaction",
        "fetch_customer"
    ]
},
{
    "name": "Manage AI Tools",
    "description": "Configure AI tool availability and settings",
    "permissions": [
        "manage_ai_tools",
        "fetch_permission",
        "fetch_action"
    ]
}

Step 3: Create AI Management Category

File: backend/seed/category.json

Add this new category:

{
    "name": "Manage AI Assistant",
    "description": "Permissions for using and managing the AI assistant",
    "actions": [
        "Access AI Chat",
        "Use Loan Analysis Tool",
        "Use Fraud Detection Tool",
        "Use Customer Insights Tool",
        "Use AI Report Generation",
        "Use Advanced AI Tools",
        "Manage AI Tools"
    ]
}

Step 4: Add Permission Checking to WebSocket Route

File: backend/routers/socket.py

Currently, the WebSocket route accepts all authenticated users. Add permission checking for AI chat:

# Add import at top
from controller.auth import check_permissions

# In websocket handler, after JWT validation (around line 156):
@r.websocket("/ws")
async def websocket(
    websocket: WebSocket,
    Authorize: AuthJWT = Depends(),
    db: AsyncSession = Depends(get_db),
):
    # ... existing code ...

    try:
        # Validate JWT
        Authorize.jwt_required("websocket", token=token)
        # ... get current_user ...

        await websocket.accept()

        # ✅ ADD THIS: Check if user has permission to use AI chat
        try:
            can_access_ai = check_permissions(
                "access_ai_chat",
                db=db,
                current_user=current_user,
                throw=False  # Returns True/False instead of raising
            )
            if not can_access_ai:
                error_msg = {
                    "event_type": "permission_error",
                    "data": {
                        "error": "You do not have permission to access the AI assistant"
                    }
                }
                await websocket.send_json(error_msg)
                await websocket.close(code=1008, reason="Permission denied")
                return
        except Exception as e:
            logger.error(f"Permission check failed: {e}")
            await websocket.close(code=1008, reason="Permission check failed")
            return

        # ... rest of websocket handler ...

Step 5: Add Tool-Level Permission Checking

File: backend/controller/ai_agent.py

In the chat_with_tools_streaming() and chat_with_tools() functions, check permissions before allowing tool use:

# Add import
from controller.auth import check_permissions

# In chat_with_tools_streaming(), before executing a tool (around tool selection logic):
async def chat_with_tools_streaming(db, user_msg, current_user, token_callback, conversation_id=None):
    """
    Stream AI responses with tool execution.
    Checks permissions before allowing each tool.
    """

    # ... existing code to set up tools ...

    # Tool permission mapping
    TOOL_PERMISSIONS = {
        "analyze_loan": "use_ai_loan_tool",
        "detect_fraud": "use_ai_fraud_detection",
        "customer_insights": "use_ai_customer_insights",
        "generate_report": "use_ai_report_generation",
        "advanced_data_query": "use_ai_advanced_tools",
    }

    # When OpenAI decides to call a tool, check permission first:
    if tool_use_event:
        tool_name = tool_use_event.get("tool_name")
        required_permission = TOOL_PERMISSIONS.get(tool_name)

        if required_permission:
            has_permission = check_permissions(
                required_permission,
                db=db,
                current_user=current_user,
                throw=False
            )

            if not has_permission:
                # Send permission denied event
                await token_callback(
                    "chat_tool_error",
                    {
                        "tool_name": tool_name,
                        "error": f"Permission denied: {required_permission}",
                        "conversation_id": conversation_id
                    }
                )
                continue  # Skip this tool, continue with response

        # Permission check passed - execute tool
        tool_result = execute_tool(tool_name, tool_input)
        # ... rest of tool execution ...

Step 6: Add Permission Information to Frontend

File: ui/src/modules/ai/redux/reducer.ts

Update Redux state to track user permissions:

export interface AIState {
    // ... existing fields ...

    // User permissions for AI tools
    userPermissions: {
        canAccessChat: boolean;
        canUseAnalysis: boolean;
        canUseLoanTool: boolean;
        canUseFraudDetection: boolean;
        canUseCustomerInsights: boolean;
        canUseReports: boolean;
        canUseAdvancedTools: boolean;
    };
}

File: ui/src/modules/ai/components/chat_window.tsx

Disable unavailable tools in the UI based on permissions:

// Import user permissions from Redux
const { userPermissions } = useSelector((state: RootState) => state.aiState);

// Show/hide tools based on permissions
const availableTools = [
    userPermissions?.canUseLoanTool && { id: 'loan_analysis', name: 'Loan Analysis' },
    userPermissions?.canUseFraudDetection && { id: 'fraud_detection', name: 'Fraud Detection' },
    userPermissions?.canUseCustomerInsights && { id: 'customer_insights', name: 'Customer Insights' },
    // ... other tools ...
].filter(Boolean);

// Disable input if user can't access chat
{!userPermissions?.canAccessChat && (
    <div className="p-4 text-center text-red-600">
        You don't have permission to access the AI assistant
    </div>
)}

Permission Hierarchy Example

Here's how a typical "Agent Supervisor" role would be set up:

Role: Agent Supervisor
├─ Action: Access AI Chat
│  └─ Permissions: access_ai_chat, fetch_conversation
├─ Action: Use Loan Analysis Tool
│  └─ Permissions: access_ai_chat, use_ai_analysis, use_ai_loan_tool, ...
├─ Action: Use Fraud Detection Tool
│  └─ Permissions: access_ai_chat, use_ai_analysis, use_ai_fraud_detection, ...
└─ Action: Use Customer Insights Tool
   └─ Permissions: access_ai_chat, use_ai_analysis, use_ai_customer_insights, ...

# Result: Agent Supervisor can use these AI tools

A "Customer Service Agent" role might only have:

Role: Customer Service Agent
├─ Action: Access AI Chat
│  └─ Permissions: access_ai_chat, fetch_conversation
└─ Action: Use Customer Insights Tool
   └─ Permissions: access_ai_chat, use_ai_analysis, use_ai_customer_insights, ...

# Result: Can only access chat and customer insights, no loan or fraud tools

Implementation Checklist

  • [ ] Backend Seed Data: Add permissions, actions, and category to seed files
  • [ ] Run Seed: Execute backend/seed/4_process_permissions_and_actions.sql to update database
  • [ ] WebSocket Route: Add check_permissions("access_ai_chat") after JWT validation
  • [ ] AI Agent Controller: Add tool-level permission checks in chat_with_tools_streaming()
  • [ ] Frontend Redux: Add userPermissions state to AIState
  • [ ] Frontend UI: Disable/hide tools based on user permissions
  • [ ] Test: Assign permissions to test roles and verify access is granted/denied
  • [ ] Audit: Add logging of AI tool access to audit trail

Security Best Practices

  1. Always check permissions at the backend - Frontend checks are for UX only
  2. Check at entry point - Verify permissions at WebSocket connection and route entry
  3. Check at tool execution - Verify permissions again before executing expensive operations
  4. Use throw=False for graceful handling instead of raising exceptions
  5. Log all permission checks for audit trail
  6. Superuser bypass - Your system already implements superuser bypass (is_superuser=True)
  7. Default deny - Never grant permissions unless explicitly set in a role

How to Test

1. Create a test role in the UI: - Go to Manage Roles → Create Role - Assign "Access AI Chat" and "Use Loan Analysis Tool" actions - Assign this role to a test user

2. Login as the test user and verify: - AI chat opens successfully ✓ - Loan analysis tool is available ✓ - Fraud detection tool is grayed out/unavailable ✓

3. Test permission denial: - Try accessing chat with user without "access_ai_chat" permission - Should see error message and chat window should not open - Check server logs for permission denial event

4. Test superuser: - Login as superuser - All AI tools should be available regardless of roles


  • WebSocket endpoint: /ws (line 116 in socket.py)
  • Permission check function: check_permissions() (line 1802 in auth.py)
  • Permission decorator: @permission_required() (line 1919 in auth.py)
  • AI chat functions: chat_with_tools() and chat_with_tools_streaming() (ai_agent.py)