Agentic Architecture Pattern: Role Based

Written by

in


    """
Pattern 40: Role-Based Pattern

Agents assigned specific roles with defined responsibilities and permissions.
Roles determine what tasks agents can perform and what resources they can access.
"""

from typing import Dict, Any, List, Optional, Set
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI


@dataclass
class Permission:
    """Permission granted to a role."""
    permission_id: str
    name: str
    resource: str
    actions: List[str]  # e.g., ["read", "write", "execute"]


@dataclass
class Role:
    """Role with responsibilities and permissions."""
    role_id: str
    name: str
    description: str
    responsibilities: List[str]
    permissions: List[Permission] = field(default_factory=list)
    required_skills: List[str] = field(default_factory=list)


@dataclass
class RoleAssignment:
    """Assignment of role to agent."""
    agent_name: str
    role: Role
    assigned_at: datetime = field(default_factory=datetime.now)
    active: bool = True


class RoleBasedAgent:
    """Agent with role-based capabilities."""
    
    def __init__(self, name: str, skills: List[str], model_name: str = "gpt-4"):
        self.name = name
        self.skills = skills
        self.roles: List[Role] = []
        self.llm = ChatOpenAI(model=model_name, temperature=0.7)
    
    def assign_role(self, role: Role) -> bool:
        """Assign role to agent if qualified."""
        # Check if agent has required skills
        has_skills = all(skill in self.skills for skill in role.required_skills)
        
        if has_skills:
            self.roles.append(role)
            return True
        return False
    
    def has_permission(self, resource: str, action: str) -> bool:
        """Check if agent has permission for action on resource."""
        for role in self.roles:
            for perm in role.permissions:
                if perm.resource == resource and action in perm.actions:
                    return True
        return False
    
    def perform_task(self, task: str, resource: str, action: str) -> Dict[str, Any]:
        """Perform task if agent has permission."""
        if not self.has_permission(resource, action):
            return {
                "success": False,
                "error": f"Permission denied: {action} on {resource}",
                "agent": self.name
            }
        
        # Find applicable role
        applicable_role = None
        for role in self.roles:
            for perm in role.permissions:
                if perm.resource == resource and action in perm.actions:
                    applicable_role = role
                    break
        
        if not applicable_role:
            return {"success": False, "error": "No applicable role"}
        
        # Execute task with role context
        prompt = ChatPromptTemplate.from_messages([
            ("system", f"You are {self.name} acting in the role of {applicable_role.name}. "
                      f"Your responsibilities: {', '.join(applicable_role.responsibilities)}"),
            ("human", f"Task: {task}\n"
                     f"Action: {action} on {resource}\n\n"
                     f"Execute this task (brief description of what you do).")
        ])
        
        chain = prompt | self.llm
        response = chain.invoke({})
        
        return {
            "success": True,
            "agent": self.name,
            "role": applicable_role.name,
            "task": task,
            "result": str(response.content)[:200]
        }


class RoleBasedPattern:
    """
    Role-Based Pattern - Role-based access control and task assignment.
    
    Agents are assigned roles that define their responsibilities and permissions.
    Tasks are performed based on role capabilities and access rights.
    """
    
    def __init__(self):
        self.roles: Dict[str, Role] = {}
        self.agents: Dict[str, RoleBasedAgent] = {}
        self.role_assignments: List[RoleAssignment] = []
    
    def define_role(self, role: Role):
        """Define a role in the system."""
        self.roles[role.role_id] = role
    
    def register_agent(self, agent: RoleBasedAgent):
        """Register agent in the system."""
        self.agents[agent.name] = agent
    
    def assign_role_to_agent(self, agent_name: str, role_id: str) -> bool:
        """Assign role to agent."""
        if agent_name not in self.agents or role_id not in self.roles:
            return False
        
        agent = self.agents[agent_name]
        role = self.roles[role_id]
        
        success = agent.assign_role(role)
        
        if success:
            assignment = RoleAssignment(agent_name=agent_name, role=role)
            self.role_assignments.append(assignment)
            print(f"   ✓ Assigned {role.name} to {agent_name}")
            return True
        else:
            print(f"   ✗ {agent_name} not qualified for {role.name}")
            return False
    
    def execute_task(self, agent_name: str, task: str, resource: str, action: str) -> Dict[str, Any]:
        """Execute task through agent with role-based permissions."""
        if agent_name not in self.agents:
            return {"success": False, "error": "Agent not found"}
        
        agent = self.agents[agent_name]
        result = agent.perform_task(task, resource, action)
        
        if result["success"]:
            print(f"   ✓ {agent_name} ({result['role']}): {task[:50]}...")
        else:
            print(f"   ✗ {agent_name}: {result['error']}")
        
        return result
    
    def get_role_matrix(self) -> Dict[str, List[str]]:
        """Get matrix of roles assigned to each agent."""
        matrix = {}
        for agent_name, agent in self.agents.items():
            matrix[agent_name] = [role.name for role in agent.roles]
        return matrix
    
    def run(self, scenario: str) -> Dict[str, Any]:
        """Execute role-based pattern."""
        return {
            "pattern": "RoleBased",
            "total_roles": len(self.roles),
            "total_agents": len(self.agents),
            "total_assignments": len(self.role_assignments),
            "active_assignments": sum(1 for a in self.role_assignments if a.active),
            "scenario": scenario
        }


# Example usage
if __name__ == "__main__":
    print("=== Role-Based Pattern Demo ===\n")
    
    # Create pattern
    pattern = RoleBasedPattern()
    
    # Define roles with permissions
    print("1. Defining roles...")
    
    admin_role = Role(
        role_id="admin",
        name="System Administrator",
        description="Full system access and management",
        responsibilities=["Manage users", "Configure system", "Monitor security"],
        permissions=[
            Permission("p1", "full_access", "system", ["read", "write", "execute", "delete"]),
            Permission("p2", "user_mgmt", "users", ["read", "write", "delete"])
        ],
        required_skills=["administration", "security"]
    )
    
    developer_role = Role(
        role_id="developer",
        name="Software Developer",
        description="Develop and maintain code",
        responsibilities=["Write code", "Fix bugs", "Review code"],
        permissions=[
            Permission("p3", "code_access", "codebase", ["read", "write"]),
            Permission("p4", "deploy_staging", "staging", ["read", "execute"])
        ],
        required_skills=["programming", "git"]
    )
    
    analyst_role = Role(
        role_id="analyst",
        name="Data Analyst",
        description="Analyze data and generate reports",
        responsibilities=["Analyze data", "Generate reports", "Create visualizations"],
        permissions=[
            Permission("p5", "data_read", "database", ["read"]),
            Permission("p6", "report_create", "reports", ["read", "write"])
        ],
        required_skills=["data_analysis", "SQL"]
    )
    
    for role in [admin_role, developer_role, analyst_role]:
        pattern.define_role(role)
    
    # Register agents
    print("\n2. Registering agents...")
    
    alice = RoleBasedAgent("Alice", ["administration", "security", "programming"])
    bob = RoleBasedAgent("Bob", ["programming", "git", "testing"])
    carol = RoleBasedAgent("Carol", ["data_analysis", "SQL", "python"])
    
    for agent in [alice, bob, carol]:
        pattern.register_agent(agent)
    
    # Assign roles
    print("\n3. Assigning roles...")
    pattern.assign_role_to_agent("Alice", "admin")
    pattern.assign_role_to_agent("Alice", "developer")  # Alice has multiple roles
    pattern.assign_role_to_agent("Bob", "developer")
    pattern.assign_role_to_agent("Bob", "admin")  # Should fail - Bob not qualified
    pattern.assign_role_to_agent("Carol", "analyst")
    
    # Execute tasks
    print("\n4. Executing tasks with role-based permissions...")
    
    pattern.execute_task("Alice", "Configure firewall rules", "system", "write")
    pattern.execute_task("Bob", "Deploy to production", "production", "execute")  # Should fail
    pattern.execute_task("Bob", "Implement new feature", "codebase", "write")
    pattern.execute_task("Carol", "Generate quarterly report", "reports", "write")
    pattern.execute_task("Carol", "Delete user account", "users", "delete")  # Should fail
    
    # Role matrix
    print("\n5. Role Assignment Matrix:")
    matrix = pattern.get_role_matrix()
    for agent_name, roles in matrix.items():
        print(f"   {agent_name}: {', '.join(roles)}")
    
    # Summary
    print("\n6. System Summary:")
    summary = pattern.run("Enterprise role-based access control")
    print(f"   Total Roles: {summary['total_roles']}")
    print(f"   Total Agents: {summary['total_agents']}")
    print(f"   Role Assignments: {summary['total_assignments']}")
    print(f"   Active: {summary['active_assignments']}")
    
    print("\n✓ Role-based pattern enforced permissions and responsibilities!")

    

Agentic Architecture Pattern: Role Based

Pattern 40: 40 Role Based – Line-by-Line Explanation

Overview

Pattern 40: Role-Based Pattern

Agents assigned specific roles with defined responsibilities and permissions. Roles determine what tasks agents can perform and what resources they can access.


Code Structure Analysis

File Information

  • Pattern Number: 40
  • Pattern Name: 40 Role Based
  • File Path: patterns\organizational\40_role_based.py
  • Total Lines: 278

Detailed Code Explanation

Module Docstring

"""
Pattern 40: Role-Based Pattern

Agents assigned specific roles with defined responsibilities and permissions.
Roles determine what tasks agents can perform and what resources they can access.
"""

Explanation: This module docstring describes the purpose and key features of the 40 Role Based pattern.


Imports Section

from typing import Dict, Any, List, Optional, Set
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI  # First 20 imports shown

Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional, Set: Type hints for better code documentation – from dataclasses import dataclass, field: Data class decorators for clean data structures – from datetime import datetime: Date and time utilities – from enum import Enum: Enumeration support for fixed sets of values – from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration


Classes

Permission (Line 17)

Description: Permission granted to a role.

Role (Line 26)

Description: Role with responsibilities and permissions.

RoleAssignment (Line 37)

Description: Assignment of role to agent.

RoleBasedAgent (Line 45)

Description: Agent with role-based capabilities.

Methods:

__init__ (Line 48)
def __init__(self, name, skills, model_name):
    """No method docstring."""

Purpose: No method docstring.

Parameters: – self: Instance reference – name: Identifier or label – skills: Parameter for skills – model_name: LLM model to use (e.g., “gpt-4”)

assign_role (Line 54)
def assign_role(self, role):
    """Assign role to agent if qualified."""

Purpose: Assign role to agent if qualified.

Parameters: – self: Instance reference – role: Parameter for role

has_permission (Line 64)
def has_permission(self, resource, action):
    """Check if agent has permission for action on resource."""

Purpose: Check if agent has permission for action on resource.

Parameters: – self: Instance reference – resource: Parameter for resource – action: Parameter for action

perform_task (Line 72)
def perform_task(self, task, resource, action):
    """Perform task if agent has permission."""

Purpose: Perform task if agent has permission.

Parameters: – self: Instance reference – task: Parameter for task – resource: Parameter for resource – action: Parameter for action

RoleBasedPattern (Line 113)

Description: Role-Based Pattern – Role-based access control and task assignment.

Agents are assigned roles that define their responsibilities and permissions. Tasks are performed based on role capabilities and access rights.

Methods:

__init__ (Line 121)
def __init__(self):
    """No method docstring."""

Purpose: No method docstring.

Parameters: – self: Instance reference

define_role (Line 126)
def define_role(self, role):
    """Define a role in the system."""

Purpose: Define a role in the system.

Parameters: – self: Instance reference – role: Parameter for role

register_agent (Line 130)
def register_agent(self, agent):
    """Register agent in the system."""

Purpose: Register agent in the system.

Parameters: – self: Instance reference – agent: Parameter for agent

assign_role_to_agent (Line 134)
def assign_role_to_agent(self, agent_name, role_id):
    """Assign role to agent."""

Purpose: Assign role to agent.

Parameters: – self: Instance reference – agent_name: Parameter for agent_name – role_id: Parameter for role_id

execute_task (Line 153)
def execute_task(self, agent_name, task, resource, action):
    """Execute task through agent with role-based permissions."""

Purpose: Execute task through agent with role-based permissions.

Parameters: – self: Instance reference – agent_name: Parameter for agent_name – task: Parameter for task – resource: Parameter for resource – action: Parameter for action

get_role_matrix (Line 168)
def get_role_matrix(self):
    """Get matrix of roles assigned to each agent."""

Purpose: Get matrix of roles assigned to each agent.

Parameters: – self: Instance reference

run (Line 175)
def run(self, scenario):
    """Execute role-based pattern."""

Purpose: Execute role-based pattern.

Parameters: – self: Instance reference – scenario: Parameter for scenario


Design Patterns Used

  • Strategy Pattern: Different execution strategies for various scenarios
  • State Pattern: Managing different states in the workflow
  • Chain of Responsibility: Sequential processing through workflow nodes
  • Observer Pattern: Tracking and monitoring pattern execution
  • Factory Pattern: Creating instances with proper configuration

Usage Example

# Initialize the pattern
pattern = Permission(name="example", model_name="gpt-4")

# Configure and execute
result = pattern.execute(data={"key": "value"})

# Check results
print(result)

Key Concepts

  • LLM Integration: Uses LangChain/OpenAI for intelligent decision-making
  • Workflow Orchestration: LangGraph manages execution flow through nodes
  • State Management: TypedDict defines workflow state structure
  • Error Handling: Comprehensive error handling and fallback mechanisms
  • Extensibility: Designed for easy customization and extension

Extension Points

This pattern can be extended by: 1. Adding custom workflow nodes 2. Implementing additional validation logic 3. Integrating with external services 4. Customizing LLM prompts and responses 5. Adding monitoring and logging capabilities

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *