Agentic Architecture Pattern: Matrix Organization

Written by

in


    """
Pattern 33: Matrix Organization Pattern

Agents report to both functional managers and project managers simultaneously.
Dual reporting structure balances functional expertise with project needs.
"""

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


class ManagerType(Enum):
    FUNCTIONAL = "functional"
    PROJECT = "project"


@dataclass
class MatrixAgent:
    """Agent with dual reporting structure."""
    name: str
    functional_area: str  # e.g., Engineering, Design, Marketing
    functional_manager: Optional[str] = None
    projects: List[str] = field(default_factory=list)
    project_managers: List[str] = field(default_factory=list)
    tasks: List[Dict[str, Any]] = field(default_factory=list)


@dataclass
class Manager:
    """Manager in matrix organization."""
    name: str
    manager_type: ManagerType
    area: str  # Functional area or Project name
    direct_reports: Set[str] = field(default_factory=set)


@dataclass
class ConflictResolution:
    """Conflict between functional and project priorities."""
    agent_name: str
    functional_priority: str
    project_priority: str
    resolution: Optional[str] = None
    timestamp: datetime = field(default_factory=datetime.now)


class MatrixOrganizationPattern:
    """
    Matrix Organization Pattern - Dual reporting structure.
    
    Features:
    - Functional managers (expertise areas)
    - Project managers (initiatives)
    - Agents report to both
    - Priority conflict resolution
    - Resource balancing
    """
    
    def __init__(self, model_name: str = "gpt-4"):
        self.llm = ChatOpenAI(model=model_name, temperature=0.7)
        self.agents: Dict[str, MatrixAgent] = {}
        self.functional_managers: Dict[str, Manager] = {}
        self.project_managers: Dict[str, Manager] = {}
        self.conflicts: List[ConflictResolution] = []
    
    def add_functional_manager(self, name: str, area: str):
        """Add a functional manager."""
        manager = Manager(name, ManagerType.FUNCTIONAL, area)
        self.functional_managers[name] = manager
        print(f"✓ Added functional manager: {name} ({area})")
    
    def add_project_manager(self, name: str, project: str):
        """Add a project manager."""
        manager = Manager(name, ManagerType.PROJECT, project)
        self.project_managers[name] = manager
        print(f"✓ Added project manager: {name} (Project: {project})")
    
    def add_agent(self, agent: MatrixAgent):
        """Add an agent with functional assignment."""
        self.agents[agent.name] = agent
        
        # Assign to functional manager
        for fm_name, fm in self.functional_managers.items():
            if fm.area == agent.functional_area:
                agent.functional_manager = fm_name
                fm.direct_reports.add(agent.name)
                break
        
        print(f"✓ Added agent: {agent.name} ({agent.functional_area}) → "
              f"Functional Manager: {agent.functional_manager}")
    
    def assign_to_project(self, agent_name: str, project_name: str, 
                          project_manager_name: str):
        """Assign agent to a project with project manager."""
        if agent_name in self.agents and project_manager_name in self.project_managers:
            agent = self.agents[agent_name]
            pm = self.project_managers[project_manager_name]
            
            agent.projects.append(project_name)
            agent.project_managers.append(project_manager_name)
            pm.direct_reports.add(agent_name)
            
            print(f"✓ {agent_name} assigned to project '{project_name}' → PM: {project_manager_name}")
    
    def assign_task(self, agent_name: str, task: str, source_manager: str, 
                    manager_type: ManagerType) -> Dict[str, Any]:
        """Assign task from either functional or project manager."""
        if agent_name not in self.agents:
            return {"success": False, "error": "Agent not found"}
        
        agent = self.agents[agent_name]
        task_info = {
            "task": task,
            "source_manager": source_manager,
            "manager_type": manager_type.value,
            "assigned_at": datetime.now()
        }
        agent.tasks.append(task_info)
        
        return {"success": True, "agent": agent_name, "task": task}
    
    def resolve_priority_conflict(self, agent_name: str, functional_task: str, 
                                   project_task: str) -> ConflictResolution:
        """Resolve conflict between functional and project priorities."""
        if agent_name not in self.agents:
            return None
        
        agent = self.agents[agent_name]
        conflict = ConflictResolution(
            agent_name=agent_name,
            functional_priority=functional_task,
            project_priority=project_task
        )
        
        # Use LLM to resolve conflict
        prompt = ChatPromptTemplate.from_messages([
            ("system", f"You are resolving a priority conflict for {agent_name}, "
                      f"who works in {agent.functional_area}. "
                      f"They report to both a functional manager and project managers. "
                      f"Provide a balanced resolution that considers both priorities."),
            ("human", f"Functional Manager Priority: {functional_task}\n"
                     f"Project Manager Priority: {project_task}\n\n"
                     f"Resolution:")
        ])
        
        chain = prompt | self.llm
        response = chain.invoke({})
        conflict.resolution = response.content.strip()
        
        self.conflicts.append(conflict)
        return conflict
    
    def get_agent_workload(self, agent_name: str) -> Dict[str, Any]:
        """Get agent's workload across all dimensions."""
        if agent_name not in self.agents:
            return {}
        
        agent = self.agents[agent_name]
        return {
            "agent": agent_name,
            "functional_area": agent.functional_area,
            "functional_manager": agent.functional_manager,
            "active_projects": len(agent.projects),
            "project_managers": agent.project_managers,
            "total_tasks": len(agent.tasks),
            "tasks_by_manager_type": {
                "functional": sum(1 for t in agent.tasks if t["manager_type"] == "functional"),
                "project": sum(1 for t in agent.tasks if t["manager_type"] == "project")
            }
        }
    
    def get_manager_team(self, manager_name: str) -> Dict[str, Any]:
        """Get team reporting to a manager."""
        if manager_name in self.functional_managers:
            manager = self.functional_managers[manager_name]
        elif manager_name in self.project_managers:
            manager = self.project_managers[manager_name]
        else:
            return {}
        
        return {
            "manager": manager_name,
            "type": manager.manager_type.value,
            "area": manager.area,
            "direct_reports": list(manager.direct_reports)
        }
    
    def run(self, scenario: str) -> Dict[str, Any]:
        """Execute matrix organization scenario."""
        return {
            "pattern": "Matrix Organization",
            "scenario": scenario,
            "agents": len(self.agents),
            "functional_managers": len(self.functional_managers),
            "project_managers": len(self.project_managers),
            "conflicts_resolved": len(self.conflicts)
        }


# Example usage
if __name__ == "__main__":
    print("=== Matrix Organization Pattern Demo ===\n")
    
    org = MatrixOrganizationPattern()
    
    # Add functional managers
    print("--- Functional Managers ---")
    org.add_functional_manager("Sarah", "Engineering")
    org.add_functional_manager("Mike", "Design")
    org.add_functional_manager("Lisa", "Data Science")
    
    # Add project managers
    print("\n--- Project Managers ---")
    org.add_project_manager("Tom", "Mobile App Launch")
    org.add_project_manager("Jane", "AI Integration")
    
    # Add agents
    print("\n--- Agents (Dual Reporting) ---")
    agents = [
        MatrixAgent("Alice", "Engineering"),
        MatrixAgent("Bob", "Design"),
        MatrixAgent("Carol", "Data Science"),
        MatrixAgent("David", "Engineering")
    ]
    
    for agent in agents:
        org.add_agent(agent)
    
    # Assign agents to projects
    print("\n--- Project Assignments ---")
    org.assign_to_project("Alice", "Mobile App Launch", "Tom")
    org.assign_to_project("Bob", "Mobile App Launch", "Tom")
    org.assign_to_project("Carol", "AI Integration", "Jane")
    org.assign_to_project("David", "AI Integration", "Jane")
    
    # Assign tasks from both types of managers
    print("\n--- Task Assignments ---")
    org.assign_task("Alice", "Code review for team", "Sarah", ManagerType.FUNCTIONAL)
    org.assign_task("Alice", "Build login feature", "Tom", ManagerType.PROJECT)
    org.assign_task("Carol", "Train ML model", "Jane", ManagerType.PROJECT)
    org.assign_task("Carol", "Mentor junior analysts", "Lisa", ManagerType.FUNCTIONAL)
    
    # Resolve priority conflict
    print("\n--- Priority Conflict Resolution ---")
    conflict = org.resolve_priority_conflict(
        "Alice",
        "Lead technical training session (Functional Manager)",
        "Complete critical app release (Project Manager)"
    )
    print(f"Agent: {conflict.agent_name}")
    print(f"Functional: {conflict.functional_priority}")
    print(f"Project: {conflict.project_priority}")
    print(f"Resolution: {conflict.resolution}")
    
    # Show agent workload
    print("\n--- Agent Workload ---")
    for agent_name in ["Alice", "Carol"]:
        workload = org.get_agent_workload(agent_name)
        print(f"\n{agent_name}:")
        print(f"  Functional Area: {workload['functional_area']}")
        print(f"  Functional Manager: {workload['functional_manager']}")
        print(f"  Active Projects: {workload['active_projects']}")
        print(f"  Project Managers: {', '.join(workload['project_managers'])}")
        print(f"  Total Tasks: {workload['total_tasks']}")
        print(f"  Tasks by Type: Functional={workload['tasks_by_manager_type']['functional']}, "
              f"Project={workload['tasks_by_manager_type']['project']}")
    
    # Show manager teams
    print("\n--- Manager Teams ---")
    for manager_name in ["Sarah", "Tom"]:
        team = org.get_manager_team(manager_name)
        print(f"\n{manager_name} ({team['type']} - {team['area']}):")
        print(f"  Reports: {', '.join(team['direct_reports'])}")
    
    print("\n--- Summary ---")
    result = org.run("Dual reporting structure demo")
    print(f"Pattern: {result['pattern']}")
    print(f"Total Agents: {result['agents']}")
    print(f"Functional Managers: {result['functional_managers']}")
    print(f"Project Managers: {result['project_managers']}")
    print(f"Conflicts Resolved: {result['conflicts_resolved']}")

    

Agentic Architecture Pattern: Matrix Organization

Pattern 33: 33 Matrix Organization – Line-by-Line Explanation

Overview

Pattern 33: Matrix Organization Pattern

Agents report to both functional managers and project managers simultaneously. Dual reporting structure balances functional expertise with project needs.


Code Structure Analysis

File Information

  • Pattern Number: 33
  • Pattern Name: 33 Matrix Organization
  • File Path: patterns\organizational\33_matrix_organization.py
  • Total Lines: 286

Detailed Code Explanation

Module Docstring

"""
Pattern 33: Matrix Organization Pattern

Agents report to both functional managers and project managers simultaneously.
Dual reporting structure balances functional expertise with project needs.
"""

Explanation: This module docstring describes the purpose and key features of the 33 Matrix Organization 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


Enumerations

ManagerType (Line 16)

class ManagerType(Enum):
    FUNCTIONAL
    PROJECT

Purpose: No enum docstring.

Values: – FUNCTIONAL: Represents functional – PROJECT: Represents project


Classes

ManagerType (Line 16)

Description: No class docstring.

MatrixAgent (Line 22)

Description: Agent with dual reporting structure.

Manager (Line 33)

Description: Manager in matrix organization.

ConflictResolution (Line 42)

Description: Conflict between functional and project priorities.

MatrixOrganizationPattern (Line 51)

Description: Matrix Organization Pattern – Dual reporting structure.

Features: – Functional managers (expertise areas) – Project managers (initiatives) – Agents report to both – Priority conflict resolution – Resource balancing

Methods:

__init__ (Line 63)
def __init__(self, model_name):
    """No method docstring."""

Purpose: No method docstring.

Parameters: – self: Instance reference – model_name: LLM model to use (e.g., “gpt-4”)

add_functional_manager (Line 70)
def add_functional_manager(self, name, area):
    """Add a functional manager."""

Purpose: Add a functional manager.

Parameters: – self: Instance reference – name: Identifier or label – area: Parameter for area

add_project_manager (Line 76)
def add_project_manager(self, name, project):
    """Add a project manager."""

Purpose: Add a project manager.

Parameters: – self: Instance reference – name: Identifier or label – project: Parameter for project

add_agent (Line 82)
def add_agent(self, agent):
    """Add an agent with functional assignment."""

Purpose: Add an agent with functional assignment.

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

assign_to_project (Line 96)
def assign_to_project(self, agent_name, project_name, project_manager_name):
    """Assign agent to a project with project manager."""

Purpose: Assign agent to a project with project manager.

Parameters: – self: Instance reference – agent_name: Parameter for agent_name – project_name: Parameter for project_name – project_manager_name: Parameter for project_manager_name

assign_task (Line 109)
def assign_task(self, agent_name, task, source_manager, manager_type):
    """Assign task from either functional or project manager."""

Purpose: Assign task from either functional or project manager.

Parameters: – self: Instance reference – agent_name: Parameter for agent_name – task: Parameter for task – source_manager: Parameter for source_manager – manager_type: Parameter for manager_type

resolve_priority_conflict (Line 126)
def resolve_priority_conflict(self, agent_name, functional_task, project_task):
    """Resolve conflict between functional and project priorities."""

Purpose: Resolve conflict between functional and project priorities.

Parameters: – self: Instance reference – agent_name: Parameter for agent_name – functional_task: Parameter for functional_task – project_task: Parameter for project_task

get_agent_workload (Line 157)
def get_agent_workload(self, agent_name):
    """Get agent's workload across all dimensions."""

Purpose: Get agent’s workload across all dimensions.

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

get_manager_team (Line 176)
def get_manager_team(self, manager_name):
    """Get team reporting to a manager."""

Purpose: Get team reporting to a manager.

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

run (Line 192)
def run(self, scenario):
    """Execute matrix organization scenario."""

Purpose: Execute matrix organization scenario.

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 = ManagerType(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 *